<?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"> <channel> <title>杰哥的{运维，编程，调板子}小笔记</title><description>杰哥的{运维，编程，调板子}小笔记</description><link>https://jia.je/</link><atom:link href="https://jia.je/feed_rss_updated.xml" rel="self" type="application/rss+xml" /> <docs>https://github.com/jiegec/blog-source</docs><language>zh</language> <pubDate>Mon, 09 Mar 2026 06:52:24 -0000</pubDate> <lastBuildDate>Mon, 09 Mar 2026 06:52:24 -0000</lastBuildDate> <ttl>1440</ttl> <generator>MkDocs RSS plugin - v1.17.9</generator> <image> <url>None</url> <title>杰哥的{运维，编程，调板子}小笔记</title> <link>https://jia.je/</link> </image> <item> <title>Nginx 反代导致 SSE 延迟变高的问题与解决方法</title> <category>buffering</category> <category>devops</category> <category>nginx</category> <category>sse</category> <description>&lt;h1 id=&#34;nginx-反代导致-sse-延迟变高的问题与解决方法&#34;&gt;Nginx 反代导致 SSE 延迟变高的问题与解决方法&lt;a class=&#34;headerlink&#34; href=&#34;#nginx-反代导致-sse-延迟变高的问题与解决方法&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;最近有同学遇到这么一个问题：在 Nginx 反代后面搭了一个使用 SSE（Server Sent Events）机制的服务端，但客户端观察到请求延迟比较高，数据批量到达，而不是一行一行地出现。经过排查，发现是 Nginx 的 buffering 机制导致的。本文通过实验复现该问题，并探索了几种解决方法。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;问题复现&#34;&gt;问题复现&lt;a class=&#34;headerlink&#34; href=&#34;#问题复现&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;为了复现这个问题，我 Vibe Coding 了一个测试服务端 &lt;code&gt;server.py&lt;/code&gt;，监听 8080 端口，在 &lt;code&gt;/events&lt;/code&gt; 路径下每秒发送一条 SSE 消息，共发送 5 次：&lt;/p&gt; &lt;div class=&#34;language-python highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-0-1&#34;&gt;&lt;a id=&#34;__codelineno-0-1&#34; name=&#34;__codelineno-0-1&#34; href=&#34;#__codelineno-0-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;ch&#34;&gt;#!/usr/bin/env python3&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-2&#34;&gt;&lt;a id=&#34;__codelineno-0-2&#34; name=&#34;__codelineno-0-2&#34; href=&#34;#__codelineno-0-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;sd&#34;&gt;&amp;quot;&amp;quot;&amp;quot;SSE server that sends 5 messages, one every second.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-3&#34;&gt;&lt;a id=&#34;__codelineno-0-3&#34; name=&#34;__codelineno-0-3&#34; href=&#34;#__codelineno-0-3&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-4&#34;&gt;&lt;a id=&#34;__codelineno-0-4&#34; name=&#34;__codelineno-0-4&#34; href=&#34;#__codelineno-0-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-5&#34;&gt;&lt;a id=&#34;__codelineno-0-5&#34; name=&#34;__codelineno-0-5&#34; href=&#34;#__codelineno-0-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nn&#34;&gt;http.server&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;HTTPServer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;BaseHTTPRequestHandler&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-6&#34;&gt;&lt;a id=&#34;__codelineno-0-6&#34; name=&#34;__codelineno-0-6&#34; href=&#34;#__codelineno-0-6&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-7&#34;&gt;&lt;a id=&#34;__codelineno-0-7&#34; name=&#34;__codelineno-0-7&#34; href=&#34;#__codelineno-0-7&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-8&#34;&gt;&lt;a id=&#34;__codelineno-0-8&#34; name=&#34;__codelineno-0-8&#34; href=&#34;#__codelineno-0-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SSEHandler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BaseHTTPRequestHandler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-9&#34;&gt;&lt;a id=&#34;__codelineno-0-9&#34; name=&#34;__codelineno-0-9&#34; href=&#34;#__codelineno-0-9&#34;&gt;&lt;/a&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;do_GET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-10&#34;&gt;&lt;a id=&#34;__codelineno-0-10&#34; name=&#34;__codelineno-0-10&#34; href=&#34;#__codelineno-0-10&#34;&gt;&lt;/a&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;/events&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-11&#34;&gt;&lt;a id=&#34;__codelineno-0-11&#34; name=&#34;__codelineno-0-11&#34; href=&#34;#__codelineno-0-11&#34;&gt;&lt;/a&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;send_response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-12&#34;&gt;&lt;a id=&#34;__codelineno-0-12&#34; name=&#34;__codelineno-0-12&#34; href=&#34;#__codelineno-0-12&#34;&gt;&lt;/a&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;send_header&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;text/event-stream&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-13&#34;&gt;&lt;a id=&#34;__codelineno-0-13&#34; name=&#34;__codelineno-0-13&#34; href=&#34;#__codelineno-0-13&#34;&gt;&lt;/a&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;end_headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-14&#34;&gt;&lt;a id=&#34;__codelineno-0-14&#34; name=&#34;__codelineno-0-14&#34; href=&#34;#__codelineno-0-14&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-15&#34;&gt;&lt;a id=&#34;__codelineno-0-15&#34; name=&#34;__codelineno-0-15&#34; href=&#34;#__codelineno-0-15&#34;&gt;&lt;/a&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-16&#34;&gt;&lt;a id=&#34;__codelineno-0-16&#34; name=&#34;__codelineno-0-16&#34; href=&#34;#__codelineno-0-16&#34;&gt;&lt;/a&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;data: Message &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; at &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n\n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-17&#34;&gt;&lt;a id=&#34;__codelineno-0-17&#34; name=&#34;__codelineno-0-17&#34; href=&#34;#__codelineno-0-17&#34;&gt;&lt;/a&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wfile&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;encode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-18&#34;&gt;&lt;a id=&#34;__codelineno-0-18&#34; name=&#34;__codelineno-0-18&#34; href=&#34;#__codelineno-0-18&#34;&gt;&lt;/a&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wfile&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;flush&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-19&#34;&gt;&lt;a id=&#34;__codelineno-0-19&#34; name=&#34;__codelineno-0-19&#34; href=&#34;#__codelineno-0-19&#34;&gt;&lt;/a&gt; &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-20&#34;&gt;&lt;a id=&#34;__codelineno-0-20&#34; name=&#34;__codelineno-0-20&#34; href=&#34;#__codelineno-0-20&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-21&#34;&gt;&lt;a id=&#34;__codelineno-0-21&#34; name=&#34;__codelineno-0-21&#34; href=&#34;#__codelineno-0-21&#34;&gt;&lt;/a&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wfile&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-22&#34;&gt;&lt;a id=&#34;__codelineno-0-22&#34; name=&#34;__codelineno-0-22&#34; href=&#34;#__codelineno-0-22&#34;&gt;&lt;/a&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-23&#34;&gt;&lt;a id=&#34;__codelineno-0-23&#34; name=&#34;__codelineno-0-23&#34; href=&#34;#__codelineno-0-23&#34;&gt;&lt;/a&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;send_response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;404&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-24&#34;&gt;&lt;a id=&#34;__codelineno-0-24&#34; name=&#34;__codelineno-0-24&#34; href=&#34;#__codelineno-0-24&#34;&gt;&lt;/a&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;end_headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-25&#34;&gt;&lt;a id=&#34;__codelineno-0-25&#34; name=&#34;__codelineno-0-25&#34; href=&#34;#__codelineno-0-25&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-26&#34;&gt;&lt;a id=&#34;__codelineno-0-26&#34; name=&#34;__codelineno-0-26&#34; href=&#34;#__codelineno-0-26&#34;&gt;&lt;/a&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;log_message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-27&#34;&gt;&lt;a id=&#34;__codelineno-0-27&#34; name=&#34;__codelineno-0-27&#34; href=&#34;#__codelineno-0-27&#34;&gt;&lt;/a&gt; &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;[&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;strftime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;%Y-%m-&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%d&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt; %H:%M:%S&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;] &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-28&#34;&gt;&lt;a id=&#34;__codelineno-0-28&#34; name=&#34;__codelineno-0-28&#34; href=&#34;#__codelineno-0-28&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-29&#34;&gt;&lt;a id=&#34;__codelineno-0-29&#34; name=&#34;__codelineno-0-29&#34; href=&#34;#__codelineno-0-29&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-30&#34;&gt;&lt;a id=&#34;__codelineno-0-30&#34; name=&#34;__codelineno-0-30&#34; href=&#34;#__codelineno-0-30&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-31&#34;&gt;&lt;a id=&#34;__codelineno-0-31&#34; name=&#34;__codelineno-0-31&#34; href=&#34;#__codelineno-0-31&#34;&gt;&lt;/a&gt; &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;HTTPServer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;0.0.0.0&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8080&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SSEHandler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-32&#34;&gt;&lt;a id=&#34;__codelineno-0-32&#34; name=&#34;__codelineno-0-32&#34; href=&#34;#__codelineno-0-32&#34;&gt;&lt;/a&gt; &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;SSE server starting on http://0.0.0.0:8080&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-33&#34;&gt;&lt;a id=&#34;__codelineno-0-33&#34; name=&#34;__codelineno-0-33&#34; href=&#34;#__codelineno-0-33&#34;&gt;&lt;/a&gt; &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;serve_forever&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;启动服务端，使用 curl 访问 &lt;code&gt;localhost:8080/events&lt;/code&gt;，可以看到每秒输出一条消息，没有延迟。接下来在 docker compose 里启动 Nginx，配置如下：&lt;/p&gt; &lt;div class=&#34;language-yaml highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-1-1&#34;&gt;&lt;a id=&#34;__codelineno-1-1&#34; name=&#34;__codelineno-1-1&#34; href=&#34;#__codelineno-1-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nt&#34;&gt;services&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-2&#34;&gt;&lt;a id=&#34;__codelineno-1-2&#34; name=&#34;__codelineno-1-2&#34; href=&#34;#__codelineno-1-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;nginx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-3&#34;&gt;&lt;a id=&#34;__codelineno-1-3&#34; name=&#34;__codelineno-1-3&#34; href=&#34;#__codelineno-1-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l l-Scalar l-Scalar-Plain&#34;&gt;nginx:alpine&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-4&#34;&gt;&lt;a id=&#34;__codelineno-1-4&#34; name=&#34;__codelineno-1-4&#34; href=&#34;#__codelineno-1-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ports&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-5&#34;&gt;&lt;a id=&#34;__codelineno-1-5&#34; name=&#34;__codelineno-1-5&#34; href=&#34;#__codelineno-1-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p p-Indicator&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;80:80&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-6&#34;&gt;&lt;a id=&#34;__codelineno-1-6&#34; name=&#34;__codelineno-1-6&#34; href=&#34;#__codelineno-1-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;volumes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-7&#34;&gt;&lt;a id=&#34;__codelineno-1-7&#34; name=&#34;__codelineno-1-7&#34; href=&#34;#__codelineno-1-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p p-Indicator&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l l-Scalar l-Scalar-Plain&#34;&gt;./nginx.conf:/etc/nginx/nginx.conf:ro&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-8&#34;&gt;&lt;a id=&#34;__codelineno-1-8&#34; name=&#34;__codelineno-1-8&#34; href=&#34;#__codelineno-1-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;depends_on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-9&#34;&gt;&lt;a id=&#34;__codelineno-1-9&#34; name=&#34;__codelineno-1-9&#34; href=&#34;#__codelineno-1-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p p-Indicator&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l l-Scalar l-Scalar-Plain&#34;&gt;sse-server&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-10&#34;&gt;&lt;a id=&#34;__codelineno-1-10&#34; name=&#34;__codelineno-1-10&#34; href=&#34;#__codelineno-1-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;networks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-11&#34;&gt;&lt;a id=&#34;__codelineno-1-11&#34; name=&#34;__codelineno-1-11&#34; href=&#34;#__codelineno-1-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p p-Indicator&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l l-Scalar l-Scalar-Plain&#34;&gt;sse-network&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-12&#34;&gt;&lt;a id=&#34;__codelineno-1-12&#34; name=&#34;__codelineno-1-12&#34; href=&#34;#__codelineno-1-12&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-13&#34;&gt;&lt;a id=&#34;__codelineno-1-13&#34; name=&#34;__codelineno-1-13&#34; href=&#34;#__codelineno-1-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;sse-server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-14&#34;&gt;&lt;a id=&#34;__codelineno-1-14&#34; name=&#34;__codelineno-1-14&#34; href=&#34;#__codelineno-1-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l l-Scalar l-Scalar-Plain&#34;&gt;python:3.11-slim&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-15&#34;&gt;&lt;a id=&#34;__codelineno-1-15&#34; name=&#34;__codelineno-1-15&#34; href=&#34;#__codelineno-1-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;command&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l l-Scalar l-Scalar-Plain&#34;&gt;python /app/server.py&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-16&#34;&gt;&lt;a id=&#34;__codelineno-1-16&#34; name=&#34;__codelineno-1-16&#34; href=&#34;#__codelineno-1-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;volumes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-17&#34;&gt;&lt;a id=&#34;__codelineno-1-17&#34; name=&#34;__codelineno-1-17&#34; href=&#34;#__codelineno-1-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p p-Indicator&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l l-Scalar l-Scalar-Plain&#34;&gt;./server.py:/app/server.py:ro&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-18&#34;&gt;&lt;a id=&#34;__codelineno-1-18&#34; name=&#34;__codelineno-1-18&#34; href=&#34;#__codelineno-1-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ports&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-19&#34;&gt;&lt;a id=&#34;__codelineno-1-19&#34; name=&#34;__codelineno-1-19&#34; href=&#34;#__codelineno-1-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p p-Indicator&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;8080:8080&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-20&#34;&gt;&lt;a id=&#34;__codelineno-1-20&#34; name=&#34;__codelineno-1-20&#34; href=&#34;#__codelineno-1-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;networks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-21&#34;&gt;&lt;a id=&#34;__codelineno-1-21&#34; name=&#34;__codelineno-1-21&#34; href=&#34;#__codelineno-1-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p p-Indicator&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l l-Scalar l-Scalar-Plain&#34;&gt;sse-network&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-22&#34;&gt;&lt;a id=&#34;__codelineno-1-22&#34; name=&#34;__codelineno-1-22&#34; href=&#34;#__codelineno-1-22&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-23&#34;&gt;&lt;a id=&#34;__codelineno-1-23&#34; name=&#34;__codelineno-1-23&#34; href=&#34;#__codelineno-1-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nt&#34;&gt;networks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-24&#34;&gt;&lt;a id=&#34;__codelineno-1-24&#34; name=&#34;__codelineno-1-24&#34; href=&#34;#__codelineno-1-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;sse-network&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-25&#34;&gt;&lt;a id=&#34;__codelineno-1-25&#34; name=&#34;__codelineno-1-25&#34; href=&#34;#__codelineno-1-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;driver&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l l-Scalar l-Scalar-Plain&#34;&gt;bridge&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;接着是 nginx 的配置：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-2-1&#34;&gt;&lt;a id=&#34;__codelineno-2-1&#34; name=&#34;__codelineno-2-1&#34; href=&#34;#__codelineno-2-1&#34;&gt;&lt;/a&gt;events { &lt;/span&gt;&lt;span id=&#34;__span-2-2&#34;&gt;&lt;a id=&#34;__codelineno-2-2&#34; name=&#34;__codelineno-2-2&#34; href=&#34;#__codelineno-2-2&#34;&gt;&lt;/a&gt; worker_connections 1024; &lt;/span&gt;&lt;span id=&#34;__span-2-3&#34;&gt;&lt;a id=&#34;__codelineno-2-3&#34; name=&#34;__codelineno-2-3&#34; href=&#34;#__codelineno-2-3&#34;&gt;&lt;/a&gt;} &lt;/span&gt;&lt;span id=&#34;__span-2-4&#34;&gt;&lt;a id=&#34;__codelineno-2-4&#34; name=&#34;__codelineno-2-4&#34; href=&#34;#__codelineno-2-4&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-5&#34;&gt;&lt;a id=&#34;__codelineno-2-5&#34; name=&#34;__codelineno-2-5&#34; href=&#34;#__codelineno-2-5&#34;&gt;&lt;/a&gt;http { &lt;/span&gt;&lt;span id=&#34;__span-2-6&#34;&gt;&lt;a id=&#34;__codelineno-2-6&#34; name=&#34;__codelineno-2-6&#34; href=&#34;#__codelineno-2-6&#34;&gt;&lt;/a&gt; server { &lt;/span&gt;&lt;span id=&#34;__span-2-7&#34;&gt;&lt;a id=&#34;__codelineno-2-7&#34; name=&#34;__codelineno-2-7&#34; href=&#34;#__codelineno-2-7&#34;&gt;&lt;/a&gt; listen 80; &lt;/span&gt;&lt;span id=&#34;__span-2-8&#34;&gt;&lt;a id=&#34;__codelineno-2-8&#34; name=&#34;__codelineno-2-8&#34; href=&#34;#__codelineno-2-8&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-9&#34;&gt;&lt;a id=&#34;__codelineno-2-9&#34; name=&#34;__codelineno-2-9&#34; href=&#34;#__codelineno-2-9&#34;&gt;&lt;/a&gt; location /events { &lt;/span&gt;&lt;span id=&#34;__span-2-10&#34;&gt;&lt;a id=&#34;__codelineno-2-10&#34; name=&#34;__codelineno-2-10&#34; href=&#34;#__codelineno-2-10&#34;&gt;&lt;/a&gt; proxy_pass http://sse-server:8080; &lt;/span&gt;&lt;span id=&#34;__span-2-11&#34;&gt;&lt;a id=&#34;__codelineno-2-11&#34; name=&#34;__codelineno-2-11&#34; href=&#34;#__codelineno-2-11&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-12&#34;&gt;&lt;a id=&#34;__codelineno-2-12&#34; name=&#34;__codelineno-2-12&#34; href=&#34;#__codelineno-2-12&#34;&gt;&lt;/a&gt; # Add additional config later here &lt;/span&gt;&lt;span id=&#34;__span-2-13&#34;&gt;&lt;a id=&#34;__codelineno-2-13&#34; name=&#34;__codelineno-2-13&#34; href=&#34;#__codelineno-2-13&#34;&gt;&lt;/a&gt; } &lt;/span&gt;&lt;span id=&#34;__span-2-14&#34;&gt;&lt;a id=&#34;__codelineno-2-14&#34; name=&#34;__codelineno-2-14&#34; href=&#34;#__codelineno-2-14&#34;&gt;&lt;/a&gt; } &lt;/span&gt;&lt;span id=&#34;__span-2-15&#34;&gt;&lt;a id=&#34;__codelineno-2-15&#34; name=&#34;__codelineno-2-15&#34; href=&#34;#__codelineno-2-15&#34;&gt;&lt;/a&gt;} &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;启动 docker compose，用 curl 分别访问 80 和 8080 端口的 &lt;code&gt;/events&lt;/code&gt;，观察到以下现象：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;通过 80 端口访问 nginx：5 秒后一次性输出所有 data&lt;/li&gt; &lt;li&gt;通过 8080 端口直接访问 server：每秒输出一条 data&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;这说明确实是 nginx 导致的。接下来测试几种解决方法。&lt;/p&gt; &lt;h2 id=&#34;解决方法&#34;&gt;解决方法&lt;a class=&#34;headerlink&#34; href=&#34;#解决方法&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;首先，查阅 nginx 的&lt;a href=&#34;https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering&#34;&gt;文档&lt;/a&gt;，可以看到它的描述：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-3-1&#34;&gt;&lt;a id=&#34;__codelineno-3-1&#34; name=&#34;__codelineno-3-1&#34; href=&#34;#__codelineno-3-1&#34;&gt;&lt;/a&gt;Syntax: proxy_buffering on | off; &lt;/span&gt;&lt;span id=&#34;__span-3-2&#34;&gt;&lt;a id=&#34;__codelineno-3-2&#34; name=&#34;__codelineno-3-2&#34; href=&#34;#__codelineno-3-2&#34;&gt;&lt;/a&gt;Default: proxy_buffering on; &lt;/span&gt;&lt;span id=&#34;__span-3-3&#34;&gt;&lt;a id=&#34;__codelineno-3-3&#34; name=&#34;__codelineno-3-3&#34; href=&#34;#__codelineno-3-3&#34;&gt;&lt;/a&gt;Context: http, server, location &lt;/span&gt;&lt;span id=&#34;__span-3-4&#34;&gt;&lt;a id=&#34;__codelineno-3-4&#34; name=&#34;__codelineno-3-4&#34; href=&#34;#__codelineno-3-4&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-5&#34;&gt;&lt;a id=&#34;__codelineno-3-5&#34; name=&#34;__codelineno-3-5&#34; href=&#34;#__codelineno-3-5&#34;&gt;&lt;/a&gt;Enables or disables buffering of responses from the proxied server. &lt;/span&gt;&lt;span id=&#34;__span-3-6&#34;&gt;&lt;a id=&#34;__codelineno-3-6&#34; name=&#34;__codelineno-3-6&#34; href=&#34;#__codelineno-3-6&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-7&#34;&gt;&lt;a id=&#34;__codelineno-3-7&#34; name=&#34;__codelineno-3-7&#34; href=&#34;#__codelineno-3-7&#34;&gt;&lt;/a&gt;When buffering is enabled, nginx receives a response from the proxied server as soon as possible, saving it into the buffers set by the proxy_buffer_size and proxy_buffers directives. If the whole response does not fit into memory, a part of it can be saved to a temporary file on the disk. Writing to temporary files is controlled by the proxy_max_temp_file_size and proxy_temp_file_write_size directives. &lt;/span&gt;&lt;span id=&#34;__span-3-8&#34;&gt;&lt;a id=&#34;__codelineno-3-8&#34; name=&#34;__codelineno-3-8&#34; href=&#34;#__codelineno-3-8&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-9&#34;&gt;&lt;a id=&#34;__codelineno-3-9&#34; name=&#34;__codelineno-3-9&#34; href=&#34;#__codelineno-3-9&#34;&gt;&lt;/a&gt;When buffering is disabled, the response is passed to a client synchronously, immediately as it is received. nginx will not try to read the whole response from the proxied server. The maximum size of the data that nginx can receive from the server at a time is set by the proxy_buffer_size directive. &lt;/span&gt;&lt;span id=&#34;__span-3-10&#34;&gt;&lt;a id=&#34;__codelineno-3-10&#34; name=&#34;__codelineno-3-10&#34; href=&#34;#__codelineno-3-10&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-11&#34;&gt;&lt;a id=&#34;__codelineno-3-11&#34; name=&#34;__codelineno-3-11&#34; href=&#34;#__codelineno-3-11&#34;&gt;&lt;/a&gt;Buffering can also be enabled or disabled by passing “yes” or “no” in the “X-Accel-Buffering” response header field. This capability can be disabled using the proxy_ignore_headers directive. &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;根据描述，可以想到一些可能的解决方法：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Nginx 配置添加 &lt;code&gt;proxy_buffering off;&lt;/code&gt;：工作&lt;/li&gt; &lt;li&gt;服务端在响应的 header 里添加 &lt;code&gt;X-Accel-Buffering: no&lt;/code&gt;（&lt;code&gt;self.send_header(&#34;X-Accel-Buffering&#34;, &#34;no&#34;)&lt;/code&gt;）：工作&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;在一开头的场景里，由于中间的 Nginx 配置改起来比较麻烦，最后就用了第二种方法。回想起来，一开始思路走偏了，一直在往 cache 方向想，实际上是 buffering 的问题：Nginx 会先从 server 读取一大片数据，攒够了再发给 client，避免来回转发小段数据的开销，但 SSE 又希望有较低的延迟，这就冲突了。&lt;/p&gt; &lt;p&gt;小结一下：排查这类问题要理解 Nginx 的工作机制，找错方向可能很难定位；同时，利用 LLM 快速构建可复现的测试环境，有助于验证假设。&lt;/p&gt;</description> <link>https://jia.je/devops/2026/03/05/nginx-sse-buffering/</link> <pubDate>Thu, 05 Mar 2026 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/devops/2026/03/05/nginx-sse-buffering/</guid> <enclosure url="https://jia.je/assets/images/social/devops/2026/03/05/nginx-sse-buffering.png" type="image/png" length="66830" /> </item> <item> <title>记一次软 RAID1 坏盘的恢复过程</title> <category>devops</category> <category>linux</category> <category>md</category> <category>mdadm</category> <category>raid</category> <category>soft-raid</category> <description>&lt;h1 id=&#34;记一次软-raid1-坏盘的恢复过程&#34;&gt;记一次软 RAID1 坏盘的恢复过程&lt;a class=&#34;headerlink&#34; href=&#34;#记一次软-raid1-坏盘的恢复过程&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;最近遇到一个运维场景，两个 SATA 盘组了一个 RAID1，Linux 的根系统也在上面，启动时能进内核，但是内核一直在报错 &lt;code&gt;link is too slow to respond, please be patient&lt;/code&gt; 以及 &lt;code&gt;COMRESET failed (errno=-16)&lt;/code&gt;。下面记录一下故障排查以及恢复的过程。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;恢复过程&#34;&gt;恢复过程&lt;a class=&#34;headerlink&#34; href=&#34;#恢复过程&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;考虑到 Linux 系统也在 RAID1 上面，所以找了另一台机器，接上两个 SATA 盘，然后观察到，其中一个盘直接无法识别，另一个盘可以正常访问，但它分区表里只有一个分区，参与到了 md 组的 RAID1 当中。遇到盘坏了又是 RAID，第一反应是买一个新盘，然后重建 RAID。但是一通询价，发现最近硬盘价格涨的比较多，所以先尝试如何单盘启动。由于是 UEFI 启动，推测 ESP 在已经坏的那个盘上面，好的盘上并没有 ESP，但它唯一的分区已经占满了整个空间，所以第一步是对 RAID 分区缩容，这就需要：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;首先用 &lt;code&gt;fsck -f /dev/md0 &amp;amp;&amp;amp; resize2fs /dev/md0 newsize&lt;/code&gt; 对根分区进行缩容&lt;/li&gt; &lt;li&gt;用 &lt;code&gt;mdadm --grow --size=newsize /dev/md0&lt;/code&gt; 对 RAID 进行缩容&lt;/li&gt; &lt;li&gt;停止 RAID：&lt;code&gt;mdadm --stop /dev/md0&lt;/code&gt;&lt;/li&gt; &lt;li&gt;重新分区，缩小 RAID 分区大小：&lt;code&gt;cfdisk /dev/sda&lt;/code&gt;&lt;/li&gt; &lt;li&gt;重新启动 RAID，更新 device size：&lt;code&gt;mdadm --assemble --update=devicesize /dev/md0 /dev/sda1&lt;/code&gt;&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;这些步骤完成以后，就可以在空余的空间里建 ESP 分区了：建分区，&lt;code&gt;mkfs.vfat&lt;/code&gt;，挂载到 &lt;code&gt;/mnt/boot/efi&lt;/code&gt;（假设 &lt;code&gt;/dev/sda1&lt;/code&gt; 已经挂载到了 &lt;code&gt;/mnt&lt;/code&gt;），接着 &lt;code&gt;arch-chroot /mnt&lt;/code&gt;（或者手抄 &lt;a href=&#34;https://wiki.archlinux.org/title/Chroot#Using_chroot&#34;&gt;Archlinux Wiki&lt;/a&gt;），进去 &lt;code&gt;grub-install&lt;/code&gt;，修改 &lt;code&gt;/etc/fstab&lt;/code&gt;，重新 &lt;code&gt;update-grub&lt;/code&gt;。&lt;/p&gt; &lt;p&gt;这个过程中，踩了一些小坑，比如：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;重启以后直接进 grub shell，没有菜单显示出来，后来发现是 UEFI 启动项里有之前的旧残留，导致 grub 没有能够正确加载 ESP 里面的 grub.cfg，如果在 grub shell 里手动 source 一下是正常的&lt;/li&gt; &lt;li&gt;如果不更新 device size，那么 assemble 的时候会说 &lt;code&gt;does not have a valid v1.2 superblock&lt;/code&gt; 报错，实际上就是它记录了旧的分区大小，和新的分区大小不匹配，此时要强制修改它&lt;/li&gt; &lt;li&gt;最后买了个新盘，但是不够大：960GB vs 1TB，导致如果要重组 RAID1 还得再缩小一次已有的 RAID1 分区，之前缩小的时候只给 ESP 预留了足够的空间，但分区还不够小到能够在新盘里建一个相同大小的分区&lt;/li&gt; &lt;/ol&gt;</description> <link>https://jia.je/devops/2026/01/21/soft-raid-recovery/</link> <pubDate>Wed, 21 Jan 2026 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/devops/2026/01/21/soft-raid-recovery/</guid> <enclosure url="https://jia.je/assets/images/social/devops/2026/01/21/soft-raid-recovery.png" type="image/png" length="53085" /> </item> <item> <title>IBM POWER9 微架构评测</title> <category>cpu</category> <category>hardware</category> <category>ibm</category> <category>performance</category> <category>power9</category> <category>ppc64le</category> <category>uarch-review</category> <description>&lt;h1 id=&#34;ibm-power9-微架构评测&#34;&gt;IBM POWER9 微架构评测&lt;a class=&#34;headerlink&#34; href=&#34;#ibm-power9-微架构评测&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;继 &lt;a href=&#34;../../15/ibm-power8/&#34;&gt;IBM POWER8&lt;/a&gt; 之后，也来评测一下后续的 IBM POWER9 微架构。IBM POWER9 有 SMT4 和 SMT8 两种版本，我只有 SMT4 版本的测试环境，下列所有评测都是针对 SMT4 版本进行测试。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;官方信息&#34;&gt;官方信息&lt;a class=&#34;headerlink&#34; href=&#34;#官方信息&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;IBM 关于 POWER9 微架构有如下公开信息：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://ieeexplore.ieee.org/document/8409955&#34;&gt;IBM POWER9 processor core&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://ieeexplore.ieee.org/document/7924241&#34;&gt;IBM Power9 Processor Architecture&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;下面分各个模块分别记录官方提供的信息，以及实测的结果。官方信息与实测结果一致的数据会加粗。&lt;/p&gt; &lt;h2 id=&#34;benchmark&#34;&gt;Benchmark&lt;a class=&#34;headerlink&#34; href=&#34;#benchmark&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;IBM POWER9 的性能测试结果见 &lt;a href=&#34;../../../../../benchmark/&#34;&gt;SPEC&lt;/a&gt;。&lt;/p&gt; &lt;h2 id=&#34;前端&#34;&gt;前端&lt;a class=&#34;headerlink&#34; href=&#34;#前端&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;l1-icache&#34;&gt;L1 ICache&lt;a class=&#34;headerlink&#34; href=&#34;#l1-icache&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：&lt;strong&gt;32KB(SMT4)&lt;/strong&gt;/64KB(split into 2 regions, SMT8)&lt;/p&gt; &lt;p&gt;为了测试 L1 ICache 容量，构造一个具有巨大指令 footprint 的循环，由大量的 nop 和最后的分支指令组成。观察在不同 footprint 大小下的 IPC：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power9-fetch-bandwidth.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;测试环境是 SMT4 Core，所以只有 32KB 的容量。超出 L1 ICache 容量后，IPC 从 6 降低到了 4.7。相比 POWER8，容量不变，超出 ICache 容量后的 IPC 提高了。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/fetch_bandwidth_gen.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;取指带宽&#34;&gt;取指带宽&lt;a class=&#34;headerlink&#34; href=&#34;#取指带宽&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：32 bytes/cycle&lt;/p&gt; &lt;p&gt;为了测试实际的 Fetch 宽度，参考 &lt;a href=&#34;https://zhuanlan.zhihu.com/p/720136752&#34;&gt;如何测量真正的取指带宽（I-fetch width） - JamesAslan&lt;/a&gt; 构造了测试。&lt;/p&gt; &lt;p&gt;其原理是当 Fetch 要跨页的时候，由于两个相邻页可能映射到不同的物理地址，如果要支持单周期跨页取指，需要查询两次 ITLB，或者 ITLB 需要把相邻两个页的映射存在一起。这个场景一般比较少，处理器很少会针对这种特殊情况做优化，但也不是没有。经过测试，把循环放在两个页的边界上，发现 IBM POWER9 微架构遇到跨页的取指时确实会拆成两个周期来进行。&lt;/p&gt; &lt;p&gt;在此基础上，构造一个循环，循环的第一条指令放在第一个页的最后四个字节，其余指令放第二个页上，那么每次循环的取指时间，就是一个周期（读取第一个页内的指令）加上第二个页内指令需要 Fetch 的周期数，多的这一个周期就足以把 Fetch 宽度从后端限制中区分开，实验结果如下：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power9-if-width.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;图中蓝线（cross-page）表示的就是上面所述的第一条指令放一个页，其余指令放第二个页的情况，横坐标是第二个页内的指令数，那么一次循环的指令数等于横坐标 +1。纵坐标是运行很多次循环的总 cycle 数除以循环次数，也就是平均每次循环耗费的周期数。可以看到每 8 条指令会多一个周期，因此 IBM POWER9 的前端取指宽度确实是 8 条指令即 32 字节。&lt;/p&gt; &lt;p&gt;为了确认这个瓶颈是由取指造成的，又构造了一组实验，把循环的所有指令都放到一个页中，这个时候 Fetch 不再成为瓶颈（图中 aligned），两个曲线的对比可以明确地得出上述结论。&lt;/p&gt; &lt;p&gt;随着指令数进一步增加，最终瓶颈在每周期执行的 NOP 指令数，因此两条线重合。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/if_width_gen.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;l1-itlb&#34;&gt;L1 ITLB&lt;a class=&#34;headerlink&#34; href=&#34;#l1-itlb&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;为了测试 L1 ITLB 的容量，构造 b 序列，每个 b 在一个单独的页（64KB 的页大小）中，观察 b 的性能：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power9-itlb-size.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到明显的 256 pages 的拐点，对应了 256 entry 的 L1 ITLB。CPI 从 3 升高到了 28。相比 POWER8 的 64-entry L1 ITLB 容量有所提升。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/itlb_size_lib.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;btb-aka-branch-target-address-calculator-btac&#34;&gt;BTB (aka Branch Target Address Calculator, BTAC)&lt;a class=&#34;headerlink&#34; href=&#34;#btb-aka-branch-target-address-calculator-btac&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：1 cycle latency&lt;/p&gt; &lt;h3 id=&#34;return-address-stack&#34;&gt;Return Address Stack&lt;a class=&#34;headerlink&#34; href=&#34;#return-address-stack&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;构造不同深度的调用链，测试每次调用花费的时间，得到如下测试结果：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power9-ras-size.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到 64 的拐点，对应的就是 RAS 的大小。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/ras_size_gen.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;cbp-conditional-branch-predictor&#34;&gt;CBP (Conditional Branch Predictor)&lt;a class=&#34;headerlink&#34; href=&#34;#cbp-conditional-branch-predictor&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：BHT(3 cycle redirect) + TAGE(4 components, 5 cycle redirect), 256-bit LGHB(long global history vector)&lt;/p&gt; &lt;h2 id=&#34;dispatch&#34;&gt;Dispatch&lt;a class=&#34;headerlink&#34; href=&#34;#dispatch&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;官方信息：6 instructions per SMT4, 12 instructions per SMT8&lt;/p&gt; &lt;h2 id=&#34;后端&#34;&gt;后端&lt;a class=&#34;headerlink&#34; href=&#34;#后端&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;rob-aka-ict&#34;&gt;ROB (aka ICT)&lt;a class=&#34;headerlink&#34; href=&#34;#rob-aka-ict&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：&lt;strong&gt;256 entries&lt;/strong&gt; per SMT4 core&lt;/p&gt; &lt;p&gt;把两个独立的 long latency pointer chasing load 放在循环的头和尾，中间用 NOP 填充，当 NOP 填满了 ROB，第二个 pointer chasing load 无法提前执行，导致性能下降。测试结果如下：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power9-rob-size.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;拐点在 256 附近。相比 POWER8 的 &lt;code&gt;28*6=168&lt;/code&gt; 有所提升&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/rob_size_gen.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;issue-queue&#34;&gt;Issue Queue&lt;a class=&#34;headerlink&#34; href=&#34;#issue-queue&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：54 instructions per SMT4 core, 108 instructions per SMT8 core&lt;/p&gt; &lt;h3 id=&#34;l1-dcache&#34;&gt;L1 DCache&lt;a class=&#34;headerlink&#34; href=&#34;#l1-dcache&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：32KB(SMT4)/64KB(SMT8, split into two regions)&lt;/p&gt; &lt;h3 id=&#34;l1-dtlb&#34;&gt;L1 DTLB&lt;a class=&#34;headerlink&#34; href=&#34;#l1-dtlb&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;用类似测 L1 DCache 的方法测试 L1 DTLB 容量，只不过这次 pointer chasing 链的指针分布在不同的 64KB page 上，使得 DTLB 成为瓶颈：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power9-dtlb-size.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到 256 Page 出现了明显的拐点，对应的就是 256 的 L1 DTLB 容量。没有超出 L1 DTLB 容量前，Load to use latency 是 4 cycle。L1 DTLB 容量相比 POWER8 的 48(ST)/96(SMT) 有所提升，和 POWER8 的 256-entry L2 DTLB 容量相同。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/dtlb_size.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;l2-cache&#34;&gt;L2 Cache&lt;a class=&#34;headerlink&#34; href=&#34;#l2-cache&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：8-way 512KB L2 cache&lt;/p&gt; &lt;h3 id=&#34;l3-cache&#34;&gt;L3 Cache&lt;a class=&#34;headerlink&#34; href=&#34;#l3-cache&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：20-way 10MB eDRAM L3 cache per core&lt;/p&gt; &lt;h3 id=&#34;prefetcher&#34;&gt;Prefetcher&lt;a class=&#34;headerlink&#34; href=&#34;#prefetcher&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;参考 &lt;a href=&#34;https://abertschi.ch/blog/2022/prefetching/&#34;&gt;Battling the Prefetcher: Exploring Coffee Lake (Part 1)&lt;/a&gt; 的方式，研究预取器的行为：分配一片内存，把数据从缓存中 flush 掉，再按照特定的访存模式访问，触发预取器，最后测量访问每个缓存行的时间，从而得到预取器预取了哪些缓存行的信息。&lt;/p&gt; &lt;p&gt;首先是连续访问若干个 128B cacheline，观察哪些被预取了进来：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power9-prefetcher-cacheline-1.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;预取的行为相比 POWER8 更加激进：有更多的缓存行被预取到了更近的 L1（或者是 L2？）。&lt;/p&gt; &lt;p&gt;如果是访问了几个分立的缓存行，有时会表现出 Next 3 Line 的行为，但都是到 L3：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power9-prefetcher-cacheline-2.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/prefetcher_cacheline.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt;</description> <link>https://jia.je/hardware/2026/01/17/ibm-power9/</link> <pubDate>Sat, 17 Jan 2026 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2026/01/17/ibm-power9/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2026/01/17/ibm-power9.png" type="image/png" length="48783" /> </item> <item> <title>IBM POWER8 微架构评测</title> <category>cpu</category> <category>hardware</category> <category>ibm</category> <category>performance</category> <category>power8</category> <category>ppc64le</category> <category>uarch-review</category> <description>&lt;h1 id=&#34;ibm-power8-微架构评测&#34;&gt;IBM POWER8 微架构评测&lt;a class=&#34;headerlink&#34; href=&#34;#ibm-power8-微架构评测&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;之前评测了很多 AMD64 和 ARM64 指令集的处理器，这次也来评测一下 PPC64LE 指令集的 IBM POWER8 微架构。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;官方信息&#34;&gt;官方信息&lt;a class=&#34;headerlink&#34; href=&#34;#官方信息&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;IBM 关于 POWER8 微架构有如下公开信息：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://research.ibm.com/publications/ibm-power8-processor-core-microarchitecture&#34;&gt;IBM POWER8 processor core microarchitecture&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;下面分各个模块分别记录官方提供的信息，以及实测的结果。官方信息与实测结果一致的数据会加粗。&lt;/p&gt; &lt;h2 id=&#34;benchmark&#34;&gt;Benchmark&lt;a class=&#34;headerlink&#34; href=&#34;#benchmark&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;IBM POWER8 的性能测试结果见 &lt;a href=&#34;../../../../../benchmark/&#34;&gt;SPEC&lt;/a&gt;。&lt;/p&gt; &lt;h2 id=&#34;前端&#34;&gt;前端&lt;a class=&#34;headerlink&#34; href=&#34;#前端&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;l1-icache&#34;&gt;L1 ICache&lt;a class=&#34;headerlink&#34; href=&#34;#l1-icache&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：&lt;strong&gt;32 KB&lt;/strong&gt;, 8-way set associative&lt;/p&gt; &lt;p&gt;为了测试 L1 ICache 容量，构造一个具有巨大指令 footprint 的循环，由大量的 nop 和最后的分支指令组成。观察在不同 footprint 大小下的 IPC：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power8-fetch-bandwidth.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;超出 L1 ICache 容量后，IPC 从 6 降低到了 2.4。其中 6 IPC 来自于，IBM POWER8 在 ST 模式下每周期可以发射 8 条指令，但其中分支指令最多两条，非分支指令最多六条，所以执行 NOP 指令的 IPC 只能达到 6。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/fetch_bandwidth_gen.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;l1-itlb-aka-instruction-effective-to-real-address-translation-table-ierat&#34;&gt;L1 ITLB (aka Instruction Effective to Real Address translation Table, IERAT)&lt;a class=&#34;headerlink&#34; href=&#34;#l1-itlb-aka-instruction-effective-to-real-address-translation-table-ierat&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：&lt;strong&gt;64-entry&lt;/strong&gt;, fully associative&lt;/p&gt; &lt;p&gt;为了测试 L1 ITLB 的容量，构造 b 序列，每个 b 在一个单独的页（64KB 的页大小）中，观察 b 的性能：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power8-itlb-size.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到明显的 64 pages 的拐点，对应了 64 entry 的 L1 ITLB。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/itlb_size_lib.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;btb-branch-target-buffer&#34;&gt;BTB (Branch Target Buffer)&lt;a class=&#34;headerlink&#34; href=&#34;#btb-branch-target-buffer&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：无 BTB，总是通过 3 周期延迟的 Fetch + Decode(Branch Scan) 来得到分支指令的目的地址，靠 SMT 来填补流水线的气泡。&lt;/p&gt; &lt;p&gt;实测也是如此，对于连续执行多个 b 指令的情况，每条 b 指令都需要 3 周期。&lt;/p&gt; &lt;h3 id=&#34;return-address-stack-aka-link-stack&#34;&gt;Return Address Stack (aka Link Stack)&lt;a class=&#34;headerlink&#34; href=&#34;#return-address-stack-aka-link-stack&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：32-entry(ST/SMT2)/16-entry(SMT4)/8-entry(SMT8) Link Stack per thread，也就是说总容量是 64，但每个线程只能用一部分&lt;/p&gt; &lt;p&gt;构造不同深度的调用链，测试每次调用花费的时间，得到如下测试结果：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power8-ras-size.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到 32 的拐点，对应的就是 ST 模式下 RAS 的大小。在同一个物理核上的其他三个逻辑核分别运行 stress，就测得 SMT4 模式下的 RAS 大小 16：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power8-ras-size-smt4.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;类似地，在其余七个逻辑核上分别运行 stress 负载，得到 SMT8 模式下的 RAS 大小为 8：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power8-ras-size-smt8.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/ras_size_gen.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;cbp-conditional-branch-predictor&#34;&gt;CBP (Conditional Branch Predictor)&lt;a class=&#34;headerlink&#34; href=&#34;#cbp-conditional-branch-predictor&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：16K-entry LBHT, 16K-entry GBHT, 16K-entry GSEL，使用 21-bit GHV 记录全局分支历史，GSEL 用来选择由 LBHT 还是 GBHT 提供预测（通过 2-bit 饱和计数器），LBHT 采用 PC 索引，GBHT 和 GSEL 采用 PC+GHV 的哈希索引；此外，还支持把 conditional branch to +8 也就是只跳过一条指令的分支指令改写为 predication&lt;/p&gt; &lt;h3 id=&#34;ibp-indirect-branch-predictor&#34;&gt;IBP (Indirect Branch Predictor)&lt;a class=&#34;headerlink&#34; href=&#34;#ibp-indirect-branch-predictor&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：256-entry local count cache, 512-entry global count cache，前者采用 PC 索引，后者采用 PC+GHV 的哈希索引，entry 内容是 30-bit 预测的目的地址加 2-bit 的 confidence（local count cache 的 entry 还有额外的 2-bit 饱和计数器用于选择 local 还是 global）&lt;/p&gt; &lt;h2 id=&#34;dispatch&#34;&gt;Dispatch&lt;a class=&#34;headerlink&#34; href=&#34;#dispatch&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;官方信息：按 Group 来 Dispatch，ST 模式下每周期一个 Group，每个 Group 最多 8 条指令（最多 2 条分支，最多 6 条非分支，且第二条分支必须是最后一条指令）；SMT 模式下，每周期从两个线程各 Dispatch 一个 Group，每个 Group 最多 4 条指令（最多 1 条分支，3 条非分支）&lt;/p&gt; &lt;h2 id=&#34;后端&#34;&gt;后端&lt;a class=&#34;headerlink&#34; href=&#34;#后端&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;rob-aka-global-completion-table-gct&#34;&gt;ROB (aka Global Completion Table, GCT)&lt;a class=&#34;headerlink&#34; href=&#34;#rob-aka-global-completion-table-gct&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：28-entry，ST 模式下每个 entry 对应一个 Group；SMT 模式下每个 entry 对应两个来自同一个线程的 Group；所以最多容纳 &lt;code&gt;28*8=224&lt;/code&gt; 条指令；Commit 的粒度是 Group，ST 模式下每周期 Commit 一个 Group，SMT 模式下每周期 Commit 两个 Group&lt;/p&gt; &lt;p&gt;把两个独立的 long latency pointer chasing load 放在循环的头和尾，中间用 NOP 填充，当 NOP 填满了 ROB，第二个 pointer chasing load 无法提前执行，导致性能下降。测试结果如下：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power8-rob-size.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;拐点大致在 168 附近，因为每 6 条 NOP 指令对应一个 Group，所以只能容纳 &lt;code&gt;28*6=168&lt;/code&gt; 条指令。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/rob_size_gen.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;register-file&#34;&gt;Register File&lt;a class=&#34;headerlink&#34; href=&#34;#register-file&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：一共可以有 106 个 Inflight 的 Rename，由 GPR（General Purpose Register）和 VSR（Vector and Scalar Register）共享；GPR 分为两组，每组 124-entry；VSR 分为两组，每组 144-entry；还有额外的两组 SAR（Software Architected Registers），一组用于 GPR，一组用于 VSR；CR（Condition Register）单独 Rename（32-entry mapper）到 64-entry Architected Register File；XER（fiXed-point Exception Register）Rename（30-entry mapper）到 32-entry Architected Register File；LR，CTR 和 TAR 单独 Rename（20-entry mapper）到 24-entry Architected Register File；FPSCR（Floating Point Status and Control Register）单独 Rename 到 28-entry buffer。&lt;/p&gt; &lt;h3 id=&#34;issue-queue&#34;&gt;Issue Queue&lt;a class=&#34;headerlink&#34; href=&#34;#issue-queue&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：15-entry Branch Issue Queue，8-entry Condition Register Queue，64-entry UniQueue 用于其他指令；每周期最多 Issue 10 条指令：1x Branch, 1x Condition Register Logical, 2x Fixed Point, 2x Load/Store/Fixed Point to LSU, 2x Load/Fixed Point to LU, 2x Vector-Scalar to VSU/DFU(Decimal Floating point Unit)/Crypto&lt;/p&gt; &lt;h3 id=&#34;执行单元&#34;&gt;执行单元&lt;a class=&#34;headerlink&#34; href=&#34;#执行单元&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：2 个定点计算流水线（FX），2 个 Load/Store 流水线（LS/FX），2 个 Load 流水线（L/FX），4 个双精度浮点流水线（或 8 个单精度浮点流水线），2 个向量流水线（VMX），1 个密码学流水线（Crypto），1 个分支流水线（Branch），1 个条件寄存器流水线（CR），1 个十进制浮点数流水线，共 16 个；其中 2 个 Load/Store 流水线和 2 个 Load 流水线还能执行简单的定点计算&lt;/p&gt; &lt;h3 id=&#34;load-store-unit&#34;&gt;Load Store Unit&lt;a class=&#34;headerlink&#34; href=&#34;#load-store-unit&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：共有四个 Pipeline，L0/L1 仅 Load，LS0/LS1 可 Load/Store, 3 cycle load-to-use latency&lt;/p&gt; &lt;h4 id=&#34;loadstore-reorder-queue&#34;&gt;Load/Store (Reorder) Queue&lt;a class=&#34;headerlink&#34; href=&#34;#loadstore-reorder-queue&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;官方信息：40-entry（128 Virtual）Store Reorder queue，44-entry（128 Virtual）Load Reorder Queue&lt;/p&gt; &lt;h4 id=&#34;load-to-use-latency&#34;&gt;Load to use latency&lt;a class=&#34;headerlink&#34; href=&#34;#load-to-use-latency&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;官方信息：3-cycle latency&lt;/p&gt; &lt;p&gt;实测在下列的场景下可以达到 3 cycle:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;ldr 4, 0(4)&lt;/code&gt;: load 结果转发到基地址，无偏移&lt;/li&gt; &lt;li&gt;&lt;code&gt;ldr 4, 8(4)&lt;/code&gt;：load 结果转发到基地址，有立即数偏移&lt;/li&gt; &lt;li&gt;&lt;code&gt;ldx 4, 4, 6&lt;/code&gt;：load 结果转发到基地址，有寄存器偏移&lt;/li&gt; &lt;li&gt;&lt;code&gt;ldx 4, 6, 4&lt;/code&gt;：load 结果转发到寄存器偏移&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;如果访存跨越了 128B 边界，则退化到 16 cycle。&lt;/p&gt; &lt;h3 id=&#34;l1-dcache&#34;&gt;L1 DCache&lt;a class=&#34;headerlink&#34; href=&#34;#l1-dcache&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：64KB, 8-way set associative, 128B cache line, 4 read port, 1 write port，3 cycle load to use latency, store-through（写入会同时写 L1 DCache 和 L2），所以 store miss 不分配 cache line, 16 MSHR(aka Load Miss Queue)&lt;/p&gt; &lt;p&gt;构造不同大小 footprint 的 pointer chasing 链，测试不同 footprint 下每条 load 指令耗费的时间：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power8-l1dc-size.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到 64KB 出现了明显的拐点，对应的就是 64KB 的 L1 DCache 容量。第二个拐点在 512KB，对应的是 L2 Cache 的容量。第三个拐点是 3MB，对应的是 L1 DTLB 的容量：&lt;code&gt;48*64KB=3MB&lt;/code&gt;。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/memory_latency.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h4 id=&#34;banking&#34;&gt;Banking&lt;a class=&#34;headerlink&#34; href=&#34;#banking&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;官方信息：L1 DCache 由 16 个 macro 组成，每个 macro 是 16 个 bank，一共是 256 个 bank；sram 用的是 2R 或 1W，所以每个 bank 可以支持每周期 2R 或 1W&lt;/p&gt; &lt;h3 id=&#34;l1-dtlb-aka-primary-data-effective-to-real-address-translation-derat&#34;&gt;L1 DTLB (aka primary Data Effective-to-Real Address Translation, DERAT)&lt;a class=&#34;headerlink&#34; href=&#34;#l1-dtlb-aka-primary-data-effective-to-real-address-translation-derat&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：&lt;strong&gt;48-entry&lt;/strong&gt;(ST)/96-entry(SMT), fully associative&lt;/p&gt; &lt;p&gt;用类似测 L1 DCache 的方法测试 L1 DTLB 容量，只不过这次 pointer chasing 链的指针分布在不同的 64KB page 上，使得 DTLB 成为瓶颈：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power8-dtlb-size.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到 48 Page 出现了明显的拐点，对应的就是 48 的 L1 DTLB 容量。没有超出 L1 DTLB 容量前，Load to use latency 是 3 cycle。最终出现一个 18.8 cycle 的平台。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/dtlb_size.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;l2-dtlb-aka-secondary-data-effective-to-real-address-translation-derat&#34;&gt;L2 DTLB (aka secondary Data Effective-to-Real Address Translation, DERAT)&lt;a class=&#34;headerlink&#34; href=&#34;#l2-dtlb-aka-secondary-data-effective-to-real-address-translation-derat&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：&lt;strong&gt;256-entry&lt;/strong&gt;（ST 模式下全可见，SMT 模式下每个线程只有一半可见）, fully associative&lt;/p&gt; &lt;p&gt;继续扩大 DTLB 测试规模，可以看到在 256 处出现了新的拐点，其中 256 的地方出现周期数的骤降，是触发了 Linux 的大页合并功能：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power8-dtlb-size-l2.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;关掉 THP(Transparent Huge Page) 后，周期数的骤降消失，256 的拐点之后周期数增加而不是减少：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power8-dtlb-size-l2-no-thp.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/dtlb_size.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;l3-tlb&#34;&gt;L3 TLB&lt;a class=&#34;headerlink&#34; href=&#34;#l3-tlb&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：&lt;strong&gt;2048-entry&lt;/strong&gt;, 4-way set associative, 4 concurrent page table walk&lt;/p&gt; &lt;p&gt;继续扩大 DTLB 测试规模，在 2048 处出现了拐点，注意要关闭 THP，否则拐点会消失，因为实际上没有用到 2048 个页：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power8-dtlb-size-l3.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/dtlb_size.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;prefetcher&#34;&gt;Prefetcher&lt;a class=&#34;headerlink&#34; href=&#34;#prefetcher&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：16-entry Stream Prefetcher，可以跨 4KB/64KB 页边界，用虚拟地址预取，可以预取到 L1/L2/L3&lt;/p&gt; &lt;p&gt;参考 &lt;a href=&#34;https://abertschi.ch/blog/2022/prefetching/&#34;&gt;Battling the Prefetcher: Exploring Coffee Lake (Part 1)&lt;/a&gt; 的方式，研究预取器的行为：分配一片内存，把数据从缓存中 flush 掉，再按照特定的访存模式访问，触发预取器，最后测量访问每个缓存行的时间，从而得到预取器预取了哪些缓存行的信息。&lt;/p&gt; &lt;p&gt;首先是连续访问若干个 128B cacheline，观察哪些被预取了进来：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power8-prefetcher-cacheline-1.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到后面有 12 个 cacheline 都被预取了，但是预取到了不同的 cache 层次，猜测距离越近的 4 个 cacheline 预取到 L1，更远的 2 个到 L2，其余的 6 个到 L3。&lt;/p&gt; &lt;p&gt;如果是访问了几个分立的缓存行，行为变成了 Next 3 Line：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../ibm-power8-prefetcher-cacheline-2.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/prefetcher_cacheline.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt;</description> <link>https://jia.je/hardware/2026/01/15/ibm-power8/</link> <pubDate>Thu, 15 Jan 2026 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2026/01/15/ibm-power8/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2026/01/15/ibm-power8.png" type="image/png" length="48890" /> </item> <item> <title>2025 年我是怎么使用 AI 的</title> <category>ai</category> <category>llm</category> <category>software</category> <category>vibe</category> <description>&lt;h1 id=&#34;2025-年我是怎么使用-ai-的&#34;&gt;2025 年我是怎么使用 AI 的&lt;a class=&#34;headerlink&#34; href=&#34;#2025-年我是怎么使用-ai-的&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;前言&#34;&gt;前言&lt;a class=&#34;headerlink&#34; href=&#34;#前言&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;经常看我博客的读者应该能看出来，我研究的主要是计算机系统结构方向，特别是处理器的微架构，几乎没有涉及到 AI 的内容，我也确实不喜欢 AI 研究，仅关注但不参与。但今年，因为各种 AI 技术尤其是 LLM 的发展，我确实成为了很多 AI 技术的用户，可以说 2025 年是我正经大规模用 AI 的元年，所以在年末做一个简单的总结。&lt;/p&gt; &lt;!-- more --&gt; &lt;p&gt;我不想在这里给大模型厂商打广告，所以相关的名字我都会按照某 PDF 的方法进行打码，有需要的朋友可以自行查看实际的内容。&lt;/p&gt; &lt;h2 id=&#34;vibe-coding&#34;&gt;Vibe Coding&lt;a class=&#34;headerlink&#34; href=&#34;#vibe-coding&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;首先的一个冲击来自于 Vibe Coding。我写代码也有大概十五年了，一直都是坚持自己写代码，但今年从一些朋友那里了解到一些 Vibe Coding 的效果以后，也自己尝试了一下，确实能够感受到 Vibe Coding 对写代码的巨大冲击，我的心态也出现了一定的变化。Vibe Coding 并不复杂，其实就是用一些 Coding 客户端，配上 LLM 加一些 Tool Call，使得 LLM 可以自己编写、测试和运行代码。目前随着 LLM 能力的变强，Vibe Coding 逐渐成为了一个可以负担得起且效果不错的东西。结合实际的使用，以及受朋友们的一些启发，我目前已经用它进行了一些 Vibe Coding 尝试，例如：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;写一些简单的 MCP 服务器，例如 &lt;a href=&#34;https://github.com/jiegec/devdocs-mcp-server&#34;&gt;devdocs-mcp-server&lt;/a&gt; 把 devdocs.io 的文档通过 MCP 暴露给 LLM，让它可以精确读取标准库的文档，避免幻觉，还有让 LLM 可以读取波形文件的 &lt;a href=&#34;https://github.com/jiegec/waveform-mcp&#34;&gt;waveform-mcp&lt;/a&gt;；&lt;/li&gt; &lt;li&gt;写一个 API 路由器 &lt;a href=&#34;https://github.com/jiegec/llm-api-router&#34;&gt;llm-api-router&lt;/a&gt;，可以在多个 API 提供商之间自动 Fallback，类似于本地版的 OpenRouter，但在这里主要是为了解决 Rate Limit 问题；&lt;/li&gt; &lt;li&gt;对已有代码的一些改进，比如实现 TODO，修复代码 BUG 等等；&lt;/li&gt; &lt;li&gt;给定提示词，让 LLM 用 Typst 或者 SVG 绘图，相比直接 AI 绘图，我更希望是可编辑的矢量图；&lt;/li&gt; &lt;li&gt;给定一张图，让 LLM 用 Typst 或者 SVG 复刻出来，然后再用 Vision LLM 识别绘制出来的图，观察内容是否和输入足够相似；&lt;/li&gt; &lt;li&gt;对于闭源的软件，让 LLM 自动逆向工程，得到一份关于内部实现的代码，甚至让它实现一份开源的等价实现。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;目前给我的感觉是，LLM 借助各种 MCP Tooling，在很多事情上可以做的很好，但也有一些前提条件。第一是 LLM 需要有针对这个事情的知识，但如果它的知识停留在几年前，又做一些比较新的东西（例如 Typst 语法很多 LLM 就不会写），它就比较难写对；第二是，一定要给 LLM 反馈的路径，能够让它自产自纠自查，不然幻觉是很难避免的，一次写对的情况很少，有反馈和无反馈完全是两个表现；第三是，目前 LLM 做复杂事情需要大量的 Token，这就意味着 API 调用时间和开销都是不可忽略的因素，即使我用了比较便宜的 &lt;span class=&#34;redacted&#34;&gt;DeepSeek&lt;/span&gt; 模型，让 LLM 在后台跑几个小时，价格一样受不了。&lt;/p&gt; &lt;p&gt;举一个数据，我这个月在 &lt;span class=&#34;redacted&#34;&gt;DeepSeek&lt;/span&gt; 上已经花费了 200 多元，而这个月之前的所有时间加起来，也就不过 10 元。如果相同的 Token 数用在 &lt;span class=&#34;redacted&#34;&gt;Claude&lt;/span&gt; 上，这个价格不可想象。所以我也终于能理解，那些几百美刀一个月的订阅服务为啥有市场了。也是因为这个原因，我才会降本增效，通过订阅 &lt;span class=&#34;redacted&#34;&gt;GLM Coding Plan&lt;/span&gt; 去解决一些低频的 Vibe Coding 需求，但它的用量限制和并发限制都比较容易触发，所以才去 Vibe Coding 了一个 API 路由器，对于 &lt;span class=&#34;redacted&#34;&gt;GLM Coding Plan&lt;/span&gt; 用量以外的需求，再 Fallback 到 &lt;span class=&#34;redacted&#34;&gt;DeepSeek&lt;/span&gt; 上。&lt;/p&gt; &lt;p&gt;在使用 Vibe Coding 的过程中，我也有一些感受，就感觉我并不是在 Vibe Coding，而是在指挥一个水平飘忽不定的人在写代码。它有时候能精准地找到问题并写出正确的代码，有时候又注意力涣散，必须要我及时地打断它，让它按照我指定的方法去做。对于一些简单的代码，可能可以让它在后台跑，我去做一些别的事情，然后隔一段时间再看看它做得怎么样，有问题了，再提供及时的纠正。然后我就在想，这其实就是当领导吧，给钱让手下的人干活，不一定干的对，所以还得时不时地去纠正一下。某种意义来说，LLM 让每个人都有了成为领导，领导一群 LLM 干活的能力。我目前的工作流就是在 tmux 里挂几个 &lt;span class=&#34;redacted&#34;&gt;Qwen Code&lt;/span&gt;，连上几个配好的 MCP 服务器以及 API 路由器，然后时不时地看看它做的咋样，做得好就验收，让它 Git Commit，做得不好就让它改，时不时还得翻翻代码看看怎么帮它修。某种意义上，这和课后布置作业，给学生答疑也没啥本质上的区别，甚至 LLM 还更爱说话一点。&lt;/p&gt; &lt;p&gt;既然提到了答疑，也来谈谈教学。这种 Vibe Coding 的能力对于计算机教育的冲击无疑是巨大的，本来很多上课教的内容，AI 可以比较容易地完成，那学生可能就更倾向于让 AI 去完成了，换位思考一下，如果让我在 2025 年成为大一不会编程的新生，我也很难抵御这个诱惑。但是，锻炼代码和工程能力就欠缺了。这就对应一个很重要的问题，就是 AI 它到底是不是一种类似编译器、调试器或者编程语言的工具？我们说学生可以从编程语言而不是汇编学起，是因为它是一个很成熟很可靠的工具，你学会了高层次的工具就是会了，就可以用它做很多事情。AI 就很奇怪，它确实可以做很多事情，但又不总是可以完成，它好像是概率性的图灵完全，全看是否出现幻觉，所以它不是一个可靠的工具，但又是一个好用的工具。那么紧接的问题是，计算机教育，是要教出来真的会写代码的人，还是会用 AI 写代码就行？我目前没有答案，也不知道未来会怎么发展，只能慢慢走一步看一步了。但抛开计算机专业的教育，如果是对于计算机的通识教育，我觉得用 AI 写代码完全没有问题，毕竟对于更多人来说，能解决问题就可以，可不可靠，其实很多时候并不在考虑范围内。&lt;/p&gt; &lt;p&gt;我知道上面这段话可能会让读者有一些焦虑，但我觉得，它都这样了，就共存吧，反正焦虑也没有用，不如拥抱它。至于是否担心自己会被替代，我确实是不担心，目前它还不够专业，就算它再专业，它也没有身份证是吧。希望早日实现生产力极大富足，实现共同富裕，那就不用思考人是不是会被 AI 替代了。另外，高级编程语言出现了，那些写汇编的人去写高级语言，现在 Vibe Coding 来了，只是同一拨人又跑去做 Vibe Coding 罢了。持续学习才是最重要的。今年开始尝试 Vibe Coding 也是让我意识到，随着年龄增大，确实是没有当年对新事物接受得那么快了，这也让我有了一些反思，以后还是要多多接触新技术，一些过去的思维可能也要重新审视。&lt;/p&gt; &lt;p&gt;目前我对 Vibe Coding 的态度是，它不能替代我的思考，相反，我可以更多地思考一些更高层次的东西，而可以适当地把一些细节交给 AI。我也持续在自己写代码，特别是一些关键的部分，我还是无法信任完全由 AI 编写，毕竟它比人还懂得偷懒，经常写出来一些没有测试效果的测例，一看测例都过，一测全是 BUG。&lt;/p&gt; &lt;p&gt;我还会继续尝试和 LLM 协作，尽量保持高质量的代码产出，我认为这是用 Vibe Coding 的底线：用 AI 并不是写出烂代码的理由。以前我们有所谓的中文羞耻，觉得写了很多中文的项目的代码可能不靠谱，现在是所谓的 AI 羞耻，看到 README 里一堆 AI 生成的辞藻就觉得不靠谱一样。我们作为业内人士，还是要把事情做得漂亮，而不是让 AI 生成一个勉强能用的组装拖拉机就完事。&lt;/p&gt; &lt;h2 id=&#34;写作和语音输入&#34;&gt;写作和语音输入&lt;a class=&#34;headerlink&#34; href=&#34;#写作和语音输入&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;另一方面 AI 影响比较大的，其实是写作，包括日常的各种文字，比较正式的文档、论文甚至教材，不得不承认，AI 在写作方面确实是比我这种语文是考试弱项的偏科生要做得更好。我通常会自己编写一遍，然后交给 &lt;span class=&#34;redacted&#34;&gt;DeepSeek&lt;/span&gt; 来润色一遍，再在润色的基础上修改，保证我要表达的意思能够完全地被保留下来。一些小的人情世故，比如微信上和各种人打交道的措辞，网络上发送的邮件或者是 GitHub Issue 等等场合的客套话，AI 确实也是做得比自己好。但是，更完整的内容，或者整体架构上的把握，还是不会让 AI 完全去完成，因为能感觉到 AI 训练所使用的语料和自己的思维方式或者写作的习惯还是不一样的，我还是希望我写的东西能更加得有我的思考和劳动在里面，AI 只是一个让文字看起来更加通顺的工具，帮我纠正一些语法错误之类的。例如，我平时可能更习惯一些口语化的表达，能够让我很快地通过打字或者语音输入把我的脑子里的想法变成文字，然后再让 AI 改写成更加严肃的文字，像教材或者论文，这时 AI 就沦为了纯粹的文字风格改写或者语言翻译器。&lt;/p&gt; &lt;p&gt;既然提到了语音输入法，就不得不提，今年我用语音输入的比例大大提升了。其实语音输入法历史已经很久了，但是以前每次体验，都觉得效果不行，每次输入的有错误还得改，自己改正的时间，还不如自己打字来得快。所以一直以来我都是坚持在所有设备上都是 26 键打字用拼音输入的，当然包括手机，经过多年的练习，确实速度还不错，包括我也不喜欢麻烦别人在微信上听语音，所以我尽量都是用文字的。但今年感受下来，确实是不一样，感觉语音输入的准确率有了质的飞跃，能看到它先识别出一个音对字不对的状态，再纠正成正确的表达，还会提示你，这里可能是另一个词，如果你要修改的话，就直接点一下就行。有这个功能以后，我在手机上真的很多时候就直接用语音输入了，尤其是在一些不太正式的场合，对方也能够对那些少数的识别错误脑补的时候，语音输入确确实实替代了手机上打字。在电脑上，还是打字通常更快一些，但最近也尝试了一下 &lt;span class=&#34;redacted&#34;&gt;智谱 AutoGLM&lt;/span&gt; 的输入法，感觉这种语音输入和 LLM 结合还挺有意思的，就是它们家的语音输入准确率还比不上 &lt;span class=&#34;redacted&#34;&gt;鸿蒙 6 上的小艺输入法&lt;/span&gt;，要是二者的优点能够结合在一起就更好了，相信这一天并不遥远。&lt;/p&gt; &lt;h2 id=&#34;小结&#34;&gt;小结&lt;a class=&#34;headerlink&#34; href=&#34;#小结&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;目前想到的就这么多，其实 AI 还有很多场景可以用到，比如生成图片、视频和音乐等等，目前还没有太多的尝试，相信明年开始会逐渐接触，到时候再在年底写一个 AI 使用总结。总的下来，就是感叹自己也到了感慨科技进步的年纪了，十几年前学技术，虽然也能感觉到科技进步，但因为自己是从零开始，学的就是最新的科技，所以没有啥感觉。但这几年，不断地把新的输入和已有的积累进行对比，就能感觉明显到技术潮流和技术栈的移动，也能感觉到自己对新技术的接受度开始有了略微的下降，这值得让我警醒。以前，我们总是嘲笑大人不追求潮流，不去学习手机等新技术，我们在这个时代长大的人，可也不能犯这样的错误呀。&lt;/p&gt;</description> <link>https://jia.je/software/2025/12/25/my-ai-usage-2025/</link> <pubDate>Thu, 25 Dec 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/software/2025/12/25/my-ai-usage-2025/</guid> <enclosure url="https://jia.je/assets/images/social/software/2025/12/25/my-ai-usage-2025.png" type="image/png" length="48111" /> </item> <item> <title>条件分支预测器逆向工程（以 Apple M1 Firestorm 为例）</title> <category>apple</category> <category>cbp</category> <category>cpu</category> <category>firestorm</category> <category>hardware</category> <category>m1</category> <category>re</category> <description>&lt;h1 id=&#34;条件分支预测器逆向工程以-apple-m1-firestorm-为例&#34;&gt;条件分支预测器逆向工程（以 Apple M1 Firestorm 为例）&lt;a class=&#34;headerlink&#34; href=&#34;#条件分支预测器逆向工程以-apple-m1-firestorm-为例&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;去年我完成了针对 Apple 和 Qualcomm 条件分支预测器（Conditional Branch Predictor）的逆向工程研究，相关论文已发表在 &lt;a href=&#34;https://arxiv.org/abs/2411.13900&#34;&gt;arXiv&lt;/a&gt; 上，并公开了&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks&#34;&gt;源代码&lt;/a&gt;。考虑到许多读者对处理器逆向工程感兴趣，但可能因其复杂性而望而却步，本文将以 Apple M1 Firestorm 为例，详细介绍条件分支预测器的逆向工程方法，作为对原论文的补充说明。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;背景知识&#34;&gt;背景知识&lt;a class=&#34;headerlink&#34; href=&#34;#背景知识&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;首先介绍一些背景知识。要逆向工程条件分支预测器，需要先了解其工作原理。条件分支预测器的基本思路是：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;条件分支的跳转行为（跳转或不跳转）通常是高度可预测的&lt;/li&gt; &lt;li&gt;预测器的输入包括条件分支的地址，以及近期执行的若干条分支的历史记录；输出则是预测该条件分支是否跳转&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;为了在硬件上实现这一算法，处理器会维护一个预测表，表中每一项包含一个 2 位饱和计数器，用于预测跳转方向。查表时，系统会对条件分支地址以及近期执行的分支历史进行哈希运算，使用哈希结果作为索引读取表项，然后根据计数器的值来预测分支的跳转方向。&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../cbp-reverse-engineer-basic.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;（图源：CMU ECE740 Computer Architecture: Branch Prediction）&lt;/p&gt; &lt;p&gt;目前主流处理器普遍采用 &lt;a href=&#34;https://inria.hal.science/hal-03408381/document&#34;&gt;TAGE&lt;/a&gt; 预测器，它在上述基础查表方法的基础上进行了重要改进：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;观察到不同分支的预测所需的历史长度各不相同：有些分支无需历史信息即可准确预测，有些依赖近期分支的跳转结果，而有些则需要更久远的历史信息；&lt;/li&gt; &lt;li&gt;分支历史越长，可能的路径组合就越多，导致预测器训练过程变慢，训练期间的预测错误率较高，因此希望尽快收敛；&lt;/li&gt; &lt;li&gt;为满足不同分支对历史长度的需求，TAGE 设计了多个预测表，每个表使用不同长度的分支历史。多个表同时进行预测，当多个表都提供预测结果时（仅在 tag 匹配时提供预测），选择使用最长历史长度的预测结果。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../cbp-reverse-engineer-tage.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;（图源：&lt;a href=&#34;https://cseweb.ucsd.edu/~tullsen/halfandhalf.pdf&#34;&gt;Half&amp;amp;Half: Demystifying Intel&#39;s Directional Branch Predictors for Fast, Secure Partitioned Execution&lt;/a&gt;）&lt;/p&gt; &lt;p&gt;因此，要逆向工程处理器的条件分支预测器，需要完成以下工作：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;确定分支历史的记录方式：通常涉及分支地址和目的地址，通过一系列移位和异或操作，将结果存储在寄存器中；&lt;/li&gt; &lt;li&gt;确定 TAGE 算法的具体实现：包括表的数量、每个表的大小、索引方式以及使用的分支历史长度。&lt;/li&gt; &lt;/ol&gt; &lt;h2 id=&#34;分支历史的逆向&#34;&gt;分支历史的逆向&lt;a class=&#34;headerlink&#34; href=&#34;#分支历史的逆向&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;第一步是逆向工程处理器记录分支历史的方式。传统教科书方法使用一个寄存器，每当遇到条件分支时记录其跳转方向（跳转记为 1，不跳转记为 0），每个分支占用 1 bit。然而，现代处理器（包括 Intel、Apple、Qualcomm、ARM 和部分 AMD）普遍采用 &lt;a href=&#34;https://ieeexplore.ieee.org/document/476809/&#34;&gt;Path History Register&lt;/a&gt; 方法。这种方法设计一个长度为 &lt;span class=&#34;arithmatex&#34;&gt;\(n\)&lt;/span&gt; 的寄存器 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt;，每当遇到跳转分支（包括条件分支和无条件分支）时，将寄存器左移，然后将当前跳转分支的地址和目的地址通过哈希函数映射，将哈希结果异或到移位寄存器中。用数学公式表示为：&lt;/p&gt; &lt;p&gt;&lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}_{\mathrm{new}} = (\mathrm{PHR}_{\mathrm{old}} \ll \mathrm{shamt}) \oplus \mathrm{footprint}\)&lt;/span&gt;&lt;/p&gt; &lt;p&gt;其中 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{footprint}\)&lt;/span&gt; 是通过分支地址和目的地址计算得到的哈希值。接下来的任务是确定 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 的位宽、每次左移的位数，以及 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{footprint}\)&lt;/span&gt; 的计算方法。&lt;/p&gt; &lt;h3 id=&#34;历史长度&#34;&gt;历史长度&lt;a class=&#34;headerlink&#34; href=&#34;#历史长度&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;首先分析这个更新公式：它将最近的 &lt;span class=&#34;arithmatex&#34;&gt;\(\lceil n / \mathrm{shamt} \rceil\)&lt;/span&gt; 条跳转分支的信息压缩存储在 &lt;span class=&#34;arithmatex&#34;&gt;\(n\)&lt;/span&gt; 位的 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 寄存器中。随着移位操作的累积，更早的分支历史信息对 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 的贡献最终会变为零。&lt;/p&gt; &lt;p&gt;第一个实验的目标是确定 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 能够记录多少条最近分支的历史。具体方法是构建一个分支历史序列：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;第一个条件分支：以 50% 的概率随机跳转或不跳转；&lt;/li&gt; &lt;li&gt;中间插入若干条无条件分支；&lt;/li&gt; &lt;li&gt;最后一个条件分支：跳转方向与第一个条件分支相同。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;接下来分析两种情况：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;如果在预测最后一个条件分支时，分支历史 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 仍然包含第一个条件分支的信息，预测器应该能够准确预测最后一个条件分支的方向；&lt;/li&gt; &lt;li&gt;如果中间的无条件分支数量足够多，使得第一个条件分支的跳转信息对预测最后一个条件分支时的 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 没有影响，预测器只能以 50% 的概率进行正确预测。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;通过构造上述程序，调整中间无条件分支的数量，并使用性能计数器统计分支预测错误率，可以找到一个临界点。当无条件分支数量超过这个阈值时，第二个条件分支的错误预测率会从 0% 上升到 50%。这个临界点对应 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 能够记录的分支历史数量，即 &lt;span class=&#34;arithmatex&#34;&gt;\(\lceil n / \mathrm{shamt} \rceil\)&lt;/span&gt;。&lt;/p&gt; &lt;p&gt;经过&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/phr_size_gen.cpp&#34;&gt;测试&lt;/a&gt;：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../cbp-reverse-engineer-phr-len.png&#34; /&gt;&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-0-1&#34;&gt;&lt;a id=&#34;__codelineno-0-1&#34; name=&#34;__codelineno-0-1&#34; href=&#34;#__codelineno-0-1&#34;&gt;&lt;/a&gt;# 第一列：第二步插入的无条件分支数量加一 &lt;/span&gt;&lt;span id=&#34;__span-0-2&#34;&gt;&lt;a id=&#34;__codelineno-0-2&#34; name=&#34;__codelineno-0-2&#34; href=&#34;#__codelineno-0-2&#34;&gt;&lt;/a&gt;# 第二列到第四列：分支预测错误概率的 min/avg/max &lt;/span&gt;&lt;span id=&#34;__span-0-3&#34;&gt;&lt;a id=&#34;__codelineno-0-3&#34; name=&#34;__codelineno-0-3&#34; href=&#34;#__codelineno-0-3&#34;&gt;&lt;/a&gt;# 第五列：每次循环的周期数 &lt;/span&gt;&lt;span id=&#34;__span-0-4&#34;&gt;&lt;a id=&#34;__codelineno-0-4&#34; name=&#34;__codelineno-0-4&#34; href=&#34;#__codelineno-0-4&#34;&gt;&lt;/a&gt;size,min,avg,max,cycles &lt;/span&gt;&lt;span id=&#34;__span-0-5&#34;&gt;&lt;a id=&#34;__codelineno-0-5&#34; name=&#34;__codelineno-0-5&#34; href=&#34;#__codelineno-0-5&#34;&gt;&lt;/a&gt;97,0.00,0.00,0.01,216.87 &lt;/span&gt;&lt;span id=&#34;__span-0-6&#34;&gt;&lt;a id=&#34;__codelineno-0-6&#34; name=&#34;__codelineno-0-6&#34; href=&#34;#__codelineno-0-6&#34;&gt;&lt;/a&gt;98,0.00,0.00,0.01,221.02 &lt;/span&gt;&lt;span id=&#34;__span-0-7&#34;&gt;&lt;a id=&#34;__codelineno-0-7&#34; name=&#34;__codelineno-0-7&#34; href=&#34;#__codelineno-0-7&#34;&gt;&lt;/a&gt;99,0.00,0.00,0.01,225.18 &lt;/span&gt;&lt;span id=&#34;__span-0-8&#34;&gt;&lt;a id=&#34;__codelineno-0-8&#34; name=&#34;__codelineno-0-8&#34; href=&#34;#__codelineno-0-8&#34;&gt;&lt;/a&gt;100,0.00,0.00,0.01,229.17 &lt;/span&gt;&lt;span id=&#34;__span-0-9&#34;&gt;&lt;a id=&#34;__codelineno-0-9&#34; name=&#34;__codelineno-0-9&#34; href=&#34;#__codelineno-0-9&#34;&gt;&lt;/a&gt;101,0.45,0.50,0.53,331.97 &lt;/span&gt;&lt;span id=&#34;__span-0-10&#34;&gt;&lt;a id=&#34;__codelineno-0-10&#34; name=&#34;__codelineno-0-10&#34; href=&#34;#__codelineno-0-10&#34;&gt;&lt;/a&gt;102,0.47,0.50,0.54,336.27 &lt;/span&gt;&lt;span id=&#34;__span-0-11&#34;&gt;&lt;a id=&#34;__codelineno-0-11&#34; name=&#34;__codelineno-0-11&#34; href=&#34;#__codelineno-0-11&#34;&gt;&lt;/a&gt;103,0.46,0.50,0.54,339.85 &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;测试结果表明阈值为 100：在 Apple M1 Firestorm 上，最多可以记录最近 100 条分支的历史信息。&lt;/p&gt; &lt;details class=&#34;question&#34;&gt; &lt;summary&gt;分支预测错误率是怎么测量的？&lt;/summary&gt; &lt;p&gt;处理器内置了性能计数器，会记录分支预测错误次数。在 Linux 上，可以用 perf 子系统来读取；在 macOS 上，可以用 kpep 私有 API 来获取。我开源的代码中对这些 API 进行了&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/utils.cpp&#34;&gt;封装&lt;/a&gt;，可以实现跨平台的性能计数器读取。更进一步，我们还逆向了 Qualcomm Oryon 的针对条件分支的预测错误次数的隐藏性能计数器，用于后续的实验。&lt;/p&gt; &lt;/details&gt; &lt;h3 id=&#34;分支地址-b-的贡献&#34;&gt;分支地址 B 的贡献&lt;a class=&#34;headerlink&#34; href=&#34;#分支地址-b-的贡献&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;接下来需要推测 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{footprint}\)&lt;/span&gt; 的计算方法，即分支地址和目的地址如何参与 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 的更新过程。约定分支地址记为 &lt;span class=&#34;arithmatex&#34;&gt;\(B\)&lt;/span&gt;（Branch 的首字母），目的地址记为 &lt;span class=&#34;arithmatex&#34;&gt;\(T\)&lt;/span&gt;（Target 的首字母），用 &lt;span class=&#34;arithmatex&#34;&gt;\(B[i]\)&lt;/span&gt; 表示分支地址从低到高第 &lt;span class=&#34;arithmatex&#34;&gt;\(i\)&lt;/span&gt; 位（下标从 0 开始）的值，&lt;span class=&#34;arithmatex&#34;&gt;\(T[i]\)&lt;/span&gt; 同理。假设 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{footprint}\)&lt;/span&gt; 的每一位都由若干个 &lt;span class=&#34;arithmatex&#34;&gt;\(B[i]\)&lt;/span&gt; 和 &lt;span class=&#34;arithmatex&#34;&gt;\(T[i]\)&lt;/span&gt; 通过异或运算得到。&lt;/p&gt; &lt;details class=&#34;question&#34;&gt; &lt;summary&gt;分支指令本身占用了多个字节，那么分支地址指的是哪一个字节的地址呢？&lt;/summary&gt; &lt;p&gt;经过测试，AMD64 架构下，分支地址用的是分支指令最后一个字节的地址，而 ARM64 架构下，分支地址用的是分支指令第一个字节的地址。这大概是因为 AMD64 架构下分支指令是变长的，并且可以跨越页的边界；ARM64 则是定长的，并且不会跨越页的边界。&lt;/p&gt; &lt;/details&gt; &lt;p&gt;设计以下程序来推测某个 &lt;span class=&#34;arithmatex&#34;&gt;\(B[i]\)&lt;/span&gt; 如何参与 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{footprint}\)&lt;/span&gt; 的计算：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;根据上面的分析，Apple M1 Firestorm 最多可以记录最近 100 条分支的历史信息，为了让 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 进入一个稳定的初始值，执行 100 个无条件分支；&lt;/li&gt; &lt;li&gt;设计两条分支指令，第一条是条件分支，按 50% 的概率跳或不跳；第二条是无条件分支；这两条分支的分支地址只在 &lt;span class=&#34;arithmatex&#34;&gt;\(B[i]\)&lt;/span&gt; 上不同，其余的位都相同，目的地址相同；&lt;/li&gt; &lt;li&gt;执行若干条无条件分支，目的是把 &lt;span class=&#34;arithmatex&#34;&gt;\(B[i]\)&lt;/span&gt; 对 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 的贡献向前移动；&lt;/li&gt; &lt;li&gt;执行一条条件分支指令，其跳转方向与第二步中条件分支的方向一致。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;对应的代码如下：&lt;/p&gt; &lt;div class=&#34;language-c highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-1-1&#34;&gt;&lt;a id=&#34;__codelineno-1-1&#34; name=&#34;__codelineno-1-1&#34; href=&#34;#__codelineno-1-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// step 1.&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-2&#34;&gt;&lt;a id=&#34;__codelineno-1-2&#34; name=&#34;__codelineno-1-2&#34; href=&#34;#__codelineno-1-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// 100 jumps forward&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-3&#34;&gt;&lt;a id=&#34;__codelineno-1-3&#34; name=&#34;__codelineno-1-3&#34; href=&#34;#__codelineno-1-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-4&#34;&gt;&lt;a id=&#34;__codelineno-1-4&#34; name=&#34;__codelineno-1-4&#34; href=&#34;#__codelineno-1-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;jump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jump_1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-5&#34;&gt;&lt;a id=&#34;__codelineno-1-5&#34; name=&#34;__codelineno-1-5&#34; href=&#34;#__codelineno-1-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// ...&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-6&#34;&gt;&lt;a id=&#34;__codelineno-1-6&#34; name=&#34;__codelineno-1-6&#34; href=&#34;#__codelineno-1-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;jump_98&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jump_99&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-7&#34;&gt;&lt;a id=&#34;__codelineno-1-7&#34; name=&#34;__codelineno-1-7&#34; href=&#34;#__codelineno-1-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;jump_99&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-8&#34;&gt;&lt;a id=&#34;__codelineno-1-8&#34; name=&#34;__codelineno-1-8&#34; href=&#34;#__codelineno-1-8&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-9&#34;&gt;&lt;a id=&#34;__codelineno-1-9&#34; name=&#34;__codelineno-1-9&#34; href=&#34;#__codelineno-1-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// step 2.&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-10&#34;&gt;&lt;a id=&#34;__codelineno-1-10&#34; name=&#34;__codelineno-1-10&#34; href=&#34;#__codelineno-1-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rand&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-11&#34;&gt;&lt;a id=&#34;__codelineno-1-11&#34; name=&#34;__codelineno-1-11&#34; href=&#34;#__codelineno-1-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// the follow two branches differ in B[i]&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-12&#34;&gt;&lt;a id=&#34;__codelineno-1-12&#34; name=&#34;__codelineno-1-12&#34; href=&#34;#__codelineno-1-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// first conditional branch, 50% taken or not taken&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-13&#34;&gt;&lt;a id=&#34;__codelineno-1-13&#34; name=&#34;__codelineno-1-13&#34; href=&#34;#__codelineno-1-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-14&#34;&gt;&lt;a id=&#34;__codelineno-1-14&#34; name=&#34;__codelineno-1-14&#34; href=&#34;#__codelineno-1-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// second unconditional branch&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-15&#34;&gt;&lt;a id=&#34;__codelineno-1-15&#34; name=&#34;__codelineno-1-15&#34; href=&#34;#__codelineno-1-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-16&#34;&gt;&lt;a id=&#34;__codelineno-1-16&#34; name=&#34;__codelineno-1-16&#34; href=&#34;#__codelineno-1-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-17&#34;&gt;&lt;a id=&#34;__codelineno-1-17&#34; name=&#34;__codelineno-1-17&#34; href=&#34;#__codelineno-1-17&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-18&#34;&gt;&lt;a id=&#34;__codelineno-1-18&#34; name=&#34;__codelineno-1-18&#34; href=&#34;#__codelineno-1-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// step 3.&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-19&#34;&gt;&lt;a id=&#34;__codelineno-1-19&#34; name=&#34;__codelineno-1-19&#34; href=&#34;#__codelineno-1-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// variable number of jumps forward&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-20&#34;&gt;&lt;a id=&#34;__codelineno-1-20&#34; name=&#34;__codelineno-1-20&#34; href=&#34;#__codelineno-1-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;varjump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-21&#34;&gt;&lt;a id=&#34;__codelineno-1-21&#34; name=&#34;__codelineno-1-21&#34; href=&#34;#__codelineno-1-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;varjump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;varjump_1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-22&#34;&gt;&lt;a id=&#34;__codelineno-1-22&#34; name=&#34;__codelineno-1-22&#34; href=&#34;#__codelineno-1-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// ...&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-23&#34;&gt;&lt;a id=&#34;__codelineno-1-23&#34; name=&#34;__codelineno-1-23&#34; href=&#34;#__codelineno-1-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;varjump_k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-24&#34;&gt;&lt;a id=&#34;__codelineno-1-24&#34; name=&#34;__codelineno-1-24&#34; href=&#34;#__codelineno-1-24&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-25&#34;&gt;&lt;a id=&#34;__codelineno-1-25&#34; name=&#34;__codelineno-1-25&#34; href=&#34;#__codelineno-1-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// step 4.&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-26&#34;&gt;&lt;a id=&#34;__codelineno-1-26&#34; name=&#34;__codelineno-1-26&#34; href=&#34;#__codelineno-1-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// conditional branch&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-27&#34;&gt;&lt;a id=&#34;__codelineno-1-27&#34; name=&#34;__codelineno-1-27&#34; href=&#34;#__codelineno-1-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-28&#34;&gt;&lt;a id=&#34;__codelineno-1-28&#34; name=&#34;__codelineno-1-28&#34; href=&#34;#__codelineno-1-28&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-29&#34;&gt;&lt;a id=&#34;__codelineno-1-29&#34; name=&#34;__codelineno-1-29&#34; href=&#34;#__codelineno-1-29&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;第二步中条件分支跳转与否，会影响分支历史中 &lt;span class=&#34;arithmatex&#34;&gt;\(B[i]\)&lt;/span&gt; 一个位的变化，它会经过哈希函数，影响 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{footprint}\)&lt;/span&gt;，进而异或到 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 中。通过调整第三步执行的无条件分支个数，可以把 &lt;span class=&#34;arithmatex&#34;&gt;\(B[i]\)&lt;/span&gt; 对 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 的影响左移到不同的位置。如果 &lt;span class=&#34;arithmatex&#34;&gt;\(B[i]\)&lt;/span&gt; 对 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 造成了影响，就可以正确预测最后一条条件分支指令的方向。当左移次数足够多时，&lt;span class=&#34;arithmatex&#34;&gt;\(B[i]\)&lt;/span&gt; 对 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 的贡献会变为零，此时对最后一条条件分支指令的方向预测只有 50% 的正确率。在 Apple M1 Firestorm 上&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/phr_branch_bits_location_gen.cpp&#34;&gt;测试&lt;/a&gt;，得到如下结果：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../cbp-reverse-engineer-phrb.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;横坐标 &lt;code&gt;Dummy branches&lt;/code&gt; 指的是上面第三步插入的无条件分支的个数，纵坐标 &lt;code&gt;Branch toggle bit&lt;/code&gt; 代表修改的是具体哪一个 &lt;span class=&#34;arithmatex&#34;&gt;\(B[i]\)&lt;/span&gt;，颜色对应分支预测的错误率，浅色部分对应最后一条分支只能正确预测 50%，深色部分对应最后一条分支总是可以正确预测。&lt;/p&gt; &lt;p&gt;从这个图可以得到什么信息呢？首先观察 &lt;span class=&#34;arithmatex&#34;&gt;\(B[2]\)&lt;/span&gt; 对应的这一行，可以看到它确实参与到了 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 的计算中，但是仅仅经过 28 次移位，这个贡献就被移出了 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt;，为了保留在 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 内，最多移动 27 次。类似地，在移出 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 之前，&lt;span class=&#34;arithmatex&#34;&gt;\(B[3]\)&lt;/span&gt; 最多移动 26 次，&lt;span class=&#34;arithmatex&#34;&gt;\(B[4]\)&lt;/span&gt; 最多移动 25 次，&lt;span class=&#34;arithmatex&#34;&gt;\(B[5]\)&lt;/span&gt; 最多移动 24 次。&lt;/p&gt; &lt;p&gt;但实际上，这些 &lt;span class=&#34;arithmatex&#34;&gt;\(B\)&lt;/span&gt; 是同时进入 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 的：这暗示它们对应 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{footprint}\)&lt;/span&gt; 的不同位置。如果某个 &lt;span class=&#34;arithmatex&#34;&gt;\(B[i]\)&lt;/span&gt; 出现在 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{footprint}\)&lt;/span&gt; 更高位的地方，它也会进入 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 更高位，经过更少的移位次数就会被移出 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt;；反之，如果 &lt;span class=&#34;arithmatex&#34;&gt;\(B[i]\)&lt;/span&gt; 出现在 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{footprint}\)&lt;/span&gt; 更低位的地方，它能够在 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 中停留更长的时间。&lt;/p&gt; &lt;p&gt;根据上面的实验，可见 &lt;span class=&#34;arithmatex&#34;&gt;\(B[5], B[4], B[3], B[2]\)&lt;/span&gt; 参与到了 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{footprint}\)&lt;/span&gt; 计算中，而 &lt;span class=&#34;arithmatex&#34;&gt;\(B\)&lt;/span&gt; 的其他位则没有。但比较奇怪的是，&lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 理应可以记录最近 100 条分支的信息，但实际上只观察到了 28。所以一定还有其他的信息。&lt;/p&gt; &lt;h3 id=&#34;目的地址-t-的贡献&#34;&gt;目的地址 T 的贡献&lt;a class=&#34;headerlink&#34; href=&#34;#目的地址-t-的贡献&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;刚刚测试了 &lt;span class=&#34;arithmatex&#34;&gt;\(B\)&lt;/span&gt;，接下来测试 &lt;span class=&#34;arithmatex&#34;&gt;\(T\)&lt;/span&gt; 各位对 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 的贡献，方法类似：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;为了让 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 进入一个稳定的初始值，执行 100 个无条件分支；&lt;/li&gt; &lt;li&gt;设计一个间接分支，根据随机数，随机跳转到两个不同的目的地址，这两个目的地址只在 &lt;span class=&#34;arithmatex&#34;&gt;\(T[i]\)&lt;/span&gt; 上不同，其余的位都相同，分支地址相同；&lt;/li&gt; &lt;li&gt;执行若干条无条件分支，目的是把 &lt;span class=&#34;arithmatex&#34;&gt;\(T[i]\)&lt;/span&gt; 对 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 的贡献向前移动；&lt;/li&gt; &lt;li&gt;执行一条条件分支指令，其跳转方向取决于第二步中间接分支所使用的随机数。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;对应的代码如下：&lt;/p&gt; &lt;div class=&#34;language-c highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-2-1&#34;&gt;&lt;a id=&#34;__codelineno-2-1&#34; name=&#34;__codelineno-2-1&#34; href=&#34;#__codelineno-2-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// step 1.&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-2&#34;&gt;&lt;a id=&#34;__codelineno-2-2&#34; name=&#34;__codelineno-2-2&#34; href=&#34;#__codelineno-2-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// 100 jumps forward&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-3&#34;&gt;&lt;a id=&#34;__codelineno-2-3&#34; name=&#34;__codelineno-2-3&#34; href=&#34;#__codelineno-2-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-4&#34;&gt;&lt;a id=&#34;__codelineno-2-4&#34; name=&#34;__codelineno-2-4&#34; href=&#34;#__codelineno-2-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;jump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jump_1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-5&#34;&gt;&lt;a id=&#34;__codelineno-2-5&#34; name=&#34;__codelineno-2-5&#34; href=&#34;#__codelineno-2-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// ...&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-6&#34;&gt;&lt;a id=&#34;__codelineno-2-6&#34; name=&#34;__codelineno-2-6&#34; href=&#34;#__codelineno-2-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;jump_98&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jump_99&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-7&#34;&gt;&lt;a id=&#34;__codelineno-2-7&#34; name=&#34;__codelineno-2-7&#34; href=&#34;#__codelineno-2-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;jump_99&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-8&#34;&gt;&lt;a id=&#34;__codelineno-2-8&#34; name=&#34;__codelineno-2-8&#34; href=&#34;#__codelineno-2-8&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-9&#34;&gt;&lt;a id=&#34;__codelineno-2-9&#34; name=&#34;__codelineno-2-9&#34; href=&#34;#__codelineno-2-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// step 2.&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-10&#34;&gt;&lt;a id=&#34;__codelineno-2-10&#34; name=&#34;__codelineno-2-10&#34; href=&#34;#__codelineno-2-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rand&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-11&#34;&gt;&lt;a id=&#34;__codelineno-2-11&#34; name=&#34;__codelineno-2-11&#34; href=&#34;#__codelineno-2-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// indirect branch&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-12&#34;&gt;&lt;a id=&#34;__codelineno-2-12&#34; name=&#34;__codelineno-2-12&#34; href=&#34;#__codelineno-2-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// the follow two targets differ in T[i]&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-13&#34;&gt;&lt;a id=&#34;__codelineno-2-13&#34; name=&#34;__codelineno-2-13&#34; href=&#34;#__codelineno-2-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;auto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-14&#34;&gt;&lt;a id=&#34;__codelineno-2-14&#34; name=&#34;__codelineno-2-14&#34; href=&#34;#__codelineno-2-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-15&#34;&gt;&lt;a id=&#34;__codelineno-2-15&#34; name=&#34;__codelineno-2-15&#34; href=&#34;#__codelineno-2-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;target0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-16&#34;&gt;&lt;a id=&#34;__codelineno-2-16&#34; name=&#34;__codelineno-2-16&#34; href=&#34;#__codelineno-2-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// add many nops&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-17&#34;&gt;&lt;a id=&#34;__codelineno-2-17&#34; name=&#34;__codelineno-2-17&#34; href=&#34;#__codelineno-2-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;target1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-18&#34;&gt;&lt;a id=&#34;__codelineno-2-18&#34; name=&#34;__codelineno-2-18&#34; href=&#34;#__codelineno-2-18&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-19&#34;&gt;&lt;a id=&#34;__codelineno-2-19&#34; name=&#34;__codelineno-2-19&#34; href=&#34;#__codelineno-2-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// step 3.&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-20&#34;&gt;&lt;a id=&#34;__codelineno-2-20&#34; name=&#34;__codelineno-2-20&#34; href=&#34;#__codelineno-2-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// variable number of jumps forward&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-21&#34;&gt;&lt;a id=&#34;__codelineno-2-21&#34; name=&#34;__codelineno-2-21&#34; href=&#34;#__codelineno-2-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;varjump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-22&#34;&gt;&lt;a id=&#34;__codelineno-2-22&#34; name=&#34;__codelineno-2-22&#34; href=&#34;#__codelineno-2-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;varjump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;varjump_1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-23&#34;&gt;&lt;a id=&#34;__codelineno-2-23&#34; name=&#34;__codelineno-2-23&#34; href=&#34;#__codelineno-2-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// ...&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-24&#34;&gt;&lt;a id=&#34;__codelineno-2-24&#34; name=&#34;__codelineno-2-24&#34; href=&#34;#__codelineno-2-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;varjump_k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-25&#34;&gt;&lt;a id=&#34;__codelineno-2-25&#34; name=&#34;__codelineno-2-25&#34; href=&#34;#__codelineno-2-25&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-26&#34;&gt;&lt;a id=&#34;__codelineno-2-26&#34; name=&#34;__codelineno-2-26&#34; href=&#34;#__codelineno-2-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// step 4.&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-27&#34;&gt;&lt;a id=&#34;__codelineno-2-27&#34; name=&#34;__codelineno-2-27&#34; href=&#34;#__codelineno-2-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// conditional branch&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-28&#34;&gt;&lt;a id=&#34;__codelineno-2-28&#34; name=&#34;__codelineno-2-28&#34; href=&#34;#__codelineno-2-28&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-29&#34;&gt;&lt;a id=&#34;__codelineno-2-29&#34; name=&#34;__codelineno-2-29&#34; href=&#34;#__codelineno-2-29&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-30&#34;&gt;&lt;a id=&#34;__codelineno-2-30&#34; name=&#34;__codelineno-2-30&#34; href=&#34;#__codelineno-2-30&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;在 Apple M1 Firestorm 上&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/phr_target_bits_location_gen.cpp&#34;&gt;测试&lt;/a&gt;，得到如下结果：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../cbp-reverse-engineer-phrt.png&#34; /&gt;&lt;/p&gt; &lt;details class=&#34;question&#34;&gt; &lt;summary&gt;为了测试 T[31]，岂不是要插入很多个 NOP，一方面二进制很大，其次还要执行很长时间？&lt;/summary&gt; &lt;p&gt;是的，所以这里在测试的时候，采用的是类似 JIT 的方法，通过 mmap &lt;code&gt;MAP_FIXED&lt;/code&gt; 在内存中特定位置分配并写入代码，避免了用汇编器生成一个巨大的 ELF。同时，为了避免执行大量的 NOP，考虑到前面已经发现 &lt;span class=&#34;arithmatex&#34;&gt;\(B[6]\)&lt;/span&gt; 或更高的位没有参与到 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 计算中，所以可以添加额外的一组无条件分支来跳过大量的 NOP，它们的目的地址相同，分支地址低位相同，因此对 PHR 不会产生影响。对应的代码如下：&lt;/p&gt; &lt;div class=&#34;language-c highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-3-1&#34;&gt;&lt;a id=&#34;__codelineno-3-1&#34; name=&#34;__codelineno-3-1&#34; href=&#34;#__codelineno-3-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// step 1.&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-2&#34;&gt;&lt;a id=&#34;__codelineno-3-2&#34; name=&#34;__codelineno-3-2&#34; href=&#34;#__codelineno-3-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// 100 jumps forward&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-3&#34;&gt;&lt;a id=&#34;__codelineno-3-3&#34; name=&#34;__codelineno-3-3&#34; href=&#34;#__codelineno-3-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-4&#34;&gt;&lt;a id=&#34;__codelineno-3-4&#34; name=&#34;__codelineno-3-4&#34; href=&#34;#__codelineno-3-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;jump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jump_1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-5&#34;&gt;&lt;a id=&#34;__codelineno-3-5&#34; name=&#34;__codelineno-3-5&#34; href=&#34;#__codelineno-3-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// ...&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-6&#34;&gt;&lt;a id=&#34;__codelineno-3-6&#34; name=&#34;__codelineno-3-6&#34; href=&#34;#__codelineno-3-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;jump_98&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jump_99&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-7&#34;&gt;&lt;a id=&#34;__codelineno-3-7&#34; name=&#34;__codelineno-3-7&#34; href=&#34;#__codelineno-3-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;jump_99&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-8&#34;&gt;&lt;a id=&#34;__codelineno-3-8&#34; name=&#34;__codelineno-3-8&#34; href=&#34;#__codelineno-3-8&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-9&#34;&gt;&lt;a id=&#34;__codelineno-3-9&#34; name=&#34;__codelineno-3-9&#34; href=&#34;#__codelineno-3-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// step 2.&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-10&#34;&gt;&lt;a id=&#34;__codelineno-3-10&#34; name=&#34;__codelineno-3-10&#34; href=&#34;#__codelineno-3-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rand&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-11&#34;&gt;&lt;a id=&#34;__codelineno-3-11&#34; name=&#34;__codelineno-3-11&#34; href=&#34;#__codelineno-3-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// indirect branch&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-12&#34;&gt;&lt;a id=&#34;__codelineno-3-12&#34; name=&#34;__codelineno-3-12&#34; href=&#34;#__codelineno-3-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// the follow two targets differ in T[i]&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-13&#34;&gt;&lt;a id=&#34;__codelineno-3-13&#34; name=&#34;__codelineno-3-13&#34; href=&#34;#__codelineno-3-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;auto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-14&#34;&gt;&lt;a id=&#34;__codelineno-3-14&#34; name=&#34;__codelineno-3-14&#34; href=&#34;#__codelineno-3-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-15&#34;&gt;&lt;a id=&#34;__codelineno-3-15&#34; name=&#34;__codelineno-3-15&#34; href=&#34;#__codelineno-3-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;target0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-16&#34;&gt;&lt;a id=&#34;__codelineno-3-16&#34; name=&#34;__codelineno-3-16&#34; href=&#34;#__codelineno-3-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// skip over nops, while keeping B[5:2]=0&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-17&#34;&gt;&lt;a id=&#34;__codelineno-3-17&#34; name=&#34;__codelineno-3-17&#34; href=&#34;#__codelineno-3-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-18&#34;&gt;&lt;a id=&#34;__codelineno-3-18&#34; name=&#34;__codelineno-3-18&#34; href=&#34;#__codelineno-3-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// add many nops&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-19&#34;&gt;&lt;a id=&#34;__codelineno-3-19&#34; name=&#34;__codelineno-3-19&#34; href=&#34;#__codelineno-3-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;target1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-20&#34;&gt;&lt;a id=&#34;__codelineno-3-20&#34; name=&#34;__codelineno-3-20&#34; href=&#34;#__codelineno-3-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-21&#34;&gt;&lt;a id=&#34;__codelineno-3-21&#34; name=&#34;__codelineno-3-21&#34; href=&#34;#__codelineno-3-21&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-22&#34;&gt;&lt;a id=&#34;__codelineno-3-22&#34; name=&#34;__codelineno-3-22&#34; href=&#34;#__codelineno-3-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;target2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-23&#34;&gt;&lt;a id=&#34;__codelineno-3-23&#34; name=&#34;__codelineno-3-23&#34; href=&#34;#__codelineno-3-23&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-24&#34;&gt;&lt;a id=&#34;__codelineno-3-24&#34; name=&#34;__codelineno-3-24&#34; href=&#34;#__codelineno-3-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// step 3.&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-25&#34;&gt;&lt;a id=&#34;__codelineno-3-25&#34; name=&#34;__codelineno-3-25&#34; href=&#34;#__codelineno-3-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// variable number of jumps forward&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-26&#34;&gt;&lt;a id=&#34;__codelineno-3-26&#34; name=&#34;__codelineno-3-26&#34; href=&#34;#__codelineno-3-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;varjump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-27&#34;&gt;&lt;a id=&#34;__codelineno-3-27&#34; name=&#34;__codelineno-3-27&#34; href=&#34;#__codelineno-3-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;varjump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;varjump_1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-28&#34;&gt;&lt;a id=&#34;__codelineno-3-28&#34; name=&#34;__codelineno-3-28&#34; href=&#34;#__codelineno-3-28&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// ...&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-29&#34;&gt;&lt;a id=&#34;__codelineno-3-29&#34; name=&#34;__codelineno-3-29&#34; href=&#34;#__codelineno-3-29&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;varjump_k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-30&#34;&gt;&lt;a id=&#34;__codelineno-3-30&#34; name=&#34;__codelineno-3-30&#34; href=&#34;#__codelineno-3-30&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-31&#34;&gt;&lt;a id=&#34;__codelineno-3-31&#34; name=&#34;__codelineno-3-31&#34; href=&#34;#__codelineno-3-31&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// step 4.&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-32&#34;&gt;&lt;a id=&#34;__codelineno-3-32&#34; name=&#34;__codelineno-3-32&#34; href=&#34;#__codelineno-3-32&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// conditional branch&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-33&#34;&gt;&lt;a id=&#34;__codelineno-3-33&#34; name=&#34;__codelineno-3-33&#34; href=&#34;#__codelineno-3-33&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-34&#34;&gt;&lt;a id=&#34;__codelineno-3-34&#34; name=&#34;__codelineno-3-34&#34; href=&#34;#__codelineno-3-34&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-35&#34;&gt;&lt;a id=&#34;__codelineno-3-35&#34; name=&#34;__codelineno-3-35&#34; href=&#34;#__codelineno-3-35&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;/details&gt; &lt;p&gt;由此我们终于找到了分支历史最长记录 100 条分支的来源：&lt;span class=&#34;arithmatex&#34;&gt;\(T[2]\)&lt;/span&gt; 会经过 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{footprint}\)&lt;/span&gt; 被异或到 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 的最低位，然后每次执行一个跳转分支左移一次，直到移动 100 次才被移出 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt;。类似地，&lt;span class=&#34;arithmatex&#34;&gt;\(T[3]\)&lt;/span&gt; 只需要 99 次就能移出 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt;，说明 &lt;span class=&#34;arithmatex&#34;&gt;\(T[3]\)&lt;/span&gt; 被异或到了 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}[1]\)&lt;/span&gt;。依此类推，可以知道涉及 &lt;span class=&#34;arithmatex&#34;&gt;\(T\)&lt;/span&gt; 的 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{footprint} = T[31:2]\)&lt;/span&gt;，其中 &lt;span class=&#34;arithmatex&#34;&gt;\(T[31:2]\)&lt;/span&gt; 代表一个 30 位的数，每一位从高到低分别对应 &lt;span class=&#34;arithmatex&#34;&gt;\(T[31], T[30], \cdots, T[2]\)&lt;/span&gt;。&lt;/p&gt; &lt;h3 id=&#34;小结&#34;&gt;小结&lt;a class=&#34;headerlink&#34; href=&#34;#小结&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;那么问题来了，前面测试 &lt;span class=&#34;arithmatex&#34;&gt;\(B\)&lt;/span&gt; 的时候，移位次数那么少，明显少于 &lt;span class=&#34;arithmatex&#34;&gt;\(T\)&lt;/span&gt; 的移位次数。这有两种可能：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;硬件上只有一个 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 寄存器，&lt;span class=&#34;arithmatex&#34;&gt;\(T[31:2]\)&lt;/span&gt; 被异或到 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 的低位，而 &lt;span class=&#34;arithmatex&#34;&gt;\(B[5:2]\)&lt;/span&gt; 被异或到 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 的中间位置；&lt;/li&gt; &lt;li&gt;硬件上有两个 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHR}\)&lt;/span&gt; 寄存器，其中一个是 100 位，它的 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{footprint} = T[31:2]\)&lt;/span&gt;，记为 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHRT}\)&lt;/span&gt;；另一个是 28 位，它的 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{footprint} = B[5:2]\)&lt;/span&gt;，记为 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHRB}\)&lt;/span&gt;。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;经过后续的测试，基本确认硬件实现的是第二种。用数学公式表达：&lt;/p&gt; &lt;p&gt;&lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHRT}_{\mathrm{new}} = (\mathrm{PHRT}_{\mathrm{old}} \ll 1) \oplus \mathrm{T}[31:2]\)&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHRB}_{\mathrm{new}} = (\mathrm{PHRB}_{\mathrm{old}} \ll 1) \oplus \mathrm{B}[5:2]\)&lt;/span&gt;&lt;/p&gt; &lt;p&gt;有意思的是，在我的论文发表后不久，Apple 公开的专利 &lt;a href=&#34;https://patents.google.com/patent/US12159142B1/en&#34;&gt;Managing table accesses for tagged geometric length (TAGE) load value prediction&lt;/a&gt; 中就出现了相关表述，证明了逆向结果的正确性。&lt;/p&gt; &lt;p&gt;按照这个方法，我还逆向工程了 Apple、Qualcomm、ARM 和 Intel 的多代处理器的分支历史记录方法，&lt;a href=&#34;https://jia.je/cpu/cbp.html&#34;&gt;并进行了公开&lt;/a&gt;，供感兴趣的读者阅读，也欢迎读者将测试代码移植到更多处理器上，并贡献逆向工程的结果。&lt;/p&gt; &lt;h2 id=&#34;tage-表的逆向&#34;&gt;TAGE 表的逆向&lt;a class=&#34;headerlink&#34; href=&#34;#tage-表的逆向&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;接下来，我们将目光转向 TAGE 表的逆向工程。TAGE 表与缓存结构类似，也是一个多路组相连的结构，通过 index 访问若干路，然后对每一路进行 tag 匹配，匹配正确的那一路提供预测。TAGE 在预测时，输入是历史寄存器，即上面逆向得到的 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHRT}\)&lt;/span&gt; 和 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHRB}\)&lt;/span&gt;，以及分支地址，目前这两个输入都是可控的。为了避免多个表同时提供预测，首先逆向工程使用分支历史最长的表的参数：它的容量是多少，index 如何计算，tag 如何计算，以及几路组相连。&lt;/p&gt; &lt;p&gt;如何确保使用分支历史最长的表提供预测呢？其实还是利用分支历史的特性，将随机数注入到 &lt;span class=&#34;arithmatex&#34;&gt;\(PHRT\)&lt;/span&gt; 中，例如前面的间接分支，让两个目的地址只在 &lt;span class=&#34;arithmatex&#34;&gt;\(T[2]\)&lt;/span&gt; 上不同：&lt;/p&gt; &lt;div class=&#34;language-c highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-4-1&#34;&gt;&lt;a id=&#34;__codelineno-4-1&#34; name=&#34;__codelineno-4-1&#34; href=&#34;#__codelineno-4-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// add some unconditional jumps to reset phr to some constant value&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-2&#34;&gt;&lt;a id=&#34;__codelineno-4-2&#34; name=&#34;__codelineno-4-2&#34; href=&#34;#__codelineno-4-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// 100 jumps forward&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-3&#34;&gt;&lt;a id=&#34;__codelineno-4-3&#34; name=&#34;__codelineno-4-3&#34; href=&#34;#__codelineno-4-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-4&#34;&gt;&lt;a id=&#34;__codelineno-4-4&#34; name=&#34;__codelineno-4-4&#34; href=&#34;#__codelineno-4-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;jump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jump_1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-5&#34;&gt;&lt;a id=&#34;__codelineno-4-5&#34; name=&#34;__codelineno-4-5&#34; href=&#34;#__codelineno-4-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// ...&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-6&#34;&gt;&lt;a id=&#34;__codelineno-4-6&#34; name=&#34;__codelineno-4-6&#34; href=&#34;#__codelineno-4-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;jump_98&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jump_99&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-7&#34;&gt;&lt;a id=&#34;__codelineno-4-7&#34; name=&#34;__codelineno-4-7&#34; href=&#34;#__codelineno-4-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;jump_99&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-8&#34;&gt;&lt;a id=&#34;__codelineno-4-8&#34; name=&#34;__codelineno-4-8&#34; href=&#34;#__codelineno-4-8&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-9&#34;&gt;&lt;a id=&#34;__codelineno-4-9&#34; name=&#34;__codelineno-4-9&#34; href=&#34;#__codelineno-4-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// inject&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-10&#34;&gt;&lt;a id=&#34;__codelineno-4-10&#34; name=&#34;__codelineno-4-10&#34; href=&#34;#__codelineno-4-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rand&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-11&#34;&gt;&lt;a id=&#34;__codelineno-4-11&#34; name=&#34;__codelineno-4-11&#34; href=&#34;#__codelineno-4-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// indirect branch&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-12&#34;&gt;&lt;a id=&#34;__codelineno-4-12&#34; name=&#34;__codelineno-4-12&#34; href=&#34;#__codelineno-4-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// the follow two targets differ in T[2]&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-13&#34;&gt;&lt;a id=&#34;__codelineno-4-13&#34; name=&#34;__codelineno-4-13&#34; href=&#34;#__codelineno-4-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;auto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-14&#34;&gt;&lt;a id=&#34;__codelineno-4-14&#34; name=&#34;__codelineno-4-14&#34; href=&#34;#__codelineno-4-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-15&#34;&gt;&lt;a id=&#34;__codelineno-4-15&#34; name=&#34;__codelineno-4-15&#34; href=&#34;#__codelineno-4-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;target0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-16&#34;&gt;&lt;a id=&#34;__codelineno-4-16&#34; name=&#34;__codelineno-4-16&#34; href=&#34;#__codelineno-4-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// add nop here&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-17&#34;&gt;&lt;a id=&#34;__codelineno-4-17&#34; name=&#34;__codelineno-4-17&#34; href=&#34;#__codelineno-4-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;target1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-18&#34;&gt;&lt;a id=&#34;__codelineno-4-18&#34; name=&#34;__codelineno-4-18&#34; href=&#34;#__codelineno-4-18&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-19&#34;&gt;&lt;a id=&#34;__codelineno-4-19&#34; name=&#34;__codelineno-4-19&#34; href=&#34;#__codelineno-4-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// add some unconditional jumps to shift the injected bit left&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-20&#34;&gt;&lt;a id=&#34;__codelineno-4-20&#34; name=&#34;__codelineno-4-20&#34; href=&#34;#__codelineno-4-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;varjump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-21&#34;&gt;&lt;a id=&#34;__codelineno-4-21&#34; name=&#34;__codelineno-4-21&#34; href=&#34;#__codelineno-4-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;varjump_0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;varjump_1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-22&#34;&gt;&lt;a id=&#34;__codelineno-4-22&#34; name=&#34;__codelineno-4-22&#34; href=&#34;#__codelineno-4-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// ...&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-23&#34;&gt;&lt;a id=&#34;__codelineno-4-23&#34; name=&#34;__codelineno-4-23&#34; href=&#34;#__codelineno-4-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;varjump_k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-24&#34;&gt;&lt;a id=&#34;__codelineno-4-24&#34; name=&#34;__codelineno-4-24&#34; href=&#34;#__codelineno-4-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;last&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;根据前面的分析，&lt;span class=&#34;arithmatex&#34;&gt;\(T[2]\)&lt;/span&gt; 会被异或到 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHRT}\)&lt;/span&gt; 的最低位上，每执行一次无条件分支，就左移一位。因此，通过若干个无条件分支，可以把 &lt;code&gt;d % 2&lt;/code&gt; 这个随机数注入到 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHRT}\)&lt;/span&gt; 的任意一位上。之后我们还会很多次地进行这种随机数的注入。&lt;/p&gt; &lt;p&gt;把随机数注入到 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHRT}\)&lt;/span&gt; 高位以后，再预测一个根据随机数跳转或不跳转的分支，就可以保证它只能由使用分支历史最长的表来进行预测。&lt;/p&gt; &lt;h3 id=&#34;逆向工程-pc-输入&#34;&gt;逆向工程 PC 输入&lt;a class=&#34;headerlink&#34; href=&#34;#逆向工程-pc-输入&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;首先，我们希望推断 PC 如何参与到 index 或 tag 计算中。通常，TAGE 只会采用一部分 PC 位参与 index 或 tag 计算。换句话说，如果两个分支在 PC 上不同的部分没有参与 index 或 tag 计算，那么 TAGE 无法区分这两条分支。如果这两个分支跳转方向相反，并且用相同的 PHR 进行预测，那么一定会出现错误的预测。思路如下：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;用 100 个无条件分支，保证 PHR 变成一个确定的值；&lt;/li&gt; &lt;li&gt;注入随机数 &lt;code&gt;d % 2&lt;/code&gt; 到 PHRT，并移动到高位（例如 &lt;span class=&#34;arithmatex&#34;&gt;\(PHRT[99]\)&lt;/span&gt;），使用前面所述的方法；&lt;/li&gt; &lt;li&gt;执行两个条件分支，它们在分支地址上只有一位 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[i]\)&lt;/span&gt; 不同，它们的跳转条件相反，当第一个条件分支不跳转的时候，会执行第二个条件分支，它总是会跳转。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;对应代码类似于：&lt;/p&gt; &lt;div class=&#34;language-c highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-5-1&#34;&gt;&lt;a id=&#34;__codelineno-5-1&#34; name=&#34;__codelineno-5-1&#34; href=&#34;#__codelineno-5-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// step 1. inject phrt&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-2&#34;&gt;&lt;a id=&#34;__codelineno-5-2&#34; name=&#34;__codelineno-5-2&#34; href=&#34;#__codelineno-5-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rand&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-3&#34;&gt;&lt;a id=&#34;__codelineno-5-3&#34; name=&#34;__codelineno-5-3&#34; href=&#34;#__codelineno-5-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;inject_phrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;99&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-4&#34;&gt;&lt;a id=&#34;__codelineno-5-4&#34; name=&#34;__codelineno-5-4&#34; href=&#34;#__codelineno-5-4&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-5&#34;&gt;&lt;a id=&#34;__codelineno-5-5&#34; name=&#34;__codelineno-5-5&#34; href=&#34;#__codelineno-5-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// step 2. a pair of conditional branches with different direction&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-6&#34;&gt;&lt;a id=&#34;__codelineno-5-6&#34; name=&#34;__codelineno-5-6&#34; href=&#34;#__codelineno-5-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// their PC differs in one bit&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-7&#34;&gt;&lt;a id=&#34;__codelineno-5-7&#34; name=&#34;__codelineno-5-7&#34; href=&#34;#__codelineno-5-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-8&#34;&gt;&lt;a id=&#34;__codelineno-5-8&#34; name=&#34;__codelineno-5-8&#34; href=&#34;#__codelineno-5-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-9&#34;&gt;&lt;a id=&#34;__codelineno-5-9&#34; name=&#34;__codelineno-5-9&#34; href=&#34;#__codelineno-5-9&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-10&#34;&gt;&lt;a id=&#34;__codelineno-5-10&#34; name=&#34;__codelineno-5-10&#34; href=&#34;#__codelineno-5-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;经过测试，PC 的输入是 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[18:2]\)&lt;/span&gt;，其余的没有。&lt;/p&gt; &lt;h3 id=&#34;逆向工程相连度和-index-函数的-pc-输入&#34;&gt;逆向工程相连度和 index 函数的 PC 输入&lt;a class=&#34;headerlink&#34; href=&#34;#逆向工程相连度和-index-函数的-pc-输入&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;接下来是比较复杂的一步，同时逆向工程表的相连度和 index 函数的 PC 输入。这是因为这两部分是紧密耦合的：只有知道相连度，才能知道预测出来的分支数对应几个 set；但不知道 index 函数，又无法控制分支被分配到几个 set 中。首先，为了避免 PHR 的干扰，还是只注入一个随机数到 &lt;span class=&#34;arithmatex&#34;&gt;\(PHRT[99]\)&lt;/span&gt; 上（事实上，&lt;span class=&#34;arithmatex&#34;&gt;\(PHRT[99]\)&lt;/span&gt; 不是随便选择的，而是需要在 index 函数中，但通过测试可以找到满足要求的位）。其次，构造一系列分支，它们的地址满足：第 i 条分支（i 从 0 开始）的分支地址是 &lt;span class=&#34;arithmatex&#34;&gt;\(i2^k\)&lt;/span&gt;，其中 &lt;span class=&#34;arithmatex&#34;&gt;\(k\)&lt;/span&gt; 是接下来要遍历的参数。当 &lt;span class=&#34;arithmatex&#34;&gt;\(k=3\)&lt;/span&gt; 时，分支会被放到 &lt;code&gt;0x0, 0x8, 0x10, 0x18, 0x20&lt;/code&gt; 等地址，涉及的 PC 位数随着分支数的增加而增加。接下来，我们分类讨论：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;假如涉及的 PC 位都在 tag 中，没有出现在 index 中：那么这些分支都会被映射到同一个 set 内，一旦分支数量超出相连度，就会出现预测错误。&lt;/li&gt; &lt;li&gt;假如涉及的 PC 位有一部分出现在 index 中：那么每有一个 PC 位出现在 index 中，这些分支可以被分配到的 set 数量就翻倍，直到这些 set 都满了以后，才会出现预测错误。&lt;/li&gt; &lt;li&gt;假如涉及的 PC 位有一部分超出 PC 输入的范围（如前面逆向工程得到的 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[18:2]\)&lt;/span&gt;）：那么超出输入的部分地址会被忽略，使得 set 内出现冲突。&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/pht_associativity_gen.cpp&#34;&gt;实验&lt;/a&gt;结果如下图：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../cbp-reverse-engineer-assoc.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;纵坐标就是上面的 &lt;span class=&#34;arithmatex&#34;&gt;\(k\)&lt;/span&gt;，横坐标是测试的条件分支数，颜色表示预测的错误率。当颜色从深色变浅，就说明出现了预测错误。观察：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;span class=&#34;arithmatex&#34;&gt;\(PC[3]\)&lt;/span&gt; 的情况下，只能预测 4 个分支，而 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[4]\)&lt;/span&gt; 或 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[5]\)&lt;/span&gt; 可以预测 8 个分支，暗示了四路组相连，然后 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[4]\)&lt;/span&gt; 和 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[5]\)&lt;/span&gt; 对应到了两个 set，所以能够正确预测 8 个分支。&lt;/li&gt; &lt;li&gt;&lt;span class=&#34;arithmatex&#34;&gt;\(PC[6]\)&lt;/span&gt; 的情况下，可以预测 16 个分支，对应 4 个 set；后续 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[7]\)&lt;/span&gt; 和 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[8]\)&lt;/span&gt; 又可以预测 8 个分支，对应 2 个 set；意味着 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[6]\)&lt;/span&gt; 在 index 中，给 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[4]\)&lt;/span&gt; 和 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[5]\)&lt;/span&gt; 提供了两倍的 set；&lt;span class=&#34;arithmatex&#34;&gt;\(PC[9]\)&lt;/span&gt; 在 index 中，给 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[6]\)&lt;/span&gt;、&lt;span class=&#34;arithmatex&#34;&gt;\(PC[7]\)&lt;/span&gt; 和 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[8]\)&lt;/span&gt; 提供了两倍的 set。&lt;/li&gt; &lt;li&gt;后续更高的 PC 位，没有受到 index 函数的影响，因此都是 4，直到最后超出 PC 输入范围。&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;这就说明它是四路组相连，PC[6] 和 PC[9] 参与到了 index 函数中。&lt;/p&gt; &lt;p&gt;下面给读者一个小练习，下面是在 Qualcomm Oryon 上测得的结果，可以看到噪声比较大，你能推断出它是几路组相连，有哪些 PC 参与到了 index 计算吗？&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../cbp-reverse-engineer-assoc-oryon.png&#34; /&gt;&lt;/p&gt; &lt;details class=&#34;question&#34;&gt; &lt;summary&gt;揭晓答案&lt;/summary&gt; &lt;p&gt;四路组相连，&lt;span class=&#34;arithmatex&#34;&gt;\(PC[6]\)&lt;/span&gt; 和 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[7]\)&lt;/span&gt; 参与到了 index 函数。&lt;/p&gt; &lt;/details&gt; &lt;p&gt;那么，这种测试是怎么构造的呢？即需要用相同的 PHR 去预测 &lt;span class=&#34;arithmatex&#34;&gt;\(PC=i2^k\)&lt;/span&gt; 的多条分支。思路比较复杂：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;首先执行一条间接分支，目的地址是 &lt;span class=&#34;arithmatex&#34;&gt;\(i2^{k-1}\)&lt;/span&gt;，那么它对 PHRT 的贡献是 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHRT}_1 = (\mathrm{PHRT}_0 \ll 1) \oplus (i2^{k-3})\)&lt;/span&gt;；&lt;/li&gt; &lt;li&gt;接下来，在 &lt;span class=&#34;arithmatex&#34;&gt;\(i2^{k-1}\)&lt;/span&gt; 的位置，再执行一条直接分支，目的地址是 &lt;span class=&#34;arithmatex&#34;&gt;\(i2^k\)&lt;/span&gt;，那么它对 PHRT 的贡献是 &lt;span class=&#34;arithmatex&#34;&gt;\(\mathrm{PHRT}_2 = (\mathrm{PHRT}_1 \ll 1) \oplus (i2^{k-2}) = (((\mathrm{PHRT}_0 \ll 1) \oplus (i2^{k-3})) \ll 1) \oplus (i2^{k-2}) = \mathrm{PHRT}_0 \ll 2\)&lt;/span&gt;。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;可见经过两步以后，PHRT 是保持不变的。针对 PHRB，只要 &lt;span class=&#34;arithmatex&#34;&gt;\(i2^{k-1}\)&lt;/span&gt; 没有涉及 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[5:2]\)&lt;/span&gt;，就能保证相同。那么如果 &lt;span class=&#34;arithmatex&#34;&gt;\(k\)&lt;/span&gt; 足够小，也有办法：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;首先执行一条间接分支，目的地址是 &lt;span class=&#34;arithmatex&#34;&gt;\(i2^{k-1}\)&lt;/span&gt;；&lt;/li&gt; &lt;li&gt;接下来执行大量的 NOP，使得 &lt;span class=&#34;arithmatex&#34;&gt;\(B\)&lt;/span&gt; 的低位等于 0，然后再执行一条间接分支，目的地址是 &lt;span class=&#34;arithmatex&#34;&gt;\(i2^k\)&lt;/span&gt;。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;因此我们总是可以通过两次分支，实现用相同的 PHR 预测不同 PC 上的多条分支。&lt;/p&gt; &lt;h3 id=&#34;逆向工程-tag-函数&#34;&gt;逆向工程 tag 函数&lt;a class=&#34;headerlink&#34; href=&#34;#逆向工程-tag-函数&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;接下来，进行 tag 函数的逆向工程。为了逆向工程 tag 函数，我们希望找到两个位在 tag 函数中有异或关系，那么如果这两个位同时设为 0，或者同时设为 1，其异或结果都等于 0，使得计算出来的 tag 函数相同，如果此时 index 还相同，那么预测器就无法区分这两种情况。&lt;/p&gt; &lt;p&gt;为了利用这一点，生成两个 0 到 1 的随机数 &lt;span class=&#34;arithmatex&#34;&gt;\(k\)&lt;/span&gt; 和 &lt;span class=&#34;arithmatex&#34;&gt;\(l\)&lt;/span&gt;，分别把它们注入到 PC、PHRB 或者 PHRT 中，去预测一个条件分支，其跳转与否取决于 &lt;span class=&#34;arithmatex&#34;&gt;\(k\)&lt;/span&gt; 的值（论文中有个小 typo）。如果 &lt;span class=&#34;arithmatex&#34;&gt;\(k\)&lt;/span&gt; 和 &lt;span class=&#34;arithmatex&#34;&gt;\(l\)&lt;/span&gt; 在 tag 函数中有异或关系，那么预测器总会预测错误。&lt;/p&gt; &lt;p&gt;实验结果大致如下，横纵坐标表示注入哪一个位，颜色代表预测错误率，深色意味着预测错误，也就是找到了一组异或关系：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../cbp-reverse-engineer-assoc-tag-pc-phr.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../cbp-reverse-engineer-assoc-tag-phr-phr.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;其中有一些异或关系，因为对应的位在 index 中出现的缘故，导致没有显现出来。根据已知的异或关系外推，可以得到如下的 tag 计算公式：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;PC[7] xor PHRT[0,12,...,96] xor PHRB[8,21]&lt;/li&gt; &lt;li&gt;PC[8] xor PHRT[1,13,...,97] xor PHRB[9,22]&lt;/li&gt; &lt;li&gt;PC[9] xor PHRT[2,14,...,98] xor PHRB[10,23,24]&lt;/li&gt; &lt;li&gt;PC[10] xor PHRT[3,15,...,87,99] xor PHRB[11,12,25]&lt;/li&gt; &lt;li&gt;PC[11] xor PHRT[4,16,...,88] xor PHRB[0,13,26]&lt;/li&gt; &lt;li&gt;PC[12] xor PHRT[5,17,...,89] xor PHRB[1,14,27]&lt;/li&gt; &lt;li&gt;PC[13] xor PHRT[6,18,...,90] xor PHRB[2,15]&lt;/li&gt; &lt;li&gt;PC[14] xor PHRT[7,19,...,91] xor PHRB[3,16]&lt;/li&gt; &lt;li&gt;PC[15] xor PHRT[8,20,...,92] xor PHRB[4,17]&lt;/li&gt; &lt;li&gt;PC[16] xor PHRT[9,21,...,93] xor PHRB[5,18]&lt;/li&gt; &lt;li&gt;PC[17] xor PHRT[10,22,...,94] xor PHRB[6,19]&lt;/li&gt; &lt;li&gt;PC[18] xor PHRT[11,23,...,95] xor PHRB[7,20]&lt;/li&gt; &lt;li&gt;PC[2:5]: 单独出现，不和其他位异或&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;那么，这里是怎么实现针对 PC、PHRT 和 PHRB 的注入的呢？针对 PHRT 的注入前面已经提到过，只需要一个间接分支：&lt;/p&gt; &lt;div class=&#34;language-c highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-6-1&#34;&gt;&lt;a id=&#34;__codelineno-6-1&#34; name=&#34;__codelineno-6-1&#34; href=&#34;#__codelineno-6-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// target differs in T[2]&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-2&#34;&gt;&lt;a id=&#34;__codelineno-6-2&#34; name=&#34;__codelineno-6-2&#34; href=&#34;#__codelineno-6-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;auto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-3&#34;&gt;&lt;a id=&#34;__codelineno-6-3&#34; name=&#34;__codelineno-6-3&#34; href=&#34;#__codelineno-6-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;targets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-4&#34;&gt;&lt;a id=&#34;__codelineno-6-4&#34; name=&#34;__codelineno-6-4&#34; href=&#34;#__codelineno-6-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;target0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-5&#34;&gt;&lt;a id=&#34;__codelineno-6-5&#34; name=&#34;__codelineno-6-5&#34; href=&#34;#__codelineno-6-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// add nop&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-6&#34;&gt;&lt;a id=&#34;__codelineno-6-6&#34; name=&#34;__codelineno-6-6&#34; href=&#34;#__codelineno-6-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;target1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;PHRB 的注入就比较复杂了，例如要注入 &lt;span class=&#34;arithmatex&#34;&gt;\(B[2]=k\)&lt;/span&gt;，我们需要进行三次分支的跳转：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;第一次跳转，&lt;span class=&#34;arithmatex&#34;&gt;\(B\)&lt;/span&gt; 相同，&lt;span class=&#34;arithmatex&#34;&gt;\(T[2]=k\)&lt;/span&gt;；&lt;/li&gt; &lt;li&gt;第二次跳转，&lt;span class=&#34;arithmatex&#34;&gt;\(B[2]=k\)&lt;/span&gt;，&lt;span class=&#34;arithmatex&#34;&gt;\(T[3]=k\)&lt;/span&gt;；&lt;/li&gt; &lt;li&gt;第三次跳转，&lt;span class=&#34;arithmatex&#34;&gt;\(B[2]=B[3]=k\)&lt;/span&gt;, &lt;span class=&#34;arithmatex&#34;&gt;\(T\)&lt;/span&gt; 相同。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;经过计算，可以发现前两次跳转对 PHRT 的抵消，第二次跳转的 &lt;span class=&#34;arithmatex&#34;&gt;\(B[2]\)&lt;/span&gt; 与第三次跳转的 &lt;span class=&#34;arithmatex&#34;&gt;\(B[3]\)&lt;/span&gt; 抵消，最后相当于只有最后一次跳转的 &lt;span class=&#34;arithmatex&#34;&gt;\(B[2]=k\)&lt;/span&gt; 对 PHRB 产生了贡献。&lt;/p&gt; &lt;p&gt;最复杂的是 PC 的注入，这次需要分情况讨论：&lt;/p&gt; &lt;p&gt;第一种情况是，要注入的 PC 位比较高，具体来说，是 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[7]\)&lt;/span&gt; 或者更高的位数，此时我们可以很容易地避免引入对 PHRB 的贡献，因为它只考虑 &lt;span class=&#34;arithmatex&#34;&gt;\(B[5:2]\)&lt;/span&gt;：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;第一次跳转，&lt;span class=&#34;arithmatex&#34;&gt;\(B\)&lt;/span&gt; 相同，&lt;span class=&#34;arithmatex&#34;&gt;\(T[6]=k\)&lt;/span&gt;；&lt;/li&gt; &lt;li&gt;第二次跳转，&lt;span class=&#34;arithmatex&#34;&gt;\(B[6]=k\)&lt;/span&gt; 但对 PHRB 没有贡献，&lt;span class=&#34;arithmatex&#34;&gt;\(T[7]=k\)&lt;/span&gt;。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;那么两次跳转完以后，PHRB 不变，PHRT 的贡献被抵消掉，同时实现了 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[7]=k\)&lt;/span&gt; 的注入。&lt;/p&gt; &lt;p&gt;第二种情况是，要注入的正好是 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[6]\)&lt;/span&gt;，继续用上面的方法会发现 PHRB 无法抵消，这时候，需要引入第三次跳转：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;第一次跳转，&lt;span class=&#34;arithmatex&#34;&gt;\(B\)&lt;/span&gt; 相同，&lt;span class=&#34;arithmatex&#34;&gt;\(T[3]=k\)&lt;/span&gt;； &lt;/li&gt; &lt;li&gt;第二次跳转，&lt;span class=&#34;arithmatex&#34;&gt;\(B[3]=k\)&lt;/span&gt;，&lt;span class=&#34;arithmatex&#34;&gt;\(T[5]=T[4]=k\)&lt;/span&gt;；&lt;/li&gt; &lt;li&gt;第三次跳转，&lt;span class=&#34;arithmatex&#34;&gt;\(B[4]=k\)&lt;/span&gt;，&lt;span class=&#34;arithmatex&#34;&gt;\(T[6]=k\)&lt;/span&gt;。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;验算可以发现，PHRB 和 PHRT 的贡献全都被抵消，成功注入 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[6]=k\)&lt;/span&gt;。&lt;/p&gt; &lt;p&gt;最后来看要注入的 PC 更低的情况，例如要注入 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[3]=k\)&lt;/span&gt;，还是用三次跳转：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;第一次跳转，&lt;span class=&#34;arithmatex&#34;&gt;\(B\)&lt;/span&gt; 相同，&lt;span class=&#34;arithmatex&#34;&gt;\(T[2]=k\)&lt;/span&gt;； &lt;/li&gt; &lt;li&gt;第二次跳转，&lt;span class=&#34;arithmatex&#34;&gt;\(B[2]=k\)&lt;/span&gt;，&lt;span class=&#34;arithmatex&#34;&gt;\(T[2]=T[3]=k\)&lt;/span&gt;；&lt;/li&gt; &lt;li&gt;第三次跳转，&lt;span class=&#34;arithmatex&#34;&gt;\(B[3]=k\)&lt;/span&gt;，&lt;span class=&#34;arithmatex&#34;&gt;\(T[3]=k\)&lt;/span&gt;。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;这样就成功注入 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[3]=k\)&lt;/span&gt;。&lt;/p&gt; &lt;p&gt;那么 PC 的注入就完成了，只有 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[2]\)&lt;/span&gt; 没有找到合适的方法来注入。&lt;/p&gt; &lt;h3 id=&#34;逆向工程-index-函数&#34;&gt;逆向工程 index 函数&lt;a class=&#34;headerlink&#34; href=&#34;#逆向工程-index-函数&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;相连度和 tag 函数已知，接下来，让我们逆向工程最后的 index 函数。逆向工程的思路如下：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;通过前面的逆向工程，发现 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[5:2]\)&lt;/span&gt; 是独立出现在 tag 函数中，并且没有出现在 index 中，所以我们可以构造出多个分支，它们的 tag 不同；&lt;/li&gt; &lt;li&gt;进一步，构造两组条件分支，每组都有四个条件分支，因为是四路组相连，如果这两组分别映射到两个 set 中，就可以正确预测；反之，如果被映射到同一个 set 中，就会预测错误；&lt;/li&gt; &lt;li&gt;和之前类似，向 PC、PHRB 或 PHRT 注入两个随机数 &lt;span class=&#34;arithmatex&#34;&gt;\(k\)&lt;/span&gt; 和 &lt;span class=&#34;arithmatex&#34;&gt;\(l\)&lt;/span&gt;，然后预测两组共八个条件分支，这些条件分支的跳转方向都是 &lt;code&gt;k xor l&lt;/code&gt;；&lt;/li&gt; &lt;li&gt;如果 &lt;span class=&#34;arithmatex&#34;&gt;\(k\)&lt;/span&gt; 和 &lt;span class=&#34;arithmatex&#34;&gt;\(l\)&lt;/span&gt; 注入的位同时出现在 index 函数中，但是没有异或关系，那么这八个条件分支可以正确地被预测；&lt;/li&gt; &lt;li&gt;如果 &lt;span class=&#34;arithmatex&#34;&gt;\(k\)&lt;/span&gt; 和 &lt;span class=&#34;arithmatex&#34;&gt;\(l\)&lt;/span&gt; 注入的位同时出现在 index 函数中，并且有异或关系，那么这八个条件分支会被映射到同一个 set 内，最多只能正确预测其中四个分支；&lt;/li&gt; &lt;li&gt;如果 &lt;span class=&#34;arithmatex&#34;&gt;\(k\)&lt;/span&gt; 和 &lt;span class=&#34;arithmatex&#34;&gt;\(l\)&lt;/span&gt; 注入的位至少出现一个在 tag 函数中，那么一个分支会在同一个 set 内占用两项，导致最多只能正确预测其中两个分支。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;注入 &lt;span class=&#34;arithmatex&#34;&gt;\(PC[9]\)&lt;/span&gt; 和 &lt;span class=&#34;arithmatex&#34;&gt;\(PHRT[i]\)&lt;/span&gt; 的&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/pht_index_bits_xor.cpp&#34;&gt;实验&lt;/a&gt;结果如下：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../cbp-reverse-engineer-index.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;结合上面的讨论，可以知道：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;PC[9] 和 PHRT[38] 和 PHRT[88] 有异或关系&lt;/li&gt; &lt;li&gt;PHRT[2]、PHRT[12]、PHRT[17]、PHRT[22]、PHRT[27]、PHRT[33]、PHRT[43]、PHRT[53]、PHRT[58]、PHRT[63]、PHRT[68]、PHRT[73]、PHRT[78]、PHRT[83]、PHRT[93] 在 index 中，但是和 PC[9] 没有异或关系&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;实际上还有 PHRT[7] 和 PHRT[48] 也在 index 中，但实际上测试的时候为了保证历史最长的表提供预测，还额外注入了 PHRT[99]，它与 PHRT[7] 和 PHRT[48] 有异或关系，所以在上图没有显现出来。&lt;/p&gt; &lt;p&gt;用类似的方法，去测试 PHRT 与 PHRT、PHRT 与 PHRB、PHRB 与 PHRB 之间的异或关系，就可以找到最终的 index 函数：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;PHRT[2] xor PHRT[43] xor PHRT[93]&lt;/li&gt; &lt;li&gt;PHRT[7] xor PHRT[48] xor PHRT[99]&lt;/li&gt; &lt;li&gt;PHRT[12] xor PHRT[63] xor PHRB[5]&lt;/li&gt; &lt;li&gt;PHRT[17] xor PHRT[68] xor PHRB[10]&lt;/li&gt; &lt;li&gt;PHRT[22] xor PHRT[73] xor PHRB[15]&lt;/li&gt; &lt;li&gt;PHRT[27] xor PHRT[78] xor PHRB[20]&lt;/li&gt; &lt;li&gt;PHRT[33] xor PHRT[83] xor PHRB[25]&lt;/li&gt; &lt;li&gt;PHRT[38] xor PHRT[88] xor PC[9]&lt;/li&gt; &lt;li&gt;PHRT[53] xor PHRT[58] xor PHRB[0]&lt;/li&gt; &lt;li&gt;PC[6]&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;至此使用分支历史最长的表的逆向就完成了。接下来讨论一下，如何逆向工程分支历史更短的表。&lt;/p&gt; &lt;h3 id=&#34;逆向工程使用分支历史更短的-tage-表&#34;&gt;逆向工程使用分支历史更短的 TAGE 表&lt;a class=&#34;headerlink&#34; href=&#34;#逆向工程使用分支历史更短的-tage-表&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;前面提到，TAGE 在预测时，会选取提供预测的多个表中使用历史最长的那个表。那么，如果要测试使用历史第二长的表，应该怎么办呢？我们尝试了以下方法：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;在使用历史更长的表里，预先插入一些表项，再去测试历史较短的表的情况，由于 TAGE 会利用它的 useful 计数器来进行新表项的分配，当历史更长的表里的表项的 useful 不为零，可以防止它被覆盖成新的内容，逼迫 TAGE 用历史更短的表来进行预测；&lt;/li&gt; &lt;li&gt;把多个表当成一个整体来考虑，比如在测试能够正常预测的分支数量的时候，得到的是多个表叠加的结果，再减去已知数量，可以得到历史比较短的表的信息；&lt;/li&gt; &lt;li&gt;在超出要测试的表的历史部分，注入大量随机数，例如要测试的一个表，只用到了历史的低 57 位，那就在更高的部分注入大量的随机数，那么历史最长的表能够提供预测的概率会非常小，从而逼迫 TAGE 用当前被测试的表来做预测。&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;通过这些方法，我们成功地逆向出了 Firestorm 的剩下的 TAGE 表的信息：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/reports/dissecting_cbp_of_apple_firestorm_and_qualcomm_oryon/README.md&#34;&gt;完整结果&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/&#34;&gt;代码开源&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;有兴趣的读者可以试着自己复现一下，看看能不能得到对应的实验结果，然后从结果中分析出硬件的参数。有意思的是，我们逆向出来 Qualcomm Oryon 的分支预测器的大小（6 个表一共 80KB 的空间），与官方在 Hot Chips 上公开的是一致的。&lt;/p&gt; &lt;h2 id=&#34;总结&#34;&gt;总结&lt;a class=&#34;headerlink&#34; href=&#34;#总结&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;我们通过一系列方法，实现了对 Apple M1 Firestorm 的条件分支预测器的逆向，并且成功地把它应用到了设计基本一样的 Qualcomm Oryon 处理器上，为后续的研究提供了基础。&lt;/p&gt; &lt;h2 id=&#34;引用文献&#34;&gt;引用文献&lt;a class=&#34;headerlink&#34; href=&#34;#引用文献&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://arxiv.org/abs/2411.13900&#34;&gt;Dissecting Conditional Branch Predictors of Apple Firestorm and Qualcomm Oryon for Software Optimization and Architectural Analysis&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://cseweb.ucsd.edu/~tullsen/halfandhalf.pdf&#34;&gt;Half&amp;amp;Half: Demystifying Intel’s Directional Branch Predictors for Fast, Secure Partitioned Execution&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;</description> <link>https://jia.je/hardware/2025/10/28/cbp-reverse-engineer/</link> <pubDate>Tue, 28 Oct 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2025/10/28/cbp-reverse-engineer/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2025/10/28/cbp-reverse-engineer.png" type="image/png" length="57657" /> </item> <item> <title>本博客近三个月来的访问数据观察</title> <category>analytics</category> <category>blog</category> <category>rybbit</category> <category>software</category> <description>&lt;h1 id=&#34;本博客近三个月来的访问数据观察&#34;&gt;本博客近三个月来的访问数据观察&lt;a class=&#34;headerlink&#34; href=&#34;#本博客近三个月来的访问数据观察&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;写在前面&#34;&gt;写在前面&lt;a class=&#34;headerlink&#34; href=&#34;#写在前面&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;这个博客自 2014 年更新至今，已走过近十一个年头，累计发布了四百多篇文章。出于好奇，我一直想了解哪些内容更受读者欢迎。五年前，我曾配置过 Google Analytics，但使用体验并不理想，于是转而自行部署了 &lt;a href=&#34;https://github.com/rybbit-io/rybbit/&#34;&gt;rybbit&lt;/a&gt; 实例来收集访问数据。如今三个月过去，是时候与大家分享一些有趣的发现。&lt;/p&gt; &lt;p&gt;P.S. 如果你对数据收集有所顾虑，可以屏蔽对应的 analytics 脚本。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;数据总览与趋势&#34;&gt;数据总览与趋势&lt;a class=&#34;headerlink&#34; href=&#34;#数据总览与趋势&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;首先来看这三个月内的整体访问情况与趋势：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../blog-analytics-three-months-overall.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;访问量比我的预期要高一些。虽然这些年写了不少内容，但并没有刻意宣传，主要依赖搜索引擎推荐和读者的订阅与转发。从时间趋势上可以看出两个明显特点：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;工作日访问量显著高于周末，通常为周末的两到三倍；&lt;/li&gt; &lt;li&gt;开学后工作日的访问量比暑假期间又高出一倍，但周末依然低迷。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;由此推测，学生读者占比较高。结合国庆假期访问量的下降来看，国内读者仍是主力。下面是各国家与地区的访问分布：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../blog-analytics-three-months-location.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;值得一提的是，也有不少海外读者访问，看来近年来有意识地撰写英文内容确实产生了效果。&lt;/p&gt; &lt;p&gt;以 UTC+8 时区为基准，从访问时间分布中可以看出大家的作息习惯：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../blog-analytics-three-months-time.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;尽管大家可能习惯熬夜，但深夜阅读博客的并不多，多数访问集中在工作时间。&lt;/p&gt; &lt;p&gt;接下来是基于 User Agent 的统计。首先是浏览器分布：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../blog-analytics-three-months-browser.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;不出所料，Chrome 及基于 Chromium 内核的浏览器占据主流，Firefox 和 Safari 占比不高。我本人目前也在使用 Firefox，希望它能持续发展，避免 Chrome 一家独大。&lt;/p&gt; &lt;p&gt;操作系统分布如下：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../blog-analytics-three-months-os.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;Windows 占比最高，macOS 次之。考虑到博客内容主要涉及计算机技术，这也大致反映了相关从业人员的偏好。&lt;/p&gt; &lt;p&gt;以下是访问次数较多的几篇文章：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;../../../../../hardware/2022/12/10/acpi-notes/&#34;&gt;ACPI 学习笔记&lt;/a&gt;: 886 次&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;../../../../2021/12/26/nvidia-cuda/&#34;&gt;NVIDIA 驱动和 CUDA 版本信息速查&lt;/a&gt;: 835 次&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;../../../../../system/2023/08/11/openbmc-qemu/&#34;&gt;在 QEMU 中运行 OpenBMC&lt;/a&gt;: 725 次&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;../../../../2023/08/02/spec-cpu-2006/&#34;&gt;SPEC CPU 2006 性能测试&lt;/a&gt;: 520 次&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;../../../../../hardware/2020/05/10/mifare-classic-ndef/&#34;&gt;MIFARE Classic 上配置 NDEF&lt;/a&gt;: 464 次&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;这个排名有些出乎我的意料。这几篇文章在撰写时并未特别考虑入门读者的理解难度或内容的丰富性。或许是因为它们涉及的领域资料较少，因此在相关关键词搜索中容易被找到。这一点在 Google Search Console 中也得到了印证：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../blog-analytics-three-months-search.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;相比之下，一些精心准备的文章阅读量并不高，可能是因为所在领域已有较多优质内容，新文章难以脱颖而出。这也说明文章质量与阅读量之间并非简单的正比关系。&lt;/p&gt; &lt;p&gt;我还注意到一些重度用户，他们不仅阅读多篇文章，且停留时间较长：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;未知用户一：阅读了分支预测、乱序执行、CPU 微架构分析等文章，推测可能是刚开始研究 CPU 微架构的同行；&lt;/li&gt; &lt;li&gt;未知用户二：浏览了 wishbone、乱序执行相关内容，猜测是学习清华计算机组成原理课程的学生；&lt;/li&gt; &lt;li&gt;未知用户三：从华为相关文章进入，随后浏览了其他内容，可能是搜索华为内容进入博客后，被其他文章吸引的读者；&lt;/li&gt; &lt;li&gt;未知用户四：阅读了 ARM/Samsung/Intel 等处理器微架构分析文章，又一位同行，但有一定基础，更加关注业界。&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;类似的例子还有不少，在此不一一列举。尽管 CPU 相关文章的阅读量不及软件类内容，但能得到这么多同行的关注，确实令人欣慰——毕竟这本身就是一个小众领域，不能奢求过高的阅读量。&lt;/p&gt; &lt;p&gt;通过这次数据分析，我收获了不少有趣的观察。未来可能会不定期更新类似内容，看看随着时间推移，是否会有新的发现。&lt;/p&gt; &lt;p&gt;最后，如果你对访问数据的收集感到不适，可以直接屏蔽 analytics 脚本（或许你的浏览器插件已经这样做了）。根据 rybbit 的官方说明，其信息收集方法较为尊重用户隐私，我也没有对代码进行任何修改，不放心的读者可以阅读 &lt;a href=&#34;https://github.com/rybbit-io/rybbit&#34;&gt;rybbit&lt;/a&gt; 的源码来审计。&lt;/p&gt; &lt;p&gt;P.S. 你能看出这篇文章是，我先写了一遍，然后让大模型润色的结果吗？&lt;/p&gt;</description> <link>https://jia.je/software/2025/10/09/blog-analytics-three-months/</link> <pubDate>Thu, 09 Oct 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/software/2025/10/09/blog-analytics-three-months/</guid> <enclosure url="https://jia.je/assets/images/social/software/2025/10/09/blog-analytics-three-months.png" type="image/png" length="47692" /> </item> <item> <title>ARM 公版核微架构演进</title> <category>arm</category> <category>c1</category> <category>cortex</category> <category>cpu</category> <category>hardware</category> <category>neoverse</category> <description>&lt;h1 id=&#34;arm-公版核微架构演进&#34;&gt;ARM 公版核微架构演进&lt;a class=&#34;headerlink&#34; href=&#34;#arm-公版核微架构演进&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;ARM 公版核微架构的演进频繁，型号又比较多，相关信息散落在各种地方，为了方便查阅，在这里做一个收集。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;2025-年&#34;&gt;2025 年&lt;a class=&#34;headerlink&#34; href=&#34;#2025-年&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;c1-ultra&#34;&gt;C1-Ultra&lt;a class=&#34;headerlink&#34; href=&#34;#c1-ultra&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://pc.watch.impress.co.jp/docs/column/ubiq/2046162.html&#34;&gt;Arm の新しい CPU「C1」は 2 桁パーセントの性能アップ。電力効率も大幅改善&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=U1tPpV0RWNw&#34;&gt;Inside Arm&#39;s New C1‑Ultra CPU: Double‑Digit IPC Gains Again!&lt;/a&gt;&lt;ul&gt; &lt;li&gt;C1-Ultra: successor to Cortex X925&lt;/li&gt; &lt;li&gt;Branch prediction: Additional tracking for local/per-PC history&lt;/li&gt; &lt;li&gt;33% increase in L1 I-Cache available bandwidth&lt;/li&gt; &lt;li&gt;Out of order window size growth: Up to 25% growth, Up to ~2K instruction in flight&lt;/li&gt; &lt;li&gt;2x L1 data cache capacity (128KB)&lt;/li&gt; &lt;li&gt;Data prefetchers: array-indexing coverage&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://developer.arm.com/documentation/108014/latest/&#34;&gt;Arm® C1-Ultra Core Technical Reference Manual&lt;/a&gt;&lt;ul&gt; &lt;li&gt;Implementation of the Scalable Vector Extension (SVE) with a 128-bit vector length and Scalable Vector Extension 2 (SVE2)&lt;/li&gt; &lt;li&gt;Implementation of the Scalable Matrix Extension (SME) and Scalable Matrix Extension 2 (SME2), and support for the C1-SME2 unit&lt;/li&gt; &lt;li&gt;configure the L2 cache to be 2048KB or 3072KB&lt;/li&gt; &lt;li&gt;A 64KB, 4-way set associative L1 instruction cache with 64-byte cache lines&lt;/li&gt; &lt;li&gt;A fully associative L1 instruction Translation Lookaside Buﬀer (TLB) with native support for 4KB, 16KB, 64KB, and 2MB page sizes&lt;/li&gt; &lt;li&gt;A 128KB, 4-way set associative cache with 64-byte cache lines&lt;/li&gt; &lt;li&gt;A fully associative L1 data TLB with native support for 4KB, 16KB, and 64KB page sizes and 2MB and 512MB block sizes&lt;/li&gt; &lt;li&gt;L2 cache is private to the core and can be configured to be 2MB 8-way set associative or 3MB 12-way set associative&lt;/li&gt; &lt;li&gt;L1 instruction TLB, Fully associative, 128 entries&lt;/li&gt; &lt;li&gt;L1 data TLB, Fully associative, 96 entries&lt;/li&gt; &lt;li&gt;L1 Statistical Profiling Extension (SPE) TLB, Located in the SPE block, VA to PA translations of any page and block size, 1 entry&lt;/li&gt; &lt;li&gt;L1 TRace Buﬀer Extension (TRBE) TLB, VA to PA translations of any page and block size, 1 entry&lt;/li&gt; &lt;li&gt;L2 TLB, Shared by instructions and data, 8-way set associative, 2048 entries&lt;/li&gt; &lt;li&gt;L1 instruction cache, 64KB, 4-way set associative, Virtually Indexed, Physically Tagged (VIPT) behaving as Physically Indexed, Physically Tagged (PIPT), Pseudo-Least Recently Used (LRU) cache replacement policy for L1, 32 bytes per cycle interface with L2&lt;/li&gt; &lt;li&gt;L1 data cache, 128KB, 4-way set associative, Virtually Indexed, Physically Tagged (VIPT) behaving as Physically Indexed, Physically Tagged (PIPT), Re-Reference Interval Prediction (RRIP) replacement policy, 4×64-bit read paths and 4×64-bit write paths for the integer execute pipeline, 4×128-bit read paths and 4×128-bit write paths for the vector execute pipeline&lt;/li&gt; &lt;li&gt;L2 cache, 2MB 8-way set associative with 4 banks or 3MB 12-way set associative with 4 banks, Physically Indexed, Physically Tagged (PIPT), Dynamic biased cache replacement policy, One CHI Issue E compliant interfaces with 256-bit read and write DAT channel widths&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;c1-pro&#34;&gt;C1-Pro&lt;a class=&#34;headerlink&#34; href=&#34;#c1-pro&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=yUqEhahvAVE&#34;&gt;Arm Lumex C1-Pro CPU Core: What You Need to Know&lt;/a&gt;&lt;ul&gt; &lt;li&gt;C1-Pro: successor to Cortex-A725&lt;/li&gt; &lt;li&gt;Larger direction predictor and branch history&lt;/li&gt; &lt;li&gt;2x capacity 0-cycle BTB&lt;/li&gt; &lt;li&gt;16x capacity 1-cycle BTB&lt;/li&gt; &lt;li&gt;50% more L1 Instruction TLB capacity&lt;/li&gt; &lt;li&gt;Increase effective L1D cache bandwidth&lt;/li&gt; &lt;li&gt;Lower latency L2 TLB hit&lt;/li&gt; &lt;li&gt;New indirect prefetcher&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;h2 id=&#34;2024-年&#34;&gt;2024 年&lt;a class=&#34;headerlink&#34; href=&#34;#2024-年&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;cortex-x925&#34;&gt;Cortex X925&lt;a class=&#34;headerlink&#34; href=&#34;#cortex-x925&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://www.anandtech.com/show/21399/arm-unveils-2024-cpu-core-designs-cortex-x925-a725-and-a520-arm-v9-2-redefined-for-3nm-/2&#34;&gt;Arm Unveils 2024 CPU Core Designs, Cortex X925, A725 and A520: Arm v9.2 Redefined For 3nm&lt;/a&gt; &lt;a href=&#34;https://web.archive.org/web/20250626065356/https://www.anandtech.com/show/21399/arm-unveils-2024-cpu-core-designs-cortex-x925-a725-and-a520-arm-v9-2-redefined-for-3nm-/2&#34;&gt;Archive&lt;/a&gt;&lt;ul&gt; &lt;li&gt;Decode &amp;amp; Dispatch: 10-wide&lt;/li&gt; &lt;li&gt;SIMD/FP execution: 6x 128b&lt;/li&gt; &lt;li&gt;Integer ALU pipelines: 1- and 2-cycle operations&lt;/li&gt; &lt;li&gt;Integer multiply execution: 4x versus Cortex-X4&lt;/li&gt; &lt;li&gt;FP compare execution: 2x versus Cortex-X4&lt;/li&gt; &lt;li&gt;&lt;code&gt;&amp;gt;2x&lt;/code&gt; increase in SIMD/FP issue queues&lt;/li&gt; &lt;li&gt;2x increase in max instruction-window capacity（注：Cortex X4 是 384x2，推测 Cortex X925 是 768x2）&lt;/li&gt; &lt;li&gt;Sign-extension instruction elimination&lt;/li&gt; &lt;li&gt;Branch prediction: 2x instruction window size&lt;/li&gt; &lt;li&gt;Instruction Fetch: 2x increase in L1 I$ available bandwidth, 2x increase in L1 iTLB size, Fold out unconditional direct branches&lt;/li&gt; &lt;li&gt;3 -&amp;gt; 4 load pipelines&lt;/li&gt; &lt;li&gt;2x increase in L1 D$ available bandwidth&lt;/li&gt; &lt;li&gt;25-40% in back-end OoO growth&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://developer.arm.com/documentation/102807/0001&#34;&gt;Arm® Cortex-X925 Core Technical Reference Manual&lt;/a&gt;&lt;ul&gt; &lt;li&gt;Implementation of the Scalable Vector Extension (SVE) with a 128-bit vector length and Scalable Vector Extension 2 (SVE2)&lt;/li&gt; &lt;li&gt;configure the L2 cache to be 2048KB or 3072KB&lt;/li&gt; &lt;li&gt;A 64KB, 4-way set associative L1 instruction cache with 64-byte cache lines&lt;/li&gt; &lt;li&gt;A fully associative L1 instruction Translation Lookaside Buﬀer (TLB) with native support for 4KB, 16KB, 64KB, and 2MB page sizes&lt;/li&gt; &lt;li&gt;A 64KB, 4-way set associative cache with 64-byte cache lines&lt;/li&gt; &lt;li&gt;A fully associative L1 data TLB with native support for 4KB, 16KB and 64KB page sizes and 2MB and 512MB block sizes&lt;/li&gt; &lt;li&gt;L2 cache is private to the core and can be configured to be 2MB 8-way set associative or 3MB 12-way set associative&lt;/li&gt; &lt;li&gt;L1 instruction TLB, Caches entries at the 4KB, 16KB, 64KB, or 2MB granularity of Virtual Address (VA) to Physical Address (PA) mapping only, Fully associative, 128 entries&lt;/li&gt; &lt;li&gt;L1 data TLB, Caches entries at the 4KB, 16KB, 64KB, 2MB, or 512MB granularity of VA to PA mappings only, Fully associative, 96 entries&lt;/li&gt; &lt;li&gt;L2 TLB, Shared by instructions and data, VA to PA mappings for 4KB, 16KB, 64KB, 2MB, 32MB, 512MB, and 1GB block sizes, Intermediate Physical Address (IPA) to PA mappings for: 2MB and 1GB block sizes in a 4KB translation granule, 32MB block size in a 16KB translation granule, 512MB block size in a 64KB granule; Intermediate PAs (descriptor PAs) obtained during a translation table walk, 8-way set associative, 2048 entries&lt;/li&gt; &lt;li&gt;L1 instruction cache, 64KB, 4-way set associative, Virtually Indexed, Physically Tagged (VIPT) behaving as Physically Indexed, Physically Tagged (PIPT)&lt;/li&gt; &lt;li&gt;The Cortex®-X925 core supports the AArch64 prefetch memory instructions, PRFM PLI, into the L1 instruction cache or L2 cache&lt;/li&gt; &lt;li&gt;L1 data cache, 64KB, 4-way set associative, Virtually Indexed, Physically Tagged (VIPT) behaving as Physically Indexed, Physically Tagged (PIPT), Re-Reference Interval Prediction (RRIP) replacement policy, 4×64-bit read paths and 4×64-bit write paths for the integer execute pipeline, 4×128-bit read paths and 4×128-bit write paths for the vector execute pipeline&lt;/li&gt; &lt;li&gt;L2 cache, 2MB 8-way set associative with 4 banks or 3MB 12-way set associative with 4 banks, Physically Indexed, Physically Tagged (PIPT)&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://developer.arm.com/documentation/109842/latest/&#34;&gt;Arm® Cortex-X925 Core Software Optimization Guide&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h2 id=&#34;2023-年&#34;&gt;2023 年&lt;a class=&#34;headerlink&#34; href=&#34;#2023-年&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;cortex-x4&#34;&gt;Cortex X4&lt;a class=&#34;headerlink&#34; href=&#34;#cortex-x4&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://www.anandtech.com/show/18871/arm-unveils-armv92-mobile-architecture-cortex-x4-a720-and-a520-64bit-exclusive/2&#34;&gt;Arm Unveils 2023 Mobile CPU Core Designs: Cortex-X4, A720, and A520 - the Armv9.2 Family&lt;/a&gt; &lt;a href=&#34;https://web.archive.org/web/20250622110728/http://www4.anandtech.com/show/18871/arm-unveils-armv92-mobile-architecture-cortex-x4-a720-and-a520-64bit-exclusive/2&#34;&gt;Archive&lt;/a&gt;&lt;ul&gt; &lt;li&gt;Support for larger L2 (2M)&lt;/li&gt; &lt;li&gt;Dispatch width: 10 instrs vs Cortex-X3 (6 instrs &lt;code&gt;I$&lt;/code&gt;, 8 instrs &lt;code&gt;Mop$&lt;/code&gt;)&lt;/li&gt; &lt;li&gt;Overall pipeline depth (branch mispredict penalty): 10 cycles vs Cortex-X3 (11 cycles &lt;code&gt;I$&lt;/code&gt;, 9 cycles &lt;code&gt;Mop$&lt;/code&gt;)&lt;/li&gt; &lt;li&gt;ALUs: 8 vs 6 (Cortex-X3)&lt;/li&gt; &lt;li&gt;Branch units: 3 vs 2 (Cortex-X3)&lt;/li&gt; &lt;li&gt;Integer MAC: 2 vs 1 (Cortex-X3)&lt;/li&gt; &lt;li&gt;Pipelined FP divider / sqrt: Y vs N (Cortex-X3)&lt;/li&gt; &lt;li&gt;MCA capacity: 320x2 -&amp;gt; 384x2&lt;/li&gt; &lt;li&gt;4th LS address generation: LS LS LD -&amp;gt; LS LD LD ST&lt;/li&gt; &lt;li&gt;New L1 temporal data prefetcher&lt;/li&gt; &lt;li&gt;Reduced L1 data bank conflicts&lt;/li&gt; &lt;li&gt;Larger L1 data TLB: 48 -&amp;gt; 96&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://developer.arm.com/documentation/102484/latest/&#34;&gt;Arm® Cortex-X4 Core Technical Reference Manual&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;cortex-a720&#34;&gt;Cortex A720&lt;a class=&#34;headerlink&#34; href=&#34;#cortex-a720&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://www.anandtech.com/show/18871/arm-unveils-armv92-mobile-architecture-cortex-x4-a720-and-a520-64bit-exclusive/3&#34;&gt;Arm Unveils 2023 Mobile CPU Core Designs: Cortex-X4, A720, and A520 - the Armv9.2 Family&lt;/a&gt; &lt;a href=&#34;https://web.archive.org/web/20250522224324/https://www.anandtech.com/show/18871/arm-unveils-armv92-mobile-architecture-cortex-x4-a720-and-a520-64bit-exclusive/3&#34;&gt;Archive&lt;/a&gt;&lt;ul&gt; &lt;li&gt;11-cycle mispredict penalty, vs 12 (Cortex-A715)&lt;/li&gt; &lt;li&gt;Improved 2-taken branch prediction&lt;/li&gt; &lt;li&gt;Pipelined FDIV/FSQRT unit&lt;/li&gt; &lt;li&gt;Faster transfers from Floating-Point/NEON/SVE2 to Integer&lt;/li&gt; &lt;li&gt;Earlier deallocation of mops from Load-Store Issue Queues&lt;/li&gt; &lt;li&gt;Lower latency for L2 cache hits, 9-cycle latency to access L2, vs 10 (Cortex-A715)&lt;/li&gt; &lt;li&gt;Up to 2x memset(0) bandwidth in L2&lt;/li&gt; &lt;li&gt;New L2 spatial-prefetch engine&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;h2 id=&#34;2022-年&#34;&gt;2022 年&lt;a class=&#34;headerlink&#34; href=&#34;#2022-年&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;cortex-x3&#34;&gt;Cortex X3&lt;a class=&#34;headerlink&#34; href=&#34;#cortex-x3&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://fuse.wikichip.org/news/6855/arm-unveils-next-gen-flagship-core-cortex-x3/&#34;&gt;Arm Unveils Next-Gen Flagship Core: Cortex-X3&lt;/a&gt;&lt;ul&gt; &lt;li&gt;50% larger L1 + L2 (new) BTB capacity&lt;/li&gt; &lt;li&gt;10x larger L0 BTB capacity&lt;/li&gt; &lt;li&gt;New predictor dedicated for indirect branches&lt;/li&gt; &lt;li&gt;Double return-stack capacity (32 entries)&lt;/li&gt; &lt;li&gt;Mop cache 50% capacity (1.5K entries)&lt;/li&gt; &lt;li&gt;Removed 1 pipeline stage in Mop Cache fetch, 10-&amp;gt;9 cycles for a branch mispredict&lt;/li&gt; &lt;li&gt;Increase decode bandwidth: 5-&amp;gt;6&lt;/li&gt; &lt;li&gt;Integer ALUs increase 4-&amp;gt;6: 2-&amp;gt;4 single-cycle (SX), 2 single-/multi-cycle (MX)&lt;/li&gt; &lt;li&gt;ROB/MCQ: 288x2 -&amp;gt; 320x2&lt;/li&gt; &lt;li&gt;Integer load bandwdith: 24B -&amp;gt; 32B&lt;/li&gt; &lt;li&gt;Additional data prefetch engines: Spatial, Pointer/Indirect&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://developer.arm.com/documentation/101593/latest/&#34;&gt;Arm® Cortex‑X3 Core Technical Reference Manual&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;neoverse-v2&#34;&gt;Neoverse V2&lt;a class=&#34;headerlink&#34; href=&#34;#neoverse-v2&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://hc2023.hotchips.org/assets/program/conference/day1/CPU1/HC2023.Arm.MagnusBruce.v04.FINAL.pdf&#34;&gt;Arm Neoverse V2 platform: Leadership Performance and Power Efficiency for Next-Generation Cloud Computing, ML and HPC Workloads&lt;/a&gt;&lt;ul&gt; &lt;li&gt;6-wide/8-wide front-end&lt;/li&gt; &lt;li&gt;64KB ICache&lt;/li&gt; &lt;li&gt;320+ OoO window&lt;/li&gt; &lt;li&gt;8-wide dispatch&lt;/li&gt; &lt;li&gt;8-wide retire&lt;/li&gt; &lt;li&gt;2 LS + 1 LD / cycle&lt;/li&gt; &lt;li&gt;64KB DCache&lt;/li&gt; &lt;li&gt;6-ALU + 2-branch&lt;/li&gt; &lt;li&gt;Quad 128-bit low latency SIMD datapath&lt;/li&gt; &lt;li&gt;L2 10-cycle load-to-use, 128B/cycle, private L2 cache 1 or 2 MB&lt;/li&gt; &lt;li&gt;Two predicted branches per cycle&lt;/li&gt; &lt;li&gt;Predictor acts as ICache prefetcher&lt;/li&gt; &lt;li&gt;64kB, 4-way set-associative L1 instruction cache&lt;/li&gt; &lt;li&gt;Two-level Branch Target Buffer&lt;/li&gt; &lt;li&gt;8 table TAGE direction predictor with staged output&lt;/li&gt; &lt;li&gt;10x larger nanoBTB&lt;/li&gt; &lt;li&gt;Split main BTB into two levels with 50% more entries&lt;/li&gt; &lt;li&gt;TAGE: 2x larger tables with 2-way associativity, Longer history&lt;/li&gt; &lt;li&gt;Indirect branches: Dedicated predictor&lt;/li&gt; &lt;li&gt;Fetch bandwidth: Doubled instruction TLB and cache BW&lt;/li&gt; &lt;li&gt;Fetch Queue: Doubled from 16 to 32 entries&lt;/li&gt; &lt;li&gt;Fill Buffer: Increased size from 12 to 16 entries&lt;/li&gt; &lt;li&gt;Decode bandwidth: Increased decoder lanes from 5 to 6, Increased Decode Queue from 16 to 24 entries&lt;/li&gt; &lt;li&gt;Rename checkpoints: Increased from 5 to 6 total checkpoints, Increased from 3 to 5 vector checkpoints&lt;/li&gt; &lt;li&gt;Late read of physical register file – no data in IQs&lt;/li&gt; &lt;li&gt;Result caches with lazy writeback&lt;/li&gt; &lt;li&gt;Added two more single-cycle ALUs&lt;/li&gt; &lt;li&gt;Larger Issue Queues, SX/MX: Increased from 20 to 22 entries, VX: Increased from 20 to 28 entries&lt;/li&gt; &lt;li&gt;Predicate operations: Doubled predicate bandwidth&lt;/li&gt; &lt;li&gt;Zero latency MOV; Subset of register-register and immediate move operations execute with zero latency&lt;/li&gt; &lt;li&gt;Instruction fusion: More fusion cases, including CMP + CSEL/CSET&lt;/li&gt; &lt;li&gt;Two load/store pipes + one load pipe&lt;/li&gt; &lt;li&gt;4 x 8B result busses (integer)&lt;/li&gt; &lt;li&gt;3 x 16B result busses (FP, SVE, Neon)&lt;/li&gt; &lt;li&gt;ST to LD forwarding at L1 hit latency&lt;/li&gt; &lt;li&gt;RST and MB to reduce tag and data accesses&lt;/li&gt; &lt;li&gt;Fully-associative L1 DTLB with multiple page sizes&lt;/li&gt; &lt;li&gt;64kB 4-way set associative Dcache&lt;/li&gt; &lt;li&gt;TLB Increased from 40 to 48 entries&lt;/li&gt; &lt;li&gt;Replacement policy Changed from PLRU to dynamic RRIP&lt;/li&gt; &lt;li&gt;Larger Queues: Store Buffer, ReadAfterRead, ReadAfterWrite&lt;/li&gt; &lt;li&gt;Efficiency: VA hash based store to load forwarding&lt;/li&gt; &lt;li&gt;Multiple prefetching engines training on L1 and L2 accesses: Spatial Memory Streaming, Best Offset, Stride, Correlated Miss Cache, Page&lt;/li&gt; &lt;li&gt;New PF engines: Global SMS – larger offsets than SMS, Sampling Indirect Prefetch – pointer dereference, TableWalk – Page Table Entrie&lt;/li&gt; &lt;li&gt;Private unified Level 2 cache, 8-way SA, 4 independent banks&lt;/li&gt; &lt;li&gt;64B read or write per 2 cycles per bank = 128B/cycle total&lt;/li&gt; &lt;li&gt;96-entry Transaction Queue&lt;/li&gt; &lt;li&gt;Inclusive with L1 caches for efficient data and instruction coherency&lt;/li&gt; &lt;li&gt;AMBA CHI interface with 256b DAT channels&lt;/li&gt; &lt;li&gt;Capacity 2MB/8-way with latency of 1MB (10-cycle ld-to-use)&lt;/li&gt; &lt;li&gt;Replacement policy 6-state RRIP (up from 4)&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://chipsandcheese.com/p/hot-chips-2023-arms-neoverse-v2&#34;&gt;Hot Chips 2023: Arm’s Neoverse V2&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://developer.arm.com/documentation/102375/latest/&#34;&gt;Arm® Neoverse™ V2 Core Technical Reference Manual&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://developer.arm.com/documentation/109898/latest/&#34;&gt;Arm Neoverse V2 Software Optimization Guide&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h2 id=&#34;2021-年&#34;&gt;2021 年&lt;a class=&#34;headerlink&#34; href=&#34;#2021-年&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;cortex-x2&#34;&gt;Cortex X2&lt;a class=&#34;headerlink&#34; href=&#34;#cortex-x2&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://chipsandcheese.com/2023/10/27/cortex-x2-arm-aims-high/&#34;&gt;Cortex X2: Arm Aims High&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://developer.arm.com/documentation/101803/0200&#34;&gt;Arm® Cortex®‑X2 Core Technical Reference Manual&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://www.anandtech.com/show/16693/arm-announces-mobile-armv9-cpu-microarchitectures-cortexx2-cortexa710-cortexa510/2&#34;&gt;Arm Announces Mobile Armv9 CPU Microarchitectures: Cortex-X2, Cortex-A710 &amp;amp; Cortex-A510&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h2 id=&#34;2020-年&#34;&gt;2020 年&lt;a class=&#34;headerlink&#34; href=&#34;#2020-年&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;neoverse-n2&#34;&gt;Neoverse N2&lt;a class=&#34;headerlink&#34; href=&#34;#neoverse-n2&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://hc33.hotchips.org/assets/program/conference/day1/20210818_Hotchips_NeoverseN2.pdf&#34;&gt;Arm Neoverse N2: Arm’s 2nd generation high performance infrastructure CPUs and system IPs&lt;/a&gt;&lt;ul&gt; &lt;li&gt;Branch Prediction, 2x 8 instrs (up to 2 taken per cycle), 2x improvement&lt;/li&gt; &lt;li&gt;Nano BTB (0 cyc taken-branch bubble), 64 entry, 4x improvement&lt;/li&gt; &lt;li&gt;Conditional branch direction state, 1.5x improvement&lt;/li&gt; &lt;li&gt;Main BTB, 8K entry, 1.33x improvement&lt;/li&gt; &lt;li&gt;Alt-Path Branch Prediction&lt;/li&gt; &lt;li&gt;64KB Instruction cache&lt;/li&gt; &lt;li&gt;1.5K entry Mop Cache&lt;/li&gt; &lt;li&gt;16-entry Fetch Queue, 1.33x improvement&lt;/li&gt; &lt;li&gt;Fetch Width: 4 instr from &lt;code&gt;i$&lt;/code&gt;, 5 instr from &lt;code&gt;MOP$&lt;/code&gt;, Up to 1.5x improvement&lt;/li&gt; &lt;li&gt;Early branch redirect: uncond + cond&lt;/li&gt; &lt;li&gt;Decode width: 4 (I-cache) or 5 (Mop cache), Up to 1.25x improvement&lt;/li&gt; &lt;li&gt;Branch predict up to 16-inst/cycle, 2-taken/cycle&lt;/li&gt; &lt;li&gt;New Macro-op (MOP) cache with 1.5k entries&lt;/li&gt; &lt;li&gt;50% larger branch direction predicton&lt;/li&gt; &lt;li&gt;33% larger BTB with shorter average latency&lt;/li&gt; &lt;li&gt;Early re-steering for conditional branches that miss the BTB&lt;/li&gt; &lt;li&gt;Rename width: 5 instrs, 1.2x improvement&lt;/li&gt; &lt;li&gt;Rename Checkpointing: Yes&lt;/li&gt; &lt;li&gt;ROB size: 160+, 1.25x improvement&lt;/li&gt; &lt;li&gt;ALUs: 4, 1.33x improvement&lt;/li&gt; &lt;li&gt;Branch resolution: 2 per cycle, 2x improvement&lt;/li&gt; &lt;li&gt;Overall Pipeline Depth: 10 cycles, 1.1x improvement&lt;/li&gt; &lt;li&gt;64KB L1 Data cache&lt;/li&gt; &lt;li&gt;Private 512KB/1MB L2 Cache&lt;/li&gt; &lt;li&gt;AGU: 2-LD/ST + 1 LD, 1.5x improvement&lt;/li&gt; &lt;li&gt;L1 LD Hit bandwidth: 3x 16B/cycle, 1.5x improvement&lt;/li&gt; &lt;li&gt;Store data B/W: 32B/cycle, 2x improvement&lt;/li&gt; &lt;li&gt;L2 bandwidth: 64B read + 64B write, 2x improvement&lt;/li&gt; &lt;li&gt;L2 transactions: 64, 1.3x improvement&lt;/li&gt; &lt;li&gt;Data Prefetch Engines: Stride, spatial/region, stream, temporal&lt;/li&gt; &lt;li&gt;Correlated Miss Caching (CMC) prefetching&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;neoverse-v1&#34;&gt;Neoverse V1&lt;a class=&#34;headerlink&#34; href=&#34;#neoverse-v1&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://teratec.eu/library/pdf/forum/2021/A05-03.pdf&#34;&gt;SW defined cars: HPC, from the cloud to the dashboard for an amazing driver experience&lt;/a&gt;&lt;ul&gt; &lt;li&gt;Faster run-ahead for prefetching into the I$ (2x32B bandwidth)&lt;/li&gt; &lt;li&gt;33% larger BTBs (8K entry)&lt;/li&gt; &lt;li&gt;6x nano BTB (96 entry), zero-cycle bubble&lt;/li&gt; &lt;li&gt;2x number of concurrent code regions tracked in front-end&lt;/li&gt; &lt;li&gt;Introduction of Mop Cache, L0 decoded instruction cache (3K entry)&lt;/li&gt; &lt;li&gt;high dispatch bandwidth, 8-instrs per cycle, 2x increase, I$ decode bandwidth increased from 4x to 5x&lt;/li&gt; &lt;li&gt;Lower latency decode pipeline by 1 stage&lt;/li&gt; &lt;li&gt;OoO window size, 2x+ ROB (256 entry + compression)&lt;/li&gt; &lt;li&gt;Increase superscalar integer execution bandwidth, 1-&amp;gt;2 Branch Execution, 3-&amp;gt;4 ALU&lt;/li&gt; &lt;li&gt;2x vector/fp bandwidth, 2x256b – SVE (new), 4x128b – Neon/FP&lt;/li&gt; &lt;li&gt;3rd LD AGU/pipe (50% incr), LS LS LD&lt;/li&gt; &lt;li&gt;LD/ST data bandwidth, LD: 2x16B -&amp;gt; 3x16B, LD (SVE): 2x32B, ST: 16B -&amp;gt; 32B (2x), broken out into separate issue pipes&lt;/li&gt; &lt;li&gt;Number of outstanding external memory transactions (48-&amp;gt;96)&lt;/li&gt; &lt;li&gt;MMU capacity 1.2K-&amp;gt;2K entry (67% incr)&lt;/li&gt; &lt;li&gt;L2 latency reduced by 1 cycle for 1M (now 10cyc load to use)&lt;/li&gt; &lt;li&gt;11+ stage accordion pipeline&lt;/li&gt; &lt;li&gt;8-wide front-end / 15-wide issue&lt;/li&gt; &lt;li&gt;Four 64-bit integer ALUs + two dedicated Branch units&lt;/li&gt; &lt;li&gt;2x 256-bit SVE datapaths&lt;/li&gt; &lt;li&gt;4x 128-bit Neon/FP datapaths&lt;/li&gt; &lt;li&gt;3x load / store addr&lt;/li&gt; &lt;li&gt;3x load data &amp;amp; 2x store data pipeline&lt;/li&gt; &lt;li&gt;8-wide Instruction fetch&lt;/li&gt; &lt;li&gt;5-8 wide decode / rename&lt;/li&gt; &lt;li&gt;pipeline: P1 P2 F1 F2 DE1 RR RD I0 I1 I2 ...&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;cortex-x1&#34;&gt;Cortex X1&lt;a class=&#34;headerlink&#34; href=&#34;#cortex-x1&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://www.anandtech.com/show/15813/arm-cortex-a78-cortex-x1-cpu-ip-diverging/3&#34;&gt;Arm&#39;s New Cortex-A78 and Cortex-X1 Microarchitectures: An Efficiency and Performance Divergence&lt;/a&gt; &lt;a href=&#34;https://web.archive.org/web/20250716133719/https://www.anandtech.com/show/15813/arm-cortex-a78-cortex-x1-cpu-ip-diverging/3&#34;&gt;Archive&lt;/a&gt;&lt;ul&gt; &lt;li&gt;50% larger L0-BTB capacity, 96 entries, zero-cycle bubble taken-branch latency&lt;/li&gt; &lt;li&gt;Increased fetch bandwidth available, 5 instruction fetch from the instruction cache, 8 Mop fetch from the Mop cache&lt;/li&gt; &lt;li&gt;2x Mop cache capacity over Cortex-A77, 3K entries&lt;/li&gt; &lt;li&gt;33% increase in dispatch bandwidth, up to 8-instr/cycle&lt;/li&gt; &lt;li&gt;40% increase in out-of-order window size, 224 entry instruction window&lt;/li&gt; &lt;li&gt;2x FP/ASIMD execution bandwidth, 4x128b total bandwidth&lt;/li&gt; &lt;li&gt;Doubling available L1-D, L2 bandwidth&lt;/li&gt; &lt;li&gt;Doubleing of maximum L2 capacity&lt;/li&gt; &lt;li&gt;Up to 33% increase in window growth for in-flight loads and stores&lt;/li&gt; &lt;li&gt;66% larger L2-TLB capacity, 2K entries&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://fuse.wikichip.org/news/3543/arm-cortex-x1-the-first-from-the-cortex-x-custom-program/&#34;&gt;Arm Cortex-X1: The First From The Cortex-X Custom Program&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://developer.arm.com/documentation/101433/0102&#34;&gt;Arm® Cortex®‑X1 Core Technical Reference Manual&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;cortex-a78&#34;&gt;Cortex A78&lt;a class=&#34;headerlink&#34; href=&#34;#cortex-a78&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://www.anandtech.com/show/15813/arm-cortex-a78-cortex-x1-cpu-ip-diverging/2&#34;&gt;Arm&#39;s New Cortex-A78 and Cortex-X1 Microarchitectures: An Efficiency and Performance Divergence&lt;/a&gt; &lt;a href=&#34;https://web.archive.org/web/20250529000334/https://www.anandtech.com/show/15813/arm-cortex-a78-cortex-x1-cpu-ip-diverging/2&#34;&gt;Archive&lt;/a&gt;&lt;ul&gt; &lt;li&gt;Expand prediction support to 2 taken branches per cycles&lt;/li&gt; &lt;li&gt;Additional IMUL bandwidth, up to 2x per cycle&lt;/li&gt; &lt;li&gt;50% increase in load bandwidth over Cortex-A77, additional load AGU / result&lt;/li&gt; &lt;li&gt;Double store-data bandwidth, 32B per cycle&lt;/li&gt; &lt;li&gt;Double L2 interface bandwidth&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;h2 id=&#34;2019-年&#34;&gt;2019 年&lt;a class=&#34;headerlink&#34; href=&#34;#2019-年&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;neoverse-n1&#34;&gt;Neoverse N1&lt;a class=&#34;headerlink&#34; href=&#34;#neoverse-n1&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://www.arm.com/-/media/global/solutions/infrastructure/arm-neoverse-n1-platform.pdf&#34;&gt;The Arm Neoverse N1 Platform: Building Blocks for the Next-Gen Cloud-to-Edge Infrastructure SoC&lt;/a&gt;&lt;ul&gt; &lt;li&gt;4-wide front-end&lt;/li&gt; &lt;li&gt;dispatching/committing up to 8 instructions per cycle&lt;/li&gt; &lt;li&gt;three ALUs, a branch execution unit, two Advanced SIMD units, and two load/store execution units&lt;/li&gt; &lt;li&gt;minimum misprediction penalty is 11-cycle&lt;/li&gt; &lt;li&gt;fetch up to 4 instructions per cycle&lt;/li&gt; &lt;li&gt;large 6K-entry main branch target buffer with 3-cycle access latency&lt;/li&gt; &lt;li&gt;64-entry micro-BTB and a 16-entry nano-BTB&lt;/li&gt; &lt;li&gt;12-entry fetch queue&lt;/li&gt; &lt;li&gt;fully associative 48-entry instruction TLB&lt;/li&gt; &lt;li&gt;4-way set-associative 64KB I-cache&lt;/li&gt; &lt;li&gt;I-cache can deliver up to 16B of instructions per cycle&lt;/li&gt; &lt;li&gt;up to 8 outstanding I-cache refill requests&lt;/li&gt; &lt;li&gt;4-wide decoder&lt;/li&gt; &lt;li&gt;renaming unit can receive up to 4 macro-ops per cycle&lt;/li&gt; &lt;li&gt;up to 8 micro-operations can be dispatched into the out-of-order engine each cycle&lt;/li&gt; &lt;li&gt;The commit queue can track up to 128 micro operations&lt;/li&gt; &lt;li&gt;up to 8 micro-ops can be committed per cycle&lt;/li&gt; &lt;li&gt;a distributed issue queue with more than 100 micro-operations&lt;/li&gt; &lt;li&gt;4 integer execution pipelines, 2 load/store pipelines, and 2 Advanced SIMD pipelines&lt;/li&gt; &lt;li&gt;64kB 4-way set associative L1 data cache, 4-cycle load to use latency and a bandwidth of 32 bytes/cycle&lt;/li&gt; &lt;li&gt;The core-private 8-way set associative L2 cache is up to 1MB in size and has a load-to-use latency of 11 cycles&lt;/li&gt; &lt;li&gt;can also be configured with smaller L2 cache sizes of 256kB and 512kB with a load-to-use latency of 9 cycles&lt;/li&gt; &lt;li&gt;L2 cache connects to the system via an AMBA 5 CHI interface with 16-byte data channels&lt;/li&gt; &lt;li&gt;L3 cluster cache can be up to 2MB, with a load-to-use latency ranging between 28 and 33 cycles&lt;/li&gt; &lt;li&gt;up to 256MB of shared system-level cache&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt;</description> <link>https://jia.je/hardware/2025/09/10/arm-core-development/</link> <pubDate>Wed, 10 Sep 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2025/09/10/arm-core-development/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2025/09/10/arm-core-development.png" type="image/png" length="51844" /> </item> <item> <title>AMD Zen 3 的 BTB 结构分析</title> <category>amd</category> <category>btb</category> <category>cpu</category> <category>hardware</category> <category>zen</category> <description>&lt;h1 id=&#34;amd-zen-3-的-btb-结构分析&#34;&gt;AMD Zen 3 的 BTB 结构分析&lt;a class=&#34;headerlink&#34; href=&#34;#amd-zen-3-的-btb-结构分析&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;在之前，我们分析了 &lt;a href=&#34;../../07/amd-zen-1-btb/&#34;&gt;AMD Zen 1&lt;/a&gt; 和 &lt;a href=&#34;../amd-zen-2-btb/&#34;&gt;AMD Zen 2&lt;/a&gt; 的 BTB，接下来分析它的再下一代微架构：2020 年发布的 AMD Zen 3 的 BTB，看看 AMD 的 Zen 系列的 BTB 是如何演进的。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;官方信息&#34;&gt;官方信息&lt;a class=&#34;headerlink&#34; href=&#34;#官方信息&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;AMD 在 &lt;a href=&#34;https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/software-optimization-guides/56665.zip&#34;&gt;Software Optimization Guide for AMD EPYC™ 7003 Processors (Publication No. 56665)&lt;/a&gt; 中有如下的表述：&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;The branch target buffer (BTB) is a two-level structure accessed using the fetch address of the previous fetch block.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Zen 3 的 BTB 有两级，相比 Zen 1 和 Zen 2 少了一级。BTB 是用之前 fetch block 的地址去查询，而不再是当前 fetch block 的地址。用当前 fetch block 的地址查询 BTB 很好理解，要寻找某个地址开始的第一个分支，就用这个地址去查询 BTB，Zen 1 和 Zen 2 都是如此；用之前 fetch block 的地址，则是用更早的信息，去获取当前 fetch block 的信息，例如：&lt;/p&gt; &lt;div class=&#34;language-asm highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-0-1&#34;&gt;&lt;a id=&#34;__codelineno-0-1&#34; name=&#34;__codelineno-0-1&#34; href=&#34;#__codelineno-0-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;entrypoint1:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-2&#34;&gt;&lt;a id=&#34;__codelineno-0-2&#34; name=&#34;__codelineno-0-2&#34; href=&#34;#__codelineno-0-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;entrypoint2&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-3&#34;&gt;&lt;a id=&#34;__codelineno-0-3&#34; name=&#34;__codelineno-0-3&#34; href=&#34;#__codelineno-0-3&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-4&#34;&gt;&lt;a id=&#34;__codelineno-0-4&#34; name=&#34;__codelineno-0-4&#34; href=&#34;#__codelineno-0-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;entrypoint2:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-5&#34;&gt;&lt;a id=&#34;__codelineno-0-5&#34; name=&#34;__codelineno-0-5&#34; href=&#34;#__codelineno-0-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;# what&amp;#39;s the first branch after entrypoint2?&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;在查询从 entrypoint2 开始的第一条分支指令的时候，如果使用当前 fetch block，就是用 entrypoint2 的地址去查询，那就必须等到前面 &lt;code&gt;jmp entrypoint2&lt;/code&gt; 指令的目的地址被计算得出；如果使用之前 fetch block，就是用 entrypoint1 的地址去查询，不用等到 &lt;code&gt;jmp entrypoint2&lt;/code&gt; 指令的目的地址被计算得出。因此，如果用之前 fetch block，可以更早地进行 BTB 的访问，从而减少 BTB 的延迟，或者在相同延迟下获得更大的容量。但是，代价是：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;从 entrypoint1 跳转到的 fetch block 可能有多个，例如最后一条是间接分支指令，那就需要找到正确的分支的信息&lt;/li&gt; &lt;li&gt;可能会从不同的地址跳转到 entrypoint2 这个 fetch block，因此它的信息可能会保存多份&lt;/li&gt; &lt;/ul&gt; &lt;blockquote&gt; &lt;p&gt;Each BTB entry can hold up to two branches if the last bytes of the branches reside in the same 64-byte aligned cache line and the first branch is a conditional branch.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Zen 3 的 BTB entry 有一定的压缩能力，一个 entry 最多保存两条分支，前提是两条分支在同一个 64B 缓存行中，并且第一条分支是条件分支。这样，如果第二条分支是无条件分支，分支预测的时候，可以根据第一条分支的方向预测的结果，决定要用哪条分支的目的地址作为下一个 fetch block 的地址。虽然有压缩能力，但是没有提到单个周期预测两条分支，所以只是扩大了等效 BTB 容量。和 Zen 1、Zen 2 一样。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;L1BTB has 1024 entries and predicts with zero bubbles for conditional and unconditional direct branches, and one cycle for calls, returns and indirect branches.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Zen 3 的第一级 BTB 可以保存 1024 个 entry，但不确定这个 entry 是否可以保存两条分支，也不确定这个 entry 数量代表了实际的 entry 数量还是分支数量，后续会做实验证实；针对条件和无条件直接分支的预测不产生气泡，意味着它的延迟是一个周期。相比 Zen 2 容量翻倍，且延迟降低一个周期，猜测和使用 previous fetch block 有关。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;L2BTB has 6656 entries and creates three bubbles if its prediction differs from L1BTB.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Zen 3 的第二级 BTB 可以保存 6656 个 entry，但不确定这个 entry 是否可以保存两条分支，也不确定这个 entry 数量代表了实际的 entry 数量还是分支数量，后续会做实验证实；预测会产生三个气泡，意味着它的延迟是四个周期。&lt;/p&gt; &lt;p&gt;简单整理一下官方信息，大概有两级 BTB：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;1024-entry L1 BTB, 1 cycle latency&lt;/li&gt; &lt;li&gt;6656-entry L2 BTB, 4 cycle latency&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;相比 Zen 1 和 Zen 2 有比较大的不同：去掉了原来很小的 L0 BTB，扩大了 L1 BTB，同时延迟缩短了一个周期；虽然 L2 BTB 有所缩小，但是延迟也变短了一个周期。&lt;/p&gt; &lt;p&gt;下面结合微架构测试，进一步研究它的内部结构。&lt;/p&gt; &lt;h2 id=&#34;微架构测试&#34;&gt;微架构测试&lt;a class=&#34;headerlink&#34; href=&#34;#微架构测试&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;在之前的博客里，我们已经测试了各种处理器的 BTB，在这里也是一样的：按照一定的 stride 分布无条件直接分支，构成一个链条，然后测量 CPI。&lt;/p&gt; &lt;p&gt;考虑到 Zen 3 的 BTB 可能出现一个 entry 保存两条分支的情况，并且还对分支的类型有要求，因此下面的测试都会进行四组，分别对应四种分支模式：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;uncond：所有分支都是无条件分支：uncond, uncond, uncond, uncond, ...&lt;/li&gt; &lt;li&gt;cond：所有分支都是条件分支：cond, cond, cond, cond, ...&lt;/li&gt; &lt;li&gt;mix (uncond + cond)：条件分支和无条件分支轮流出现，但 uncond 在先：uncond, cond, uncond, cond, ...&lt;/li&gt; &lt;li&gt;mix (cond + uncond)：条件分支和无条件分支轮流出现，但 cond 在先：cond, uncond, cond, uncond, ...&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;虽然 Zen 3 使用 previous fetch block 来访问 BTB，但在这几种分支模式中，使用 previous fetch block 还是访问 current fetch block，结果都是唯一的，所以并不会对结果带来影响。&lt;/p&gt; &lt;h3 id=&#34;stride4b&#34;&gt;stride=4B&lt;a class=&#34;headerlink&#34; href=&#34;#stride4b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;首先是 stride=4B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-3-btb-4b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了三个比较显著的拐点：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个拐点是 4 条分支，CPI=1，对应 L1 BTB，没有达到完整容量，可能是因为分支太过密集&lt;/li&gt; &lt;li&gt;第二个拐点是 2048 条分支，CPI=3.6；第三个拐点是 4096 条分支，CPI=4/4.2/4.4&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Zen 3 在 stride=4B 的情况下 L1 BTB 表现比较一般，应该是牺牲了高密度分支下的性能；而主要命中的是 L2 BTB，在不同的分支模式下，测出来差不多的结果。为了验证这一点，统计了如下的性能计数器（来源：&lt;a href=&#34;https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/56214-B0-PUB.zip&#34;&gt;Processor Programming Reference (PPR) for AMD Family 19h Model 21h, Revision B0 Processors&lt;/a&gt;）：&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;PMCx08B [L2 Branch Prediction Overrides Existing Prediction (speculative)] (Core::X86::Pmc::Core::BpL2BTBCorrect)&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;它代表了 L2 BTB 提供预测（准确地说，L2 BTB 提供了预测且和 L1 BTB 提供的预测结果不同，覆盖了 L1 BTB 的预测结果）的次数，当分支数不大于 4 的时候，这个计数器的值约等于零；此后快速上升，说明后续都是 L2 BTB 在提供预测。&lt;/p&gt; &lt;p&gt;更进一步观察，发现 2048 到 4096 的 CPI 上升，来自于 L1 BTB 完全失效：2048 条分支时，L1 BTB 还能提供约 10% 的预测，所以 CPI=&lt;code&gt;0.1*1+0.9*4=3.7&lt;/code&gt;，但到 4096 条分支的时候，完全由 L2 BTB 提供分支，此时 CPI=4。&lt;/p&gt; &lt;p&gt;超过 4096 以后，则 L2 BTB 也开始缺失，出现了译码时才能发现的分支，如果这是一条 uncond 分支，那么会在译码时回滚，这一点可以通过如下性能计数器的提升来证明（来源：&lt;a href=&#34;https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/56214-B0-PUB.zip&#34;&gt;Processor Programming Reference (PPR) for AMD Family 19h Model 21h, Revision B0 Processors&lt;/a&gt;）：&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;PMCx091 [Decode Redirects] (Core::X86::Pmc::Core::BpDeReDirect): The number of times the instruction decoder overrides the predicted target.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;但在 L2 BTB 缺失后，如果译码器发现了 cond 分支，会把它预测为不跳转，所以要等到执行才能发现分支预测错误。这就导致了 cond 模式下 L2 BTB 溢出时 CPI=16，而 uncond 模式下 L2 BTB 溢出时 CPI=12，提前在译码阶段发现了 uncond 分支并纠正。&lt;/p&gt; &lt;p&gt;但译码器的纠正能力不是万能的：假如它首先发现了一条 cond 分支，在它其后又发现了一条 uncond 分支，它会用 uncond 分支去纠正，但实际上前面的 cond 分支会跳转，所以此时译码器纠正也无法提升性能，即使 BpDeReDirect 计数器的值看起来很大。&lt;/p&gt; &lt;h3 id=&#34;stride8b&#34;&gt;stride=8B&lt;a class=&#34;headerlink&#34; href=&#34;#stride8b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;接下来观察 stride=8B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-3-btb-8b.png&#34; /&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶在所有分支模式下都是 1024 个分支，CPI=1，对应 1024-entry 的 L1 BTB&lt;/li&gt; &lt;li&gt;第二个台阶不太明显，但是在 4096 附近在所有分支模式下都是一个拐点，CPI=4，对应 L2 BTB；在 mix (uncond + cond) 模式下，超过 4096 分支后 CPI 缓慢上升，到 6144 条分支 CPI=4.25，到 6656 条分支 CPI=4.85，之后 CPI 快速上升；在 mix (cond + uncond) 模式下，到 5888 条分支 CPI=5。&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;L2 BTB 的容量不太确定，超过 4096 后需要一个 entry 保存两条分支才能获得更多容量，但也带来了一定的额外的延迟。与此同时 4096 也对应了 32KB ICache 的容量，这会对分析带来干扰。&lt;/p&gt; &lt;p&gt;从 BpDeReDirect 计数器来看，uncond 分支模式下，当分支数量超过 4096 后，L2 BTB 从 4096 时无缺失，之后缺失快速提升，说明此时 L2 BTB 容量确实是 4096。在 mix (cond + uncond) 模式下，分支数超过 4096 时，BpDeReDirect 计数器略微上升，直到 6144 条分支后才有明显的上升。&lt;/p&gt; &lt;h3 id=&#34;stride16b&#34;&gt;stride=16B&lt;a class=&#34;headerlink&#34; href=&#34;#stride16b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=16B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-3-btb-16b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;相比 stride=8B，L1 BTB 的行为没有变化。4096 对应的 CPI 有所下降，从 BpL2BTBCorrect 性能计数器可以发现是 L1 BTB 起了一定的作用。在 mix (cond + uncond) 模式下，直到 5632 条分支还维持了 CPI=3.25，之后 CPI 缓慢上升，到 6656 条分支时 CPI=3.75，到 6912 条分支时 CPI=4。&lt;/p&gt; &lt;p&gt;CPI=3.25 可能是来自于 1 和 4 的加权平均：25% 的时候是 1 周期，75% 的时候是 4 周期，平均下来就是 &lt;code&gt;1*0.25+4*0.75=3.25&lt;/code&gt;。这意味着 L1 BTB 还要保持 25% 的命中率。观察 BpL2BTBCorrect 性能计数器，发现它的取值等于 75% 的分支执行次数，意味着 L1 BTB 确实提供了 25% 的预测，L2 BTB 提供了剩下 75% 的预测。这一点是挺有意思的，意味着 L1 BTB 可能采用了一些对这种循环访问模式友好的替换策略：朴素的 LRU（或类 LRU）替换策略会导致 L1 BTB 出现 100% 缺失。&lt;/p&gt; &lt;h3 id=&#34;stride32b&#34;&gt;stride=32B&lt;a class=&#34;headerlink&#34; href=&#34;#stride32b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=32B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-3-btb-32b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;相比 stride=16B，L1 BTB 的行为没有变化，但是出现了一些性能波动。所有分支模式下，L2 BTB 的拐点都出现在 5120，但性能波动比较大，mix (cond + uncond) 模式下的 CPI 达到了 4.6。通过 BpDeReDirect 性能计数器的变化，可以确认这个拐点确实是来自于 L2 BTB 的缺失。&lt;/p&gt; &lt;p&gt;前面提到，译码器的纠正能力可能会给出错误的答案，在 stride=32B 时，就会出现一个很有意思的现象：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;超出 L2 BTB 容量后，mix (uncond + cond) 模式下 BpDeReDirect 占分支数量的 50%&lt;/li&gt; &lt;li&gt;超出 L2 BTB 容量后，mix (cond + uncond) 模式下 BpDeReDirect 占分支数量的接近 100%&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;解释起来也并不复杂：stride=32B 的情况下，一个 64B cacheline 只有两条分支，那么：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;mix (uncond + cond) 模式下，第一条分支是 uncond，译码器会发现并 redirect；第二条分支是 cond，译码器会无视它，不进行 redirect；所以最后是 50% 的 redirect 比例&lt;/li&gt; &lt;li&gt;mix (cond + uncond) 模式下，第一条分支是 cond，译码器会看到后面的 uncond 分支并 redirect；第二条分支是 uncond，译码器会发现并 redirect；所以最后是接近 100% 的 redirect 比例&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;顺带一提，uncond 模式下的 BpDeReDirect 占分支数量的接近 100%，cond 模式下的 BpDeReDirect 占分支数量的 0%，都是符合预期的。&lt;/p&gt; &lt;h3 id=&#34;stride64b&#34;&gt;stride=64B&lt;a class=&#34;headerlink&#34; href=&#34;#stride64b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=64B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-3-btb-64b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;相比 stride=32B，L1 BTB 的容量减半，达到了 512。之后出现了比较明显的性能波动，但四种分支模式下，拐点依然都是出现在 5120 条分支的位置。通过 BpDeReDirect 性能计数器的变化，可以确认这个拐点确实是来自于 L2 BTB 的缺失。由于 uncond 模式下，BTB sharing 不会工作，意味着 L2 BTB 至少有 5120 个 entry。&lt;/p&gt; &lt;h3 id=&#34;stride128b&#34;&gt;stride=128B&lt;a class=&#34;headerlink&#34; href=&#34;#stride128b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=128B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-3-btb-128b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;相比 stride=64B，L1 BTB 的容量进一步减小，达到了 256；L2 BTB 的性能依然波动剧烈，但四种分支模式下，拐点依然都是出现在 5120 条分支的位置。&lt;/p&gt; &lt;p&gt;考虑到 5120 这个拐点频繁出现，认为 L2 BTB 在不考虑 BTB entry sharing 的情况下，实际容量应该是 5120。那么剩下的 1536 个分支就是来自于压缩。&lt;/p&gt; &lt;h2 id=&#34;小结&#34;&gt;小结&lt;a class=&#34;headerlink&#34; href=&#34;#小结&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;测试到这里就差不多了，更大的 stride 得到的也是类似的结果，总结一下前面的发现：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;L1 BTB 是 1024-entry，1 cycle latency，容量随着 stride 变化，大概率是 PC[n:5] 这一段被用于 index，使得 stride=64B 开始容量不断减半&lt;/li&gt; &lt;li&gt;L2 BTB 是 5120-entry，4 cycle latency；其中有 1536 个 entry 最多保存两条分支，前提是这两条分支在同一个 cacheline 当中，并且第一条是 cond，第二条是 uncond&lt;/li&gt; &lt;/ul&gt; &lt;h2 id=&#34;zen-1-到-zen-3-的-btb-的对比&#34;&gt;Zen 1 到 Zen 3 的 BTB 的对比&lt;a class=&#34;headerlink&#34; href=&#34;#zen-1-到-zen-3-的-btb-的对比&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;下面是对比表格：&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;uArch&lt;/th&gt; &lt;th&gt;AMD Zen 1&lt;/th&gt; &lt;th&gt;AMD Zen 2&lt;/th&gt; &lt;th&gt;AMD Zen 3&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;L0 BTB size&lt;/td&gt; &lt;td&gt;4+4 branches&lt;/td&gt; &lt;td&gt;8+8 branches&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L0 BTB latency&lt;/td&gt; &lt;td&gt;1 cycle&lt;/td&gt; &lt;td&gt;1 cycle&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L1 BTB size&lt;/td&gt; &lt;td&gt;256 branches&lt;/td&gt; &lt;td&gt;512 branches&lt;/td&gt; &lt;td&gt;1024 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L1 BTB latency&lt;/td&gt; &lt;td&gt;2 cycles&lt;/td&gt; &lt;td&gt;2 cycles&lt;/td&gt; &lt;td&gt;1 cycle&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L2 BTB size w/o sharing&lt;/td&gt; &lt;td&gt;2K branches&lt;/td&gt; &lt;td&gt;4K branches&lt;/td&gt; &lt;td&gt;5K branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L2 BTB size w/ sharing&lt;/td&gt; &lt;td&gt;4K branches&lt;/td&gt; &lt;td&gt;7K branches&lt;/td&gt; &lt;td&gt;6.5K branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L2 BTB latency&lt;/td&gt; &lt;td&gt;5 cycles&lt;/td&gt; &lt;td&gt;5 cycles&lt;/td&gt; &lt;td&gt;4 cycles&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Technology Node&lt;/td&gt; &lt;td&gt;14nm&lt;/td&gt; &lt;td&gt;7nm&lt;/td&gt; &lt;td&gt;7nm&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Release Year&lt;/td&gt; &lt;td&gt;2017&lt;/td&gt; &lt;td&gt;2019&lt;/td&gt; &lt;td&gt;2020&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;Zen 3 在 Zen 2 的基础上，没有更换制程，而是通过 previous fetch block 的方式，减少 L1 BTB 的延迟到 1 cycle，顺带去掉了 L0 BTB。L2 BTB 的大小进行了调整，减少了共享的部分，而增加了不限制分支类型的 BTB entry 数量，同时减少了一个周期的延迟，不确定这个延迟是单纯通过优化容量实现的，还是说也依赖了 previous fetch block 的方法来减少周期，更倾向于是后者，因为 L1 和 L2 BTB 都减少了一个周期的延迟。&lt;/p&gt; &lt;p&gt;如果按照 Intel 的 tick-tock 说法，那么 Zen 2 相比 Zen 1 是一次 tick，更换制程，微架构上做少量改动；Zen 3 相比 Zen 2 是一次 tock，不更换制程，但是在微架构上做较多改动。Zen 4 是 2022 年发布的，使用的是 5nm 制程；Zen 5 是 2024 年发布的，使用的是 4nm 制程。总结一下规律，AMD 会花费两年的时间来升级制程，并且实际上，Zen 4 和 Zen 5 不仅更新了制程，还在前端微架构上有较大的改动。&lt;/p&gt; &lt;h2 id=&#34;amd-zen-3-和-arm-neoverse-v1-的-btb-的对比&#34;&gt;AMD Zen 3 和 ARM Neoverse V1 的 BTB 的对比&lt;a class=&#34;headerlink&#34; href=&#34;#amd-zen-3-和-arm-neoverse-v1-的-btb-的对比&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;AMD Zen 3 和 ARM Neoverse V1 都是在 2020 发布的处理器，下面对它们进行一个对比：&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;uArch&lt;/th&gt; &lt;th&gt;AMD Zen 3&lt;/th&gt; &lt;th&gt;ARM Neoverse V1&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;L1/Nano BTB size&lt;/td&gt; &lt;td&gt;1024 branches&lt;/td&gt; &lt;td&gt;48*2 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L1/Nano BTB latency&lt;/td&gt; &lt;td&gt;1 cycle&lt;/td&gt; &lt;td&gt;1 cycle&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L1/Nano BTB throughput&lt;/td&gt; &lt;td&gt;1 branch&lt;/td&gt; &lt;td&gt;1-2 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L2/Main BTB size w/o sharing&lt;/td&gt; &lt;td&gt;5K branches&lt;/td&gt; &lt;td&gt;4K*2 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L2/Main BTB size w/ sharing&lt;/td&gt; &lt;td&gt;6.5K branches&lt;/td&gt; &lt;td&gt;4K*2 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L2/Main BTB latency&lt;/td&gt; &lt;td&gt;4 cycles&lt;/td&gt; &lt;td&gt;2 cycles&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L2/Main BTB throughput&lt;/td&gt; &lt;td&gt;1 branch&lt;/td&gt; &lt;td&gt;1-2 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Technology Node&lt;/td&gt; &lt;td&gt;7nm&lt;/td&gt; &lt;td&gt;5nm&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;虽然 AMD Zen 3 通过 previous fetch block 优化，实现了 1 cycle 下更大的 L1 BTB，但这一点在 2022 年发布的 ARM Neoverse V2 上被追赶：ARM Neoverse V2 的 L1/Nano BTB 也做到了 1024 的容量。&lt;/p&gt; &lt;p&gt;在 L2 BTB 方面，ARM Neoverse V1 占据了领先，无论是延迟还是容量；当然了，ARM Neoverse V1 的制程也要更加领先，ARM 采用的 5nm 对比 AMD 采用的 7nm。&lt;/p&gt; &lt;p&gt;更进一步，ARM Neoverse V1 实现了一个周期预测两条分支，即 two taken（ARM 的说法是 two predicted branches per cycle），在 2 cycle 的 Main BTB 上可以实现接近 AMD Zen 3 的 L1 BTB 的预测吞吐。AMD 也不甘示弱，在 2022 年发布的 AMD Zen 4 处理器上，实现了 two taken。&lt;/p&gt;</description> <link>https://jia.je/hardware/2025/07/08/amd-zen-3-btb/</link> <pubDate>Tue, 08 Jul 2025 00:00:01 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2025/07/08/amd-zen-3-btb/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2025/07/08/amd-zen-3-btb.png" type="image/png" length="47637" /> </item> <item> <title>AMD Zen 2 的 BTB 结构分析</title> <category>amd</category> <category>btb</category> <category>cpu</category> <category>hardware</category> <category>zen</category> <description>&lt;h1 id=&#34;amd-zen-2-的-btb-结构分析&#34;&gt;AMD Zen 2 的 BTB 结构分析&lt;a class=&#34;headerlink&#34; href=&#34;#amd-zen-2-的-btb-结构分析&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;在之前，我们分析了 &lt;a href=&#34;../../07/amd-zen-1-btb/&#34;&gt;AMD Zen 1&lt;/a&gt; 的 BTB，接下来分析它的下一代微架构：2019 年发布的 AMD Zen 2 的 BTB，看看 AMD 的 Zen 系列的 BTB 是如何演进的。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;官方信息&#34;&gt;官方信息&lt;a class=&#34;headerlink&#34; href=&#34;#官方信息&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;AMD 在 &lt;a href=&#34;https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/software-optimization-guides/56305.zip&#34;&gt;Software Optimization Guide for AMD EPYC™ 7002 Processors (Publication No. 56305)&lt;/a&gt; 中有如下的表述：&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;The branch target buffer (BTB) is a three-level structure accessed using the fetch address of the current fetch block.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Zen 2 的 BTB 有三级，是用当前 fetch block 的地址去查询，和 Zen 1 一样。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Each BTB entry includes information for branches and their targets. Each BTB entry can hold up to two branches if the branches reside in the same 64-byte aligned cache line and the first branch is a conditional branch.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Zen 2 的 BTB entry 有一定的压缩能力，一个 entry 最多保存两条分支，前提是两条分支在同一个 64B 缓存行中，并且第一条分支是条件分支。这样，如果第二条分支是无条件分支，分支预测的时候，可以根据第一条分支的方向预测的结果，决定要用哪条分支的目的地址作为下一个 fetch block 的地址。虽然有压缩能力，但是没有提到单个周期预测两条分支，所以只是扩大了等效 BTB 容量。和 Zen 1 一样。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;L0BTB holds 8 forward taken branches and 8 backward taken branches, and predicts with zero bubbles&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Zen 2 的第一级 BTB 可以保存 8 条前向分支和 8 条后向分支，预测不会带来流水线气泡，也就是说每个周期都可以预测一次。相比 Zen 1 容量翻倍。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;L1BTB has 512 entries and creates one bubble if prediction differs from L0BTB&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Zen 2 的第二级 BTB 可以保存 512 个 entry，但不确定这个 entry 是否可以保存两条分支，也不确定这个 entry 数量代表了实际的 entry 数量还是分支数量，后续会做实验证实；预测会产生单个气泡，意味着它的延迟是两个周期。相比 Zen 1 容量翻倍。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;L2BTB has 7168 entries and creates four bubbles if its prediction differs from L1BTB.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Zen 2 的第三级 BTB 可以保存 7168 个 entry，但不确定这个 entry 是否可以保存两条分支，也不确定这个 entry 数量代表了实际的 entry 数量还是分支数量，后续会做实验证实；预测会产生四个气泡，意味着它的延迟是五个周期。&lt;/p&gt; &lt;p&gt;简单整理一下官方信息，大概有三级 BTB：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;(8+8)-entry L0 BTB, 1 cycle latency&lt;/li&gt; &lt;li&gt;512-entry L1 BTB, 2 cycle latency&lt;/li&gt; &lt;li&gt;7168-entry L2 BTB, 5 cycle latency&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;从表述来看，除了容量以外基本和 Zen 1 一致，猜测是在 Zen 1 的基础上扩大了容量。&lt;/p&gt; &lt;p&gt;下面结合微架构测试，进一步研究它的内部结构。&lt;/p&gt; &lt;h2 id=&#34;微架构测试&#34;&gt;微架构测试&lt;a class=&#34;headerlink&#34; href=&#34;#微架构测试&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;在之前的博客里，我们已经测试了各种处理器的 BTB，在这里也是一样的：按照一定的 stride 分布无条件直接分支，构成一个链条，然后测量 CPI。&lt;/p&gt; &lt;p&gt;考虑到 Zen 2 的 BTB 可能出现一个 entry 保存两条分支的情况，并且还对分支的类型有要求，因此下面的测试都会进行四组，分别对应四种分支模式：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;uncond：所有分支都是无条件分支：uncond, uncond, uncond, uncond, ...&lt;/li&gt; &lt;li&gt;cond：所有分支都是条件分支：cond, cond, cond, cond, ...&lt;/li&gt; &lt;li&gt;mix (uncond + cond)：条件分支和无条件分支轮流出现，但 uncond 在先：uncond, cond, uncond, cond, ...&lt;/li&gt; &lt;li&gt;mix (cond + uncond)：条件分支和无条件分支轮流出现，但 cond 在先：cond, uncond, cond, uncond, ...&lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;stride4b&#34;&gt;stride=4B&lt;a class=&#34;headerlink&#34; href=&#34;#stride4b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;首先是 stride=4B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-2-btb-4b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了三个比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;所有分支模式下，第一个台阶都是到 8 条分支，CPI=1，8 对应了 8-entry 的 L0 BTB&lt;/li&gt; &lt;li&gt;所有分支模式下，第二个台阶都是到 256 条分支，CPI=2，对应了 512-entry 的 L1 BTB，只体现出了一半的容量；但在 mix (uncond + cond) 和 mix (cond + uncond) 模式下，分支从 256 到 512 时 CPI 缓慢上升，意味着 L1 BTB 的 512-entry 还是可以完整访问，只是带来了一定的开销：CPI 从 2 增加到了 2.5&lt;/li&gt; &lt;li&gt;在 uncond 和 cond 模式下，第三个台阶到 4096 条分支，CPI=5，对应 L2 BTB，没有显现出完整的 7168 的大小&lt;/li&gt; &lt;li&gt;在 mix (uncond + cond) 模式下，第三个台阶延伸到了 5120，超出了 4096，依然没有显现出完整的 7168 的大小&lt;/li&gt; &lt;li&gt;在 mix (cond + uncond) 模式下，第三个台阶延伸到了 7168，显现出完整的 7168 的大小&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;和 Zen 1 不同，Zen 2 的 L1 BTB 出现了不同模式下容量不同的情况，原因未知，后续还会看到类似的情况。&lt;/p&gt; &lt;p&gt;Zen 2 的 L2 BTB 依然是带有压缩的，只有在 mix (cond + uncond) 模式下才可以尽可能地用上所有的容量，而其余的三种模式都有容量上的损失。&lt;/p&gt; &lt;h3 id=&#34;stride8b&#34;&gt;stride=8B&lt;a class=&#34;headerlink&#34; href=&#34;#stride8b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;接下来观察 stride=8B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-2-btb-8b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;现象和 stride=4B 基本相同，L1 BTB 从 256 到 512 部分的变化斜率有所不同，其余部分一致。&lt;/p&gt; &lt;h3 id=&#34;stride16b&#34;&gt;stride=16B&lt;a class=&#34;headerlink&#34; href=&#34;#stride16b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=16B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-2-btb-16b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;相比 stride=4B/8B，L0 BTB 和 L2 BTB 的行为没有变化；除了 cond 模式以外，L1 BTB 的容量减半到了 128，意味着 L1 BTB 采用了组相连，此时有一半的 set 不能被用上。此外，比较特别的是，从 stride=16B 开始，CPI=5 的平台出现了波动，uncond 模式下 CPI 从 5 变到 4 再变到了 5，猜测此时 L1 BTB 也有一定的比例会介入。&lt;/p&gt; &lt;h3 id=&#34;stride32b&#34;&gt;stride=32B&lt;a class=&#34;headerlink&#34; href=&#34;#stride32b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=32B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-2-btb-32b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;相比 stride=16B，L0 BTB 的行为没有变化；除了 cond 模式以外，L1 BTB 的容量进一步减到了 64，符合组相连的预期；L2 BTB 在 mix (uncond + cond) 模式下不再能体现出 5120 的容量，而是 4096：此时在一个 64B cacheline 中只有两条分支，第一条分支是 uncond，第二条分支是 cond，不满足 entry 共享的条件（必须 cond + uncond，不能是 uncond + cond），此时 uncond 和 cond 分别保存在两个 entry 中，每个 entry 只保存一条分支，因此 L2 BTB 只能体现出 4096 的容量。而 mix (cond + uncond) 模式依然满足 entry 共享的条件，所以依然体现出 7168 的容量。特别地，在 mix (cond + uncond) 模式下出现了非常剧烈的 CPI 抖动，可能出现了一些预期之外的性能问题。&lt;/p&gt; &lt;h3 id=&#34;stride64b&#34;&gt;stride=64B&lt;a class=&#34;headerlink&#34; href=&#34;#stride64b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=64B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-2-btb-64b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;相比 stride=32B，L0 BTB 的行为没有变化；除了 cond 模式以外，L1 BTB 的容量进一步减到了 32，符合组相连的预期，但 cond 模式下依然保持了 512 的容量；L2 BTB 在 mix (cond + uncond) 模式下只能体现出 4096 的容量，此时每个 64B cacheline 都只有一条分支，不满足两条分支共享一个 entry 的条件。&lt;/p&gt; &lt;h3 id=&#34;stride128b&#34;&gt;stride=128B&lt;a class=&#34;headerlink&#34; href=&#34;#stride128b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=128B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-2-btb-128b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;相比 stride=64B，L0 BTB 的行为没有变化；除了 cond 模式以外，L1 BTB 的容量进一步减到了 16，符合组相连的预期，而 cond 模式下 L1 BTB 容量也减少到了 256；L2 BTB 的容量减半到了 2048，意味着 L2 BTB 也是组相连结构。&lt;/p&gt; &lt;h2 id=&#34;小结&#34;&gt;小结&lt;a class=&#34;headerlink&#34; href=&#34;#小结&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;测试到这里就差不多了，更大的 stride 得到的也是类似的结果，总结一下前面的发现：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;L0 BTB 是 (8+8)-entry，1 cycle latency，不随着 stride 变化，全相连&lt;/li&gt; &lt;li&gt;L1 BTB 是 512-entry，2 cycle latency，容量随着 stride 变化，大概率是 PC[n:3] 这一段被用于 index，使得 stride=16B 开始容量不断减半；但 cond 模式下的行为和其余几种模式不同，直到 stride=128B 才开始容量减半&lt;/li&gt; &lt;li&gt;L2 BTB 是 4096-entry，5 cycle latency，容量随着 stride 变化，大概率是 PC[n:6] 这一段被用于 index，使得 stride=128B 开始容量不断减半；其中有 3072 个 entry 最多保存两条分支，前提是这两条分支在同一个 cacheline 当中，并且第一条是 cond，第二条是 uncond；因此最多保存 7168 条分支&lt;/li&gt; &lt;/ul&gt; &lt;h2 id=&#34;zen-1-和-zen-2-的-btb-的对比&#34;&gt;Zen 1 和 Zen 2 的 BTB 的对比&lt;a class=&#34;headerlink&#34; href=&#34;#zen-1-和-zen-2-的-btb-的对比&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;下面是对比表格：&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;uArch&lt;/th&gt; &lt;th&gt;AMD Zen 1&lt;/th&gt; &lt;th&gt;AMD Zen 2&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;L0 BTB size&lt;/td&gt; &lt;td&gt;4+4 branches&lt;/td&gt; &lt;td&gt;8+8 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L0 BTB latency&lt;/td&gt; &lt;td&gt;1 cycle&lt;/td&gt; &lt;td&gt;1 cycle&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L1 BTB size&lt;/td&gt; &lt;td&gt;256 branches&lt;/td&gt; &lt;td&gt;512 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L1 BTB latency&lt;/td&gt; &lt;td&gt;2 cycles&lt;/td&gt; &lt;td&gt;2 cycles&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L2 BTB size w/o sharing&lt;/td&gt; &lt;td&gt;2K branches&lt;/td&gt; &lt;td&gt;4K branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L2 BTB size w/ sharing&lt;/td&gt; &lt;td&gt;4K branches&lt;/td&gt; &lt;td&gt;7K branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L2 BTB latency&lt;/td&gt; &lt;td&gt;5 cycles&lt;/td&gt; &lt;td&gt;5 cycles&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Technology Node&lt;/td&gt; &lt;td&gt;14nm&lt;/td&gt; &lt;td&gt;7nm&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Release Year&lt;/td&gt; &lt;td&gt;2017&lt;/td&gt; &lt;td&gt;2019&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;可见 Zen 2 在容量上做了一定的扩展，但机制上比较类似；特别地，可能是观察到 cond + uncond 的压缩能够生效的比例没有那么高，所以只允许其中一部分 entry 被压缩，例如 4 路组相连，只有前 3 个 way 是可以保存两条分支；剩下的一个 way 只能保存一条分支。&lt;/p&gt; &lt;h2 id=&#34;amd-zen-2-和-arm-neoverse-n1-的-btb-的对比&#34;&gt;AMD Zen 2 和 ARM Neoverse N1 的 BTB 的对比&lt;a class=&#34;headerlink&#34; href=&#34;#amd-zen-2-和-arm-neoverse-n1-的-btb-的对比&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;AMD Zen 2 和 ARM Neoverse N1 都是在 2019 发布的处理器，下面对它们进行一个对比：&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;uArch&lt;/th&gt; &lt;th&gt;AMD Zen 2&lt;/th&gt; &lt;th&gt;ARM Neoverse N1&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;L0/Nano BTB size&lt;/td&gt; &lt;td&gt;8+8 branches&lt;/td&gt; &lt;td&gt;16 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L0/Nano BTB latency&lt;/td&gt; &lt;td&gt;1 cycle&lt;/td&gt; &lt;td&gt;1 cycle&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L1/Micro BTB size&lt;/td&gt; &lt;td&gt;512 branches&lt;/td&gt; &lt;td&gt;64 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L1/Micro BTB latency&lt;/td&gt; &lt;td&gt;2 cycles&lt;/td&gt; &lt;td&gt;2 cycles&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L2/Main BTB size w/o sharing&lt;/td&gt; &lt;td&gt;4K branches&lt;/td&gt; &lt;td&gt;3K*2 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L2/Main BTB size w/ sharing&lt;/td&gt; &lt;td&gt;7K branches&lt;/td&gt; &lt;td&gt;3K*2 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;L2/Main BTB latency&lt;/td&gt; &lt;td&gt;5 cycles&lt;/td&gt; &lt;td&gt;2-3 cycles&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Technology Node&lt;/td&gt; &lt;td&gt;7nm&lt;/td&gt; &lt;td&gt;7nm&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;可见 AMD Zen 2 在 BTB 容量上有优势，但是延迟要更长；两者都在最后一级 BTB 上做了压缩，但是压缩的方法和目的不同：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;AMD Zen 2 的压缩方法是，把同一个 64B cacheline 内一条 cond 和一条 uncond 指令放在同一个 entry 当中。这样做的好处是，当预测到 cond 分支不跳转的时候，可以直接根据 uncond 指令的信息，得到下一个 fetch block 的地址；但是也对代码的结构有要求，必须是在同一个 cacheline 中，依次出现一个 cond 和一个 uncond&lt;/li&gt; &lt;li&gt;ARM Neoverse N1 的压缩方法是，根据立即数范围对分支进行分类，如果分支的立即数范围比较小，就只占用一个 entry 的一半也就是 41 bit；如果分支的立即数范围过大，就占用一个完整的 82 bit 的 entry；这主要是一个减少 SRAM 占用的优化，避免了所有的分支都要记录完整的 82 bit 信息；对代码的结构要求比较小，只要是跳转距离不太远的分支，都可以存到 41 bit 内&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;二者都没有实现一个周期预测两条分支，即 two taken（ARM 的说法是 two predicted branches per cycle）。这要等到 2020 年的 ARM Neoverse N2/V1，或者 2022 年的 AMD Zen 4 才被实现。&lt;/p&gt; &lt;p&gt;注意到 AMD 的 &lt;a href=&#34;https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/software-optimization-guides/56305.zip&#34;&gt;Software Optimization Guide for AMD EPYC™ 7002 Processors (Publication No. 56305)&lt;/a&gt; 文档里，有这么一段表述：&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Branches whose target crosses a half-megabyte aligned boundary are unable to be installed in the L0 BTB or to share BTB entries with other branches.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;也就是说，如果两个分支要共享一个 BTB entry，那么它们的目的地址不能跨越 512KB 边界，也就是和分支地址的偏移量不超过 19 位。按 48 位虚拟地址计算，如果 BTB entry 只记录一条分支，最多需要记录目的地址的完整 48 位地址；如果现在 BTB entry 要存两条分支，这两条分支的目的地址都只需要记录 19 位，加起来也就 38 位，还可以空余 10 位的信息用来维护 BTB sharing 所需的额外信息。&lt;/p&gt; &lt;p&gt;所以说到底，无论是 AMD 还是 ARM，做的事情都是对一个固定长度的 entry 设置了不同的格式，一个格式保存的地址位数多，但是只能保存一个分支；另一个格式保存的地址位数少，但是可以保存两个分支。区别就是 AMD 对两个分支的类型和位置有要求，而 ARM 允许这两个分支毫无关系。这就是不同厂商的取舍了。&lt;/p&gt;</description> <link>https://jia.je/hardware/2025/07/08/amd-zen-2-btb/</link> <pubDate>Tue, 08 Jul 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2025/07/08/amd-zen-2-btb/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2025/07/08/amd-zen-2-btb.png" type="image/png" length="47306" /> </item> <item> <title>AMD Zen 1 的 BTB 结构分析</title> <category>amd</category> <category>btb</category> <category>cpu</category> <category>hardware</category> <category>zen</category> <description>&lt;h1 id=&#34;amd-zen-1-的-btb-结构分析&#34;&gt;AMD Zen 1 的 BTB 结构分析&lt;a class=&#34;headerlink&#34; href=&#34;#amd-zen-1-的-btb-结构分析&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;AMD Zen 1 是 AMD 在 2017 年发布的 Zen 系列第一代微架构。在之前，我们分析了 ARM Neoverse &lt;a href=&#34;../../../06/05/arm-neoverse-n1-btb/&#34;&gt;N1&lt;/a&gt; 和 &lt;a href=&#34;../../../06/23/arm-neoverse-v1-btb/&#34;&gt;V1&lt;/a&gt; 的 BTB，那么现在也把视线转到 AMD 上，看看 AMD 的 Zen 系列的 BTB 是如何演进的。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;官方信息&#34;&gt;官方信息&lt;a class=&#34;headerlink&#34; href=&#34;#官方信息&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;AMD 在 &lt;a href=&#34;https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/software-optimization-guides/55723_3_01_0.zip&#34;&gt;Software Optimization Guide for AMD Family 17h Processors (Publication No. 55723)&lt;/a&gt; 中有如下的表述：&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;The branch target buffer (BTB) is a three-level structure accessed using the fetch address of the current fetch block.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Zen 1 的 BTB 有三级，是用当前 fetch block 的地址去查询。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Each BTB entry includes information for branches and their targets. Each BTB entry can hold up to two branches if the branches reside in the same 64-byte aligned cache line and the first branch is a conditional branch.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Zen 1 的 BTB entry 有一定的压缩能力，一个 entry 最多保存两条分支，前提是两条分支在同一个 64B 缓存行中，并且第一条分支是条件分支。这样，如果第二条分支是无条件分支，分支预测的时候，可以根据第一条分支的方向预测的结果，决定要用哪条分支的目的地址作为下一个 fetch block 的地址。虽然有压缩能力，但是没有提到单个周期预测两条分支，所以只是扩大了等效 BTB 容量。&lt;/p&gt; &lt;p&gt;例如，有这么一段代码：&lt;/p&gt; &lt;div class=&#34;language-asm highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-0-1&#34;&gt;&lt;a id=&#34;__codelineno-0-1&#34; name=&#34;__codelineno-0-1&#34; href=&#34;#__codelineno-0-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;# fetch block entrypoint&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-2&#34;&gt;&lt;a id=&#34;__codelineno-0-2&#34; name=&#34;__codelineno-0-2&#34; href=&#34;#__codelineno-0-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;entrypoint:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-3&#34;&gt;&lt;a id=&#34;__codelineno-0-3&#34; name=&#34;__codelineno-0-3&#34; href=&#34;#__codelineno-0-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;# do something&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-4&#34;&gt;&lt;a id=&#34;__codelineno-0-4&#34; name=&#34;__codelineno-0-4&#34; href=&#34;#__codelineno-0-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nf&#34;&gt;jnz&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;targetA&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-5&#34;&gt;&lt;a id=&#34;__codelineno-0-5&#34; name=&#34;__codelineno-0-5&#34; href=&#34;#__codelineno-0-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;# do something&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-6&#34;&gt;&lt;a id=&#34;__codelineno-0-6&#34; name=&#34;__codelineno-0-6&#34; href=&#34;#__codelineno-0-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;targetB&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;那么 jnz 和 jmp 指令可以放到同一个 entry 当中，一次读出来，然后对 jnz 指令进行分支方向预测：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;如果 jnz 预测为跳转，那么当前 fetch block 从 entrypoint 开始，到 jnz 结束；下一个 fetch block 从 targetA 开始&lt;/li&gt; &lt;li&gt;如果 jnz 预测为不跳转，那么当前 fetch block 从 entrypoint 开始，到 jmp 结束；下一个 fetch block 从 targetB 开始&lt;/li&gt; &lt;/ul&gt; &lt;blockquote&gt; &lt;p&gt;L0BTB holds 4 forward taken branches and 4 backward taken branches, and predicts with zero bubbles.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Zen 1 的第一级 BTB 可以保存 4 条前向分支和 4 条后向分支，预测不会带来流水线气泡，也就是说每个周期都可以预测一次。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;L1BTB has 256 entries and creates one bubble if prediction differs from L0BTB.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Zen 1 的第二级 BTB 可以保存 256 个 entry，但不确定这个 entry 是否可以保存两条分支，也不确定这个 entry 数量代表了实际的 entry 数量还是分支数量，后续会做实验证实；预测会产生单个气泡，意味着它的延迟是两个周期。&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;L2BTB has 4096 entries and creates four bubbles if its prediction differs from L1BTB.&lt;/p&gt; &lt;/blockquote&gt; &lt;p&gt;Zen 1 的第三级 BTB 可以保存 4096 个 entry，但不确定这个 entry 是否可以保存两条分支，也不确定这个 entry 数量代表了实际的 entry 数量还是分支数量，后续会做实验证实；预测会产生四个气泡，意味着它的延迟是五个周期。&lt;/p&gt; &lt;p&gt;简单整理一下官方信息，大概有三级 BTB：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;(4+4)-entry L0 BTB, 1 cycle latency&lt;/li&gt; &lt;li&gt;256-entry L1 BTB, 2 cycle latency&lt;/li&gt; &lt;li&gt;4096-entry L2 BTB, 5 cycle latency&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;下面结合微架构测试，进一步研究它的内部结构。&lt;/p&gt; &lt;h2 id=&#34;微架构测试&#34;&gt;微架构测试&lt;a class=&#34;headerlink&#34; href=&#34;#微架构测试&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;在之前的博客里，我们已经测试了各种处理器的 BTB，在这里也是一样的：按照一定的 stride 分布无条件直接分支，构成一个链条，然后测量 CPI。&lt;/p&gt; &lt;p&gt;考虑到 Zen 1 的 BTB 可能出现一个 entry 保存两条分支的情况，并且还对分支的类型有要求，因此下面的测试都会进行四组，分别对应四种分支模式：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;uncond：所有分支都是无条件分支：uncond, uncond, uncond, uncond, ...&lt;/li&gt; &lt;li&gt;cond：所有分支都是条件分支：cond, cond, cond, cond, ...&lt;/li&gt; &lt;li&gt;mix (uncond + cond)：条件分支和无条件分支轮流出现，但 uncond 在先：uncond, cond, uncond, cond, ...&lt;/li&gt; &lt;li&gt;mix (cond + uncond)：条件分支和无条件分支轮流出现，但 cond 在先：cond, uncond, cond, uncond, ...&lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;stride4b&#34;&gt;stride=4B&lt;a class=&#34;headerlink&#34; href=&#34;#stride4b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;首先是 stride=4B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-1-btb-4b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了三个比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;所有分支模式下，第一个台阶都是到 4 条分支，CPI=1.25，比 1 周期略高，猜测是因为循环体比较小，循环结束的操作的开销没有平摊造成的；4 对应了 4-entry 的 L0 BTB&lt;/li&gt; &lt;li&gt;所有分支模式下，第二个台阶都是到 256 条分支，CPI=2，对应了 256-entry 的 L1 BTB，意味着 L1 BTB 没有做一个 BTB entry 记录两条分支的优化，实际上就是 256 个 entry 保存 256 条分支&lt;/li&gt; &lt;li&gt;在 uncond 和 cond 模式下，第三个台阶到 2048 条分支，CPI=5，对应 L2 BTB，没有显现出完整的 4096 的大小，意味着 L2 BTB 实际上只有 2048 个 entry，每个 entry 最多保存两条分支，而 uncond 和 cond 模式下，不满足每个 entry 保存两条分支的条件，所以只保存了 2048 条分支&lt;/li&gt; &lt;li&gt;在 mix (uncond + cond) 模式下，第三个台阶一直延伸到了 3072，超出了 2048，意味着出现了两条分支保存在一个 entry 的情况，但并没有体现出完整的 4096 条分支的大小&lt;/li&gt; &lt;li&gt;在 mix (cond + uncond) 模式下，第三个台阶延伸到了 4096，体现出完整的 4096 的 L2 BTB 大小&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;可以观察到，过了 L2 BTB 容量以后，性能骤降到十多个 cycle，此时还没有超出 L1 ICache 容量，这么长的延迟，即使是在 uncond 模式下，可以在译码的时候发现 uncond 分支并 redirect，也要 16+ 个周期，可见其流水线之长。&lt;/p&gt; &lt;h3 id=&#34;stride8b&#34;&gt;stride=8B&lt;a class=&#34;headerlink&#34; href=&#34;#stride8b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;接下来观察 stride=8B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-1-btb-8b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;现象和 stride=4B 基本相同，各级 BTB 显现出来的大小没有变化。&lt;/p&gt; &lt;h3 id=&#34;stride16b&#34;&gt;stride=16B&lt;a class=&#34;headerlink&#34; href=&#34;#stride16b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=16B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-1-btb-16b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;相比 stride=4B/8B，L0 BTB 的行为没有变化；L1 BTB 的容量减半到了 128，意味着 L1 BTB 采用了组相连，此时有一半的 set 不能被用上。此外，比较特别的是，从 stride=16B 开始，CPI=5 的平台出现了波动，CPI 从 5 变到 4 再变到了 5，猜测此时 L1 BTB 也有一定的比例会介入。L2 BTB 在 mix (uncond + cond) 模式下，拐点从 3072 前移到 2560。&lt;/p&gt; &lt;h3 id=&#34;stride32b&#34;&gt;stride=32B&lt;a class=&#34;headerlink&#34; href=&#34;#stride32b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=32B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-1-btb-32b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;相比 stride=16B，L0 BTB 的行为没有变化；L1 BTB 的容量进一步减到了 64，符合组相连的预期；L2 BTB 在 mix (uncond + cond) 模式下不再能体现出 3072 的容量，而是 2048：此时在一个 64B cacheline 中只有两条分支，第一条分支是 uncond，第二条分支是 cond，不满足 entry 共享的条件（必须 cond + uncond，不能是 uncond + cond），此时 uncond 和 cond 分别保存在两个 entry 中，每个 entry 只保存一条分支，因此 L2 BTB 只能体现出 2048 的容量。而 mix (cond + uncond) 模式依然满足 entry 共享的条件，所以依然体现出 4096 的容量。&lt;/p&gt; &lt;h3 id=&#34;stride64b&#34;&gt;stride=64B&lt;a class=&#34;headerlink&#34; href=&#34;#stride64b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=64B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-1-btb-64b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;相比 stride=32B，L0 BTB 的行为没有变化；L1 BTB 的容量进一步减到了 32，符合组相连的预期；L2 BTB 在 mix (cond + uncond) 模式下只能体现出 2048 的容量，此时每个 64B cacheline 都只有一条分支，不满足两条分支共享一个 entry 的条件。&lt;/p&gt; &lt;h3 id=&#34;stride128b&#34;&gt;stride=128B&lt;a class=&#34;headerlink&#34; href=&#34;#stride128b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=128B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../amd-zen-1-btb-128b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;相比 stride=64B，L0 BTB 的行为没有变化；L1 BTB 的容量进一步减到了 16，符合组相连的预期；L2 BTB 的容量减半到了 1024，意味着 L2 BTB 也是组相连结构。&lt;/p&gt; &lt;h2 id=&#34;小结&#34;&gt;小结&lt;a class=&#34;headerlink&#34; href=&#34;#小结&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;测试到这里就差不多了，更大的 stride 得到的也是类似的结果，总结一下前面的发现：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;L0 BTB 是 (4+4)-entry，1 cycle latency，不随着 stride 变化，全相连&lt;/li&gt; &lt;li&gt;L1 BTB 是 256-entry，2 cycle latency，容量随着 stride 变化，大概率是 PC[n:3] 这一段被用于 index，使得 stride=16B 开始容量不断减半&lt;/li&gt; &lt;li&gt;L2 BTB 是 2048-entry，5 cycle latency，容量随着 stride 变化，大概率是 PC[n:6] 这一段被用于 index，使得 stride=128B 开始容量不断减半；每个 entry 最多保存两条分支，前提是这两条分支在同一个 cacheline 当中，并且第一条是 cond，第二条是 uncond；因此最多保存 4096 个分支&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;也总结一下前面发现了各种没有解释的遗留问题：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;stride=4B/8B/16B 且为 mix (uncond + cond) 模式时，L2 BTB 体现出 3072/3072/2560 的容量，而非 4096：解析见后&lt;/li&gt; &lt;li&gt;L2 BTB 对应的 CPI=5 的台阶出现比较明显的，在 4-5 之间的波动：暂无解释&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;接下来尝试解析一下这些遗留问题背后的原理。部分遗留问题，并没有被解释出来，欢迎读者提出猜想。&lt;/p&gt; &lt;h2 id=&#34;解析遗留问题&#34;&gt;解析遗留问题&lt;a class=&#34;headerlink&#34; href=&#34;#解析遗留问题&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;stride4b8b16b-且为-mix-uncond--cond-模式时l2-btb-体现出-307230722560-的容量而非-4096&#34;&gt;stride=4B/8B/16B 且为 mix (uncond + cond) 模式时，L2 BTB 体现出 3072/3072/2560 的容量，而非 4096&lt;a class=&#34;headerlink&#34; href=&#34;#stride4b8b16b-且为-mix-uncond--cond-模式时l2-btb-体现出-307230722560-的容量而非-4096&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;前面测试出来，观察到两个奇怪的容量：3072 和 2560，分别有 3 和 5 的因子。下面通过进一步的实验，观察它的来源。&lt;/p&gt; &lt;h4 id=&#34;stride16b-对应-2560-的-l2-btb-容量&#34;&gt;stride=16B 对应 2560 的 L2 BTB 容量&lt;a class=&#34;headerlink&#34; href=&#34;#stride16b-对应-2560-的-l2-btb-容量&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;首先针对这个 2560 的拐点，做了一系列测试，在 stride=16B 的情况下，测试不同的 uncond/cond 分支的组合，下面是 64B cacheline 内四条分支的类型的不同组合（U 代表 Uncond，C 代表 Cond），以及该组合对应的容量：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;CCCC: 2048（即 cond 模式）&lt;/li&gt; &lt;li&gt;CCCU: 2560&lt;/li&gt; &lt;li&gt;CCUC: 2560&lt;/li&gt; &lt;li&gt;CCUU: 2560&lt;/li&gt; &lt;li&gt;CUCC: 2560&lt;/li&gt; &lt;li&gt;CUCU: 4096（即 mix (cond + uncond) 模式）&lt;/li&gt; &lt;li&gt;CUUC: 2560&lt;/li&gt; &lt;li&gt;CUUU: 2560&lt;/li&gt; &lt;li&gt;UCCC: 2048&lt;/li&gt; &lt;li&gt;UCCU: 2560&lt;/li&gt; &lt;li&gt;UCUC: 2560（即 mix (uncond + cond) 模式）&lt;/li&gt; &lt;li&gt;UCUU: 2560&lt;/li&gt; &lt;li&gt;UUCC: 2048&lt;/li&gt; &lt;li&gt;UUCU: 2560&lt;/li&gt; &lt;li&gt;UUUC: 2048&lt;/li&gt; &lt;li&gt;UUUU: 2048（即 uncond 模式）&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;可以观察到，如果没有出现连续的 CU（CCCC/UCCC/UUCC/UUUC/UUUU），容量是 2048；如果出现了一组 CU（CC&lt;strong&gt;CU&lt;/strong&gt;/C&lt;strong&gt;CU&lt;/strong&gt;C/C&lt;strong&gt;CU&lt;/strong&gt;U/&lt;strong&gt;CU&lt;/strong&gt;CC/&lt;strong&gt;CU&lt;/strong&gt;UC/&lt;strong&gt;CU&lt;/strong&gt;UU/UC&lt;strong&gt;CU&lt;/strong&gt;/U&lt;strong&gt;CU&lt;/strong&gt;C/U&lt;strong&gt;CU&lt;/strong&gt;U/UU&lt;strong&gt;CU&lt;/strong&gt;），容量是 2560；出现了两组 CU（&lt;strong&gt;CUCU&lt;/strong&gt;），就是 mix (cond + uncond) 模式，容量是 4096。&lt;/p&gt; &lt;p&gt;一种可能的猜想：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;如果没有出现连续的 CU，那么每个 branch 占用一个 entry，那么容量就是 2048 个 branch&lt;/li&gt; &lt;li&gt;如果出现了一组 CU，那么一个 64B cacheline 里的 4 个 branch 对应 3 个 entry，那么前 2048 个 branch 对应 1536 个 entry，还剩下 512 个 entry，这些 entry 每个 entry 只放 1 个 branch（讨论见后），所以最后容量是 &lt;code&gt;2048+512=2560&lt;/code&gt; 个 branch&lt;/li&gt; &lt;li&gt;如果出现了两组 CU，那么每一组 CU 的两个 branch 对应一个 entry，容量是 4096 个 branch&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;但是也遗留了一个问题，就是只有一组 CU 的情况下，为啥剩下的 512 个 entry 只放 512 个 branch，而不能放 1024 个 branch，按理说是可能再次出现 cond + uncond 合并？这个问题暂时还没有解释。&lt;/p&gt; &lt;p&gt;由此可以看出，2560 的来源是 4 路组相连，然后其中一路发生了 cond + uncond 的合并，所以最终是 5 个分支保存到 4 路当中，再来一条分支就会放不下。&lt;/p&gt; &lt;h4 id=&#34;stride4b8b-对应-3072-的-l2-btb-容量&#34;&gt;stride=4B/8B 对应 3072 的 L2 BTB 容量&lt;a class=&#34;headerlink&#34; href=&#34;#stride4b8b-对应-3072-的-l2-btb-容量&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;带着上面的分析，再去观察 stride=4B/8B 时的 3072:3072 有 3 的因子，所以大概率是从 2 路组相连得来，其中一路出现了 cond + uncond 的合并，所以出现了 3 个 branch 占用 2 个 entry 的情况，最后体现出来就是 3072 的 L2 BTB 容量。&lt;/p&gt; &lt;p&gt;似乎到这里，3072 和 2560 分别的 3 和 5 的因子都能解释了，剩下的就是解析具体的组相连的结构。&lt;/p&gt; &lt;h4 id=&#34;组相连分析&#34;&gt;组相连分析&lt;a class=&#34;headerlink&#34; href=&#34;#组相连分析&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;那么到底是 2 路组相连，还是 4 路组相连呢，另外这个组相连的 set 是怎么构成的呢？&lt;/p&gt; &lt;p&gt;首先回忆一下，在 &lt;a href=&#34;../../../06/05/arm-neoverse-n1-btb/&#34;&gt;ARM Neoverse N1&lt;/a&gt; 中，连续的 32B 内能放 6 个分支，但是 stride=8B 的时候，一次就会往同一个 set 里增加 4 个分支，于是一个 set 内的分支数从 0 变到 4 再变到 8，拐点出现在 4 个分支，而不是 6 个分支。因此为了达到前面出现的 3072 和 2560 的拐点，新增的分支也得均匀地分到各个 set 当中。&lt;/p&gt; &lt;p&gt;前面根据 L2 BTB 的容量分析到，L2 BTB 的 Index 可能是 PC[n:6]，但肯定不是简单的这么取，否则也会出现 ARM Neoverse N1 类似的问题。只能说明 PC[6] 往上有若干个 bit 是单独出现在 L2 BTB 的 Index 当中的，而 PC[5] 以下的 bit，可能以某种哈希函数的形式，参与到 Index 当中。&lt;/p&gt; &lt;p&gt;所以，L2 BTB 可能是以 PC[n:6] 作为 Index 去访问，然后内部有多个 bank，每个 bank 内部是 2 路组相连。bank index 是通过 PC 经过哈希计算得来，使得在 stride=4B/8B 的时候，体现出 2 路组相连，而在 stride=16B 的时候，体现出 4 路组相连。同时，分支还能够均匀地分布到各个 bank 当中，避免了和 ARM Neoverse N1 类似的情况的发生。&lt;/p&gt;</description> <link>https://jia.je/hardware/2025/07/07/amd-zen-1-btb/</link> <pubDate>Mon, 07 Jul 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2025/07/07/amd-zen-1-btb/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2025/07/07/amd-zen-1-btb.png" type="image/png" length="46329" /> </item> <item> <title>ARM Neoverse V1 (代号 Zeus) 的 BTB 结构分析</title> <category>arm</category> <category>btb</category> <category>cpu</category> <category>hardware</category> <category>neoverse</category> <description>&lt;h1 id=&#34;arm-neoverse-v1-代号-zeus-的-btb-结构分析&#34;&gt;ARM Neoverse V1 (代号 Zeus) 的 BTB 结构分析&lt;a class=&#34;headerlink&#34; href=&#34;#arm-neoverse-v1-代号-zeus-的-btb-结构分析&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;ARM Neoverse V1 是 ARM Neoverse N1 的下一代服务器 CPU，在 2020 年发布。此前我们分析过 &lt;a href=&#34;../../05/arm-neoverse-n1-btb/&#34;&gt;Neoverse N1 的 BTB 设计&lt;/a&gt;。而 ARM Neoverse V1 在很多地方都和 Cortex-X1 类似，相比 Neoverse N1/Cortex-A76 有了一些改进，在这里对它的 BTB 做一些分析。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;官方信息&#34;&gt;官方信息&lt;a class=&#34;headerlink&#34; href=&#34;#官方信息&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;首先收集了一些 ARM Neoverse V1 的 BTB 结构的官方信息：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://teratec.eu/library/pdf/forum/2021/A05-03.pdf&#34;&gt;SW defined cars: HPC, from the cloud to the dashboard for an amazing driver experience&lt;/a&gt;&lt;ul&gt; &lt;li&gt;64KB L1 ICache, 2x32B bandwidth&lt;/li&gt; &lt;li&gt;8K-entry main BTB&lt;/li&gt; &lt;li&gt;96-entry nano BTB, 0 cycle bubble&lt;/li&gt; &lt;li&gt;2 stage prediction pipeline: P1 &amp;amp; P2，大概率 nano BTB 在 P1，main BTB 在 P2&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://hc2023.hotchips.org/assets/program/conference/day1/CPU1/HC2023.Arm.MagnusBruce.v04.FINAL.pdf&#34;&gt;Arm Neoverse V2 platform: Leadership Performance and Power Efficiency for Next-Generation Cloud Computing, ML and HPC Workloads&lt;/a&gt;&lt;ul&gt; &lt;li&gt;2 predicted branches per cycle，每周期最多预测两条分支&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;简单整理一下官方信息，大概有两级 BTB：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;96-entry nano BTB, 1 cycle latency (0 cycle bubble)&lt;/li&gt; &lt;li&gt;8K-entry main BTB&lt;/li&gt; &lt;li&gt;2 predicted branches per cycle&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;但是很多细节是缺失的，因此下面结合微架构测试，进一步研究它的内部结构。&lt;/p&gt; &lt;h2 id=&#34;微架构测试&#34;&gt;微架构测试&lt;a class=&#34;headerlink&#34; href=&#34;#微架构测试&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;在之前的博客里，我们已经测试了各种处理器的 BTB，在这里也是一样的：按照一定的 stride 分布无条件（uncond）或总是跳转的有条件（cond）直接分支，构成一个链条，然后测量 CPI。在先前的 &lt;a href=&#34;../../05/arm-neoverse-n1-btb/&#34;&gt;Neoverse N1 测试&lt;/a&gt; 里，我们只测试了无条件分支，但实际上，在 Neoverse N1 上用条件分支测出来的结果也是一样的，但在 Neoverse V1 上就不同了，所以在这里要分开讨论。&lt;/p&gt; &lt;h3 id=&#34;stride4b-uncond&#34;&gt;stride=4B uncond&lt;a class=&#34;headerlink&#34; href=&#34;#stride4b-uncond&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;首先是 stride=4B uncond 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-v1-btb-4b-uncond.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了如下比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到接近 64 条分支，CPI=1，对应了 96-entry 的 nano BTB，但是没有体现出完整的 96 的容量&lt;/li&gt; &lt;li&gt;第二个台阶到 16384 条分支，CPI 在 5 到 6 之间，大于 main BTB 的 2 cycle latency，说明此时没有命中 main BTB，而是要等到取指和译码后，计算出正确的目的地址再回滚，导致了 5+ cycle latency；16384 对应 64KB L1 ICache 容量&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;那么 stride=4B uncond 的情况下就遗留了如下问题：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;nano BTB 没表现出 96 的容量，只表现出接近 64 的容量&lt;/li&gt; &lt;li&gt;没有观察到 2 predicted branches per cycle&lt;/li&gt; &lt;li&gt;没有命中 main BTB&lt;/li&gt; &lt;/ol&gt; &lt;h3 id=&#34;stride4b-cond&#34;&gt;stride=4B cond&lt;a class=&#34;headerlink&#34; href=&#34;#stride4b-cond&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;stride=4B cond 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-v1-btb-4b-cond.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了如下比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 48 条分支，CPI=1，对应了 96-entry 的 nano BTB，但是没有体现出完整的 96 的容量&lt;/li&gt; &lt;li&gt;之后没有明显的分界点，性能波动剧烈，没有观察到 main BTB 的台阶&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;nano BTB 只表现出 48 的容量，刚好是 96 的一半；同时没有观察到 2 predicted branches per cycle。考虑这两点，可以认为 nano BTB 的组织方式和分支类型有关，当分支过于密集（stride=4B）或者用条件分支（cond）时，不能得到完整的 96-entry 的大小，此时也会回落到 CPI=1 的情况。&lt;/p&gt; &lt;p&gt;那么 stride=4B cond 的情况下就遗留了如下问题：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;没有命中 main BTB&lt;/li&gt; &lt;/ol&gt; &lt;h3 id=&#34;stride8b-uncond&#34;&gt;stride=8B uncond&lt;a class=&#34;headerlink&#34; href=&#34;#stride8b-uncond&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;stride=8B uncond 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-v1-btb-8b-uncond.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了如下比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 96 条分支，CPI=0.5，对应了 96-entry 的 nano BTB，体现了 2 predicted branches per cycle&lt;/li&gt; &lt;li&gt;第二个台阶到 8192 条分支，CPI=1，对应 main BTB，此时也对应了 64KB L1 ICache；此外，从 4096 开始有略微的上升&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;此时 nano BTB 完整地表现出了它的 96-entry 容量，并且实现了 CPI=0.5 的效果。main BTB 也实现了 CPI=1，考虑到它的容量不太可能单周期给出一个分支的结果，大概率是两个周期预测两条分支指令。&lt;/p&gt; &lt;p&gt;那么 stride=8B uncond 的情况下就遗留了如下问题：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;从 4096 条分支开始性能有略微的下降&lt;/li&gt; &lt;/ol&gt; &lt;h3 id=&#34;stride8b-cond&#34;&gt;stride=8B cond&lt;a class=&#34;headerlink&#34; href=&#34;#stride8b-cond&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;stride=8B cond 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-v1-btb-8b-cond.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了如下比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 48 条分支，CPI=1，对应了 96-entry 的 nano BTB，没有 2 predicted branches per cycle，容量也只有 96 的一半&lt;/li&gt; &lt;li&gt;第二个台阶到 8192 条分支，CPI=2，对应 main BTB，此时也对应了 64KB L1 ICache&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;和之前一样，遇到 cond 分支，nano BTB 的容量只有一半，也观察不到 2 predicted branches per cycle。另一边，main BTB 的 CPI 也到了 2，意味着此时 main BTB 也只能两个周期预测一条分支指令，和之前的分析吻合。&lt;/p&gt; &lt;p&gt;那么为什么用条件分支，就不能预测两条分支指令了呢？猜测是，BTB 可以一次给出两条分支的信息，但是没有时间去同时预测这两条分支的方向。所以就回落到了普通的 2 cycle BTB 情况。&lt;/p&gt; &lt;h3 id=&#34;stride16b-uncond&#34;&gt;stride=16B uncond&lt;a class=&#34;headerlink&#34; href=&#34;#stride16b-uncond&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;stride=16B uncond 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-v1-btb-16b-uncond.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了如下比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 96 条分支，CPI=0.5，对应了 96-entry 的 nano BTB，体现了 2 predicted branches per cycle&lt;/li&gt; &lt;li&gt;第二个台阶到 2048 条分支，CPI=1；略微上升到 4096，此时是 64KB L1 ICache 的容量；到 8192 出现明显突变，对应 main BTB 容量&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;那么 stride=16B uncond 的情况下就遗留了如下问题：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;从 2048 条分支开始性能有略微的下降&lt;/li&gt; &lt;/ol&gt; &lt;h3 id=&#34;stride16b-cond&#34;&gt;stride=16B cond&lt;a class=&#34;headerlink&#34; href=&#34;#stride16b-cond&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;stride=16B cond 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-v1-btb-16b-cond.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了如下比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 48 条分支，CPI=1，对应了 96-entry 的 nano BTB，没有 2 predicted branches per cycle，容量也只有 96 的一半&lt;/li&gt; &lt;li&gt;第二个台阶到 8192 条分支，CPI=2，对应 main BTB&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;预测的效果和 stride=8B cond 完全相同。&lt;/p&gt; &lt;p&gt;那么 stride=16B cond 的情况下就遗留了如下问题：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;64KB ICache 应该在 4096 条分支导致瓶颈，但是实际没有观察到&lt;/li&gt; &lt;/ol&gt; &lt;h3 id=&#34;stride32b-uncond&#34;&gt;stride=32B uncond&lt;a class=&#34;headerlink&#34; href=&#34;#stride32b-uncond&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;stride=32B uncond 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-v1-btb-32b-uncond.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了如下比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 96 条分支，CPI=0.5，对应了 96-entry 的 nano BTB，体现了 2 predicted branches per cycle&lt;/li&gt; &lt;li&gt;第二个台阶到 1024 条分支，CPI=1；略微上升到 2048，此时是 64KB L1 ICache 的容量；到 8192 右侧出现明显突变&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;那么 stride=32B uncond 的情况下就遗留了如下问题：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;从 1024 条分支开始性能有略微的下降&lt;/li&gt; &lt;li&gt;性能明显下降的点在 8192 右侧，而不是 8192&lt;/li&gt; &lt;/ol&gt; &lt;h3 id=&#34;stride32b-cond&#34;&gt;stride=32B cond&lt;a class=&#34;headerlink&#34; href=&#34;#stride32b-cond&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;stride=32B cond 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-v1-btb-32b-cond.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了如下比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 48 条分支，CPI=1，对应了 96-entry 的 nano BTB，没有 2 predicted branches per cycle，容量也只有 96 的一半&lt;/li&gt; &lt;li&gt;第二个台阶到 2048 条分支，CPI=2，对应 64KB L1 ICache 容量，之后缓慢上升，到 8192 出现性能突变，对应 main BTB 容量&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;基本符合预期，只是在 stride=16B cond 的基础上，引入了 64KB L1 ICache 导致的性能下降。&lt;/p&gt; &lt;h3 id=&#34;stride64b-uncond&#34;&gt;stride=64B uncond&lt;a class=&#34;headerlink&#34; href=&#34;#stride64b-uncond&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;stride=64B uncond 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-v1-btb-64b-uncond.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了如下比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 96 条分支，CPI=0.5，对应了 96-entry 的 nano BTB，体现了 2 predicted branches per cycle&lt;/li&gt; &lt;li&gt;第二个台阶到 1024 条分支，CPI=1，对应 64KB L1 ICache 的容量&lt;/li&gt; &lt;li&gt;第三个台阶到 4096，CPI=3，对应 main BTB 的容量；main BTB 容量减半，意味着 main BTB 应当是个组相连结构&lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;stride64b-cond&#34;&gt;stride=64B cond&lt;a class=&#34;headerlink&#34; href=&#34;#stride64b-cond&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;stride=64B cond 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-v1-btb-64b-cond.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了如下比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 48 条分支，CPI=1，对应了 96-entry 的 nano BTB，没有 2 predicted branches per cycle，容量也只有 96 的一半&lt;/li&gt; &lt;li&gt;第二个台阶到 1024 条分支，CPI=2，对应 64KB L1 ICache 容量，之后缓慢上升，到 4096 出现性能突变，对应 main BTB 容量；main BTB 容量只有 8192 的一半，意味着它是组相连结构&lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;小结&#34;&gt;小结&lt;a class=&#34;headerlink&#34; href=&#34;#小结&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;测试到这里就差不多了，更大的 stride 得到的也是类似的结果，总结一下前面的发现：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;nano BTB 是 96-entry，1 cycle latency，对于 uncond 分支可以做到一次预测两条分支，大小不随着 stride 变化，对应全相连结构&lt;/li&gt; &lt;li&gt;main BTB 是 8K-entry，2 cycle latency，对于 uncond 分支可以做到一次预测两条分支，此时可以达到 CPI=1；容量随着 stride 变化，对应组相连结构&lt;/li&gt; &lt;li&gt;64KB ICache 很多时候会比 main BTB 更早成为瓶颈&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;也总结一下前面发现了各种没有解释的遗留问题：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;cond 分支情况下，没有 2 predicted branches per cycle，此时两级 BTB 分别可以做到 CPI=1 和 CPI=2，同时 nano BTB 容量减半到 48：解释见后&lt;/li&gt; &lt;li&gt;stride=4B uncond/cond 的情况下，main BTB 没有像预期那样工作：解释见后&lt;/li&gt; &lt;li&gt;stride=8B/16B/32B uncond 的情况下，4096/2048/1024 条分支处出现了性能下降：暂无解释&lt;/li&gt; &lt;li&gt;stride=32B uncond 的情况下，main BTB 导致的拐点应该在 8192，但实际上在 8192 右侧：暂无解释&lt;/li&gt; &lt;li&gt;stride=16B cond 的情况下，64KB ICache 应该在 4096 条分支导致瓶颈，但是实际没有观察到：暂无解释&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;接下来尝试解析一下这些遗留问题背后的原理。部分遗留问题，并没有被解释出来，欢迎读者提出猜想。&lt;/p&gt; &lt;h2 id=&#34;解析遗留问题&#34;&gt;解析遗留问题&lt;a class=&#34;headerlink&#34; href=&#34;#解析遗留问题&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;cond-分支情况下没有-2-predicted-branches-per-cycle同时-nano-btb-只有-48-的容量&#34;&gt;cond 分支情况下，没有 2 predicted branches per cycle，同时 nano BTB 只有 48 的容量&lt;a class=&#34;headerlink&#34; href=&#34;#cond-分支情况下没有-2-predicted-branches-per-cycle同时-nano-btb-只有-48-的容量&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;比较相同 stride 下，cond 和 uncond 的情况，可以看到，cond 情况下两级 BTB 的 CPI 都翻倍，这意味着，当遇到全是 cond 分支时，大概是因为条件分支预测器的带宽问题，不能一次性预测两个 cond 分支的方向，而只能预测第一条 cond 分支，那么第二条 cond 分支的信息，即使通过 BTB 读取出来，也不能立即使用，还得等下一次的预测。&lt;/p&gt; &lt;p&gt;为了验证这个猜想，额外做了一组实验：把分支按照 cond, uncond, cond, uncond, ... 的顺序排列，也就是每个 cond 分支的目的地址有一条 uncond 分支。此时测出来的结果，和 uncond 相同，也就是可以做到 2 predicted branches per cycle。此时，BTB 依然一次提供了两条分支的信息，只不过条件分支预测器只预测了第一个 cond 的方向。如果它预测为不跳转，那么下一个 PC 就是 cond 分支的下一条指令；如果它预测为跳转，那么下一个 PC 就是 uncond 分支的目的地址。&lt;/p&gt; &lt;p&gt;nano BTB 的容量减半，意味着 nano BTB 的 96 的容量，实际上是 48 个 entry，每个 entry 最多记录两条分支。考虑到 nano BTB 的容量不随 stride 变化，大概率是全相连，并且是根据第一条分支的地址进行全相连匹配，这样，在 cond + cond 这种情况下，就只能表现出 48 的容量。但是 stride=4B uncond 的情况下表现出介于 48 和 64 之间的容量，还不知道是什么原因。&lt;/p&gt; &lt;p&gt;main BTB 的容量不变，意味着它在 cond + cond 的情况下，会退化为普通的 BTB，此时所有容量都可以用来保存 cond 分支，并且都能匹配到。&lt;/p&gt; &lt;p&gt;那么，具体是怎么做到 2 predicted branches per cycle 呢？猜测在执行的时候，检测这种一个分支的目的地址后，跟着一条 uncond 分支的情况：如果有的话，就把第二条分支的信息，放在第一条分支的信息后面（这在 &lt;a href=&#34;https://dl.acm.org/doi/pdf/10.1145/3613424.3623774&#34;&gt;Branch Target Buffer Organizations&lt;/a&gt; 中被称为 MB-BTB 结构），单个周期直接从 SRAM 读取出来，然后组成两个 fetch bundle：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;prediction pc -- first branch pc&lt;/li&gt; &lt;li&gt;first branch target -- second branch pc&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;然后下一个周期从 second branch target 开始继续预测。根据官方信息，Neoverse V1 的 L1 ICache 支持 2x32B 的带宽，这个 2x 代表了可以从两个不同的地方读取指令，也就是 L1 ICache 至少是双 bank 甚至双端口的 SRAM。考虑到前面的测试中，CPI=0.5 的范围跨越了各种 stride，认为 L1 ICache 是双 bank 的可能写比较小，不然应该会观测到 bank conflict，大概率就是双端口了。&lt;/p&gt; &lt;p&gt;此外，考虑到 fetch bundle 的长度限制，first branch target 到 second branch pc 不能太远。在上面的测试中，这个距离总是 0；读者如果感兴趣，可以尝试把距离拉长，看看超过 32B 以后，是不是会让 2 predicted branches per cycle 失效。类似的表述，在 &lt;a href=&#34;https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/software-optimization-guides/57647.zip&#34;&gt;AMD Zen 4 Software Optimization Guide&lt;/a&gt; 中也有出现：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-0-1&#34;&gt;&lt;a id=&#34;__codelineno-0-1&#34; name=&#34;__codelineno-0-1&#34; href=&#34;#__codelineno-0-1&#34;&gt;&lt;/a&gt;The branch target buffer (BTB) is a two-level structure accessed using the fetch address of the previous fetch block. &lt;/span&gt;&lt;span id=&#34;__span-0-2&#34;&gt;&lt;a id=&#34;__codelineno-0-2&#34; name=&#34;__codelineno-0-2&#34; href=&#34;#__codelineno-0-2&#34;&gt;&lt;/a&gt;Each BTB entry includes information for branches and their targets. &lt;/span&gt;&lt;span id=&#34;__span-0-3&#34;&gt;&lt;a id=&#34;__codelineno-0-3&#34; name=&#34;__codelineno-0-3&#34; href=&#34;#__codelineno-0-3&#34;&gt;&lt;/a&gt;Each BTB entry can hold up to two branches, and two pair cases are supported: &lt;/span&gt;&lt;span id=&#34;__span-0-4&#34;&gt;&lt;a id=&#34;__codelineno-0-4&#34; name=&#34;__codelineno-0-4&#34; href=&#34;#__codelineno-0-4&#34;&gt;&lt;/a&gt;• A conditional branch followed by another branch with both branches having their last byte in the same 64 byte aligned cacheline. &lt;/span&gt;&lt;span id=&#34;__span-0-5&#34;&gt;&lt;a id=&#34;__codelineno-0-5&#34; name=&#34;__codelineno-0-5&#34; href=&#34;#__codelineno-0-5&#34;&gt;&lt;/a&gt;• A direct branch (excluding CALLs) followed by a branch ending within the 64 byte aligned cacheline containing the target of the first branch. &lt;/span&gt;&lt;span id=&#34;__span-0-6&#34;&gt;&lt;a id=&#34;__codelineno-0-6&#34; name=&#34;__codelineno-0-6&#34; href=&#34;#__codelineno-0-6&#34;&gt;&lt;/a&gt;Predicting with BTB pairs allows two fetches to be predicted in one prediction cycle. &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;上面的第二种情况，对应了第二条分支的 pc，在第一条分支的 target 的同一个 64 字节 cacheline 内的要求。可见，ARM 和 AMD 在 BTB 的设计上是趋同的。&lt;/p&gt; &lt;p&gt;小结，Neoverse V1 在满足如下条件时，可以做到 2 predicted branches per cycle：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;uncond + uncond&lt;/li&gt; &lt;li&gt;cond + uncond&lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;stride4b-uncondcond-的情况下main-btb-没有像预期那样工作&#34;&gt;stride=4B uncond/cond 的情况下，main BTB 没有像预期那样工作&lt;a class=&#34;headerlink&#34; href=&#34;#stride4b-uncondcond-的情况下main-btb-没有像预期那样工作&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;类似的情况，我们在分析 &lt;a href=&#34;../../05/arm-neoverse-n1-btb/&#34;&gt;Neoverse N1&lt;/a&gt; 的时候就遇到了。Neoverse N1 的情况是，每对齐的 32B 块内，由于 6 路组相连，最多记录 6 条分支，而 stride=4B 时，有 8 条分支，所以出现了性能问题。&lt;/p&gt; &lt;p&gt;那么 Neoverse V1 是不是还是类似的情况呢？查阅 &lt;a href=&#34;https://developer.arm.com/documentation/101427/latest/&#34;&gt;Neoverse V1 TRM&lt;/a&gt;，可以看到它的 L1 (main) BTB 的描述是：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Index: [15:4]&lt;/li&gt; &lt;li&gt;Data: [91:0]&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;回想之前 Neoverse N1 的 main BTB 容量：Index 是 [14:5]，意味着有 1024 个 set；3 个 Way，每个 Way 里面是 82 bit 的数据，每个分支占用 41 bit，所以一共可以存 &lt;code&gt;1024*3*2=6K&lt;/code&gt; 条分支。&lt;/p&gt; &lt;p&gt;类比一下，Neoverse V1 的 main BTB 容量也就可以计算得出：Index 是 [15:4]，意味着有 4096 个 set；没有 Way，说明就是直接映射；92 bit 的数据，大概率也是每个分支占用一半也就是 46 bit，所以一共可以存 &lt;code&gt;4096*2=8K&lt;/code&gt; 条分支，和官方数据吻合。在需要 2 predicted branches 的时候，就把这两个分支放到同一个 92-bit entry 内即可。一共占用 &lt;code&gt;4096*92=376832&lt;/code&gt; bit 也就是 46 KB 的空间。&lt;/p&gt; &lt;p&gt;那么，在 stride=4B 的情况下，对齐的 16B 块内的分支会被放到同一个 set 内，而每个 set 只能放两条分支，而 stride=4B 时需要放四条分支，这就导致了 main BTB 出现性能问题。&lt;/p&gt; &lt;p&gt;但比较奇怪的是，main BTB 的容量，在 stride=32B 时是 8192，而 stride=64B 时是 4096，这和 Index 是 PC[15:4] 不符，这成为了新的遗留问题。有一种可能，就是 TRM 写的不准确，Index 并非 PC[15:4]。另外还有一个佐证：Neoverse N2 的 BTB 设计和 Neoverse V1 基本相同，但是它的 TRM 写的 Index 就是 [11:0]，这就肯定不是 PC[11:0] 了。&lt;/p&gt; &lt;p&gt;抛开 TRM，根据 JamesAslan 在 &lt;a href=&#34;https://zhuanlan.zhihu.com/p/595585895&#34;&gt;偷懒的 BTB？ARM Cortex X1 初探&lt;/a&gt; 中的测试，Main BTB 是四路组相连。如果按照四路组相连来考虑，那么 8K 条分支，实际上应该是 2048 个 set，2 个 way，一共是 4K 个 entry，每个 entry 最多保存两条分支。此时 Index 应该有 11 个 bit。在 2 way 每 way 两条分支等效为 4 way 的情况下，stride=4B 出现分支数比 way 数量更多的情况，stride=8B 则不会，意味着参与到 Index 的最低的 PC 应该是 PC[5]，即每个对齐的 32B 块内，最多放四条分支（Neoverse N1 上是每个对齐的 32B 块内最多放六条分支）。这样的话，Index 可能实际上是 PC[15:5]。&lt;/p&gt; &lt;h2 id=&#34;总结&#34;&gt;总结&lt;a class=&#34;headerlink&#34; href=&#34;#总结&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;最后总结一下 Neoverse V1 的 BTB：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;48-entry(96 branches) nano BTB, at most 2 branches per entry, 1 cycle latency, at most 2 predicted branches every 1 cycle, fully associative&lt;/li&gt; &lt;li&gt;4K-entry(8K branches) main BTB, at most 2 branches per entry, 2 cycle latency, at most 2 predicted branches every 2 cycles, 2-way(4-branch-way) set-associative, index PC[15:5]&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;当 uncond + uncond 或者 cond + uncond 时，可以实现每次预测两条分支；对于 cond + cond，每次只能预测一条分支。&lt;/p&gt; &lt;p&gt;2 predicted branches per cycle 通常也被称为 2 taken branches per cycle，简称 2 taken。&lt;/p&gt; &lt;h2 id=&#34;附录&#34;&gt;附录&lt;a class=&#34;headerlink&#34; href=&#34;#附录&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;neoverse-n2代号-perseus的-btb-结构分析&#34;&gt;Neoverse N2（代号 Perseus）的 BTB 结构分析&lt;a class=&#34;headerlink&#34; href=&#34;#neoverse-n2代号-perseus的-btb-结构分析&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;根据官方信息，Neoverse N2 和 Neoverse V1 的 BTB 配置十分类似，从数字来看只有 nano BTB 缩小到了 32-entry(64 branches)，其余是相同的，例如 main BTB 容量也是 8K branches。实测下来，BTB 测试图像和 Neoverse V1 基本一样，只有 nano BTB 容量的区别。因此本文也可以认为是对 Neoverse N2 的 BTB 结构分析。考虑到 Neoverse N2 和 Neoverse V1 的发布时间相同，可以认为它们用的就是相同的前端设计，只是改了一下参数。&lt;/p&gt; &lt;p&gt;至于为啥 Neoverse N2 比 Neoverse V1 出的更晚但 nano BTB 还更小，可能是因为它是 N 系列而不是 V 系列，基于 Cortex-A710，所以容量上做了一些取舍。&lt;/p&gt; &lt;h3 id=&#34;各代-neoverse-处理器的-btb-结构对比&#34;&gt;各代 Neoverse 处理器的 BTB 结构对比&lt;a class=&#34;headerlink&#34; href=&#34;#各代-neoverse-处理器的-btb-结构对比&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;比较一下 Neoverse V1 和 Neoverse N1 的设计：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Neoverse N1 设计了三级 BTB（16+64+6K），分别对应 1-3 的周期的延迟，特别地，main BTB 设计了 fastpath 来实现一定情况下的 2 周期延迟&lt;/li&gt; &lt;li&gt;Neoverse V1 设计了两级 BTB（96+8K），分别对应 1-2 的周期的延迟，并且都支持 2 taken&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Neoverse V1 相比 Neoverse N1，在容量和延迟上都有比较明显的提升，还额外给两级 BTB 都引入了 2 taken 的支持，进一步提升了吞吐。&lt;/p&gt; &lt;p&gt;Neoverse N1 是基于 Cortex A76 设计的，Neoverse V1 是基于 Cortex X1 设计的，中间还隔了一代 Cortex A77，根据&lt;a href=&#34;https://www.smartprix.com/bytes/cortex-a77-vs-cortex-a76-cores/&#34;&gt;官方信息&lt;/a&gt;，它的 1-cycle latency L1 BTB（即 Nano BTB）容量从 Cortex A76 的 16 变成了 64，main BTB 从 6K 扩到了 8K，而没有提 Micro BTB。同时也没有提到 two taken 的事情。由此推断，Cortex A77 扩大了 Nano BTB 和 Main BTB 的容量，去掉了 Micro BTB，因为 Nano BTB 的容量已经和原来 Neoverse N1 的 Micro BTB 一样大了，其他应该没有变化。再结合 &lt;a href=&#34;https://developer.arm.com/documentation/101111/0101&#34;&gt;Arm® Cortex®‑A77 Core Technical Reference Manual&lt;/a&gt; 可知它的 BTB index 是 &lt;code&gt;[15:4]&lt;/code&gt;，每个 entry 是 82 bits，位宽和 Neoverse N1 一致，所以应该只是扩了容量。&lt;/p&gt; &lt;p&gt;再往前找 Cortex A73 和 Cortex A75，根据 &lt;a href=&#34;https://chipsandcheese.com/p/arms-cortex-a73-resource-limits-what-are-those&#34;&gt;Chips and Cheese&lt;/a&gt; 的实验数据，Cortex A73 有两级 BTB，第一级 BTB 是 48-entry 2-cycle latency（奇怪的是，&lt;a href=&#34;https://www.theregister.com/2016/06/01/arm_cortex_a73/&#34;&gt;官方信息&lt;/a&gt; 中声称是 64 entry Micro BTAC，容量对不上，但还是更加相信实验数据），第二级 BTB 是 3K-entry 3-cycle latency。根据 &lt;a href=&#34;https://chipsandcheese.com/p/inside-sifives-p550-microarchitecture&#34;&gt;Chips and Cheese&lt;/a&gt; 的实验数据，Cortex A75 有两级 BTB，第一级 BTB 是 32-entry 1-cycle latency，第二级 BTB 是 3K-entry 3-cycle latency。&lt;/p&gt; &lt;p&gt;下面是一个对比表格：&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;uArch&lt;/th&gt; &lt;th&gt;Cortex A73&lt;/th&gt; &lt;th&gt;Cortex A75&lt;/th&gt; &lt;th&gt;Neoverse N1&lt;/th&gt; &lt;th&gt;Cortex A77&lt;/th&gt; &lt;th&gt;Neoverse V1&lt;/th&gt; &lt;th&gt;Neoverse N2&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;Nano BTB size&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;td&gt;32 branches&lt;/td&gt; &lt;td&gt;16 branches&lt;/td&gt; &lt;td&gt;64 branches&lt;/td&gt; &lt;td&gt;48*2 branches&lt;/td&gt; &lt;td&gt;32*2 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Nano BTB latency&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;td&gt;1 cycle&lt;/td&gt; &lt;td&gt;1 cycle&lt;/td&gt; &lt;td&gt;1 cycle&lt;/td&gt; &lt;td&gt;1 cycle&lt;/td&gt; &lt;td&gt;1 cycle&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Nano BTB throughput&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;td&gt;1 branch&lt;/td&gt; &lt;td&gt;1 branch&lt;/td&gt; &lt;td&gt;1 branch&lt;/td&gt; &lt;td&gt;1-2 branches&lt;/td&gt; &lt;td&gt;1-2 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Micro BTB size&lt;/td&gt; &lt;td&gt;48 branches&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;td&gt;64 branches&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Micro BTB latency&lt;/td&gt; &lt;td&gt;2 cycles&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;td&gt;2 cycles&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Micro BTB throughput&lt;/td&gt; &lt;td&gt;1 branch&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;td&gt;1 branch&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;td&gt;N/A&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Main BTB size&lt;/td&gt; &lt;td&gt;3K branches&lt;/td&gt; &lt;td&gt;3K branches&lt;/td&gt; &lt;td&gt;3K*2 branches&lt;/td&gt; &lt;td&gt;4K*2 branches&lt;/td&gt; &lt;td&gt;4K*2 branches&lt;/td&gt; &lt;td&gt;4K*2 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Main BTB latency&lt;/td&gt; &lt;td&gt;3 cycles&lt;/td&gt; &lt;td&gt;3 cycles&lt;/td&gt; &lt;td&gt;2-3 cycles&lt;/td&gt; &lt;td&gt;2-3 cycles&lt;/td&gt; &lt;td&gt;2 cycle&lt;/td&gt; &lt;td&gt;2 cycle&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Main BTB throughput&lt;/td&gt; &lt;td&gt;1 branch&lt;/td&gt; &lt;td&gt;1 branch&lt;/td&gt; &lt;td&gt;1 branch&lt;/td&gt; &lt;td&gt;1 branch&lt;/td&gt; &lt;td&gt;1-2 branches&lt;/td&gt; &lt;td&gt;1-2 branches&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Main BTB area (bits)&lt;/td&gt; &lt;td&gt;?&lt;/td&gt; &lt;td&gt;?&lt;/td&gt; &lt;td&gt;3K*82=251904&lt;/td&gt; &lt;td&gt;4K*82=335872&lt;/td&gt; &lt;td&gt;4K*92=376832&lt;/td&gt; &lt;td&gt;4K*92=376832&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Main BTB area (KiB)&lt;/td&gt; &lt;td&gt;?&lt;/td&gt; &lt;td&gt;?&lt;/td&gt; &lt;td&gt;30.75&lt;/td&gt; &lt;td&gt;41&lt;/td&gt; &lt;td&gt;46&lt;/td&gt; &lt;td&gt;46&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Technology Node&lt;/td&gt; &lt;td&gt;10nm&lt;/td&gt; &lt;td&gt;10nm&lt;/td&gt; &lt;td&gt;7nm&lt;/td&gt; &lt;td&gt;7nm&lt;/td&gt; &lt;td&gt;5nm&lt;/td&gt; &lt;td&gt;5nm&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;由此可以看出 ARM 在 BTB 上的优化脉络：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Cortex A75 相比 Cortex A73：&lt;ul&gt; &lt;li&gt;降低第一级 BTB 的延迟，从 2 周期的 Micro BTB 变成 1 周期的 Nano BTB，从而降低无条件分支的延迟，代价是容量变小了一些&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;Neoverse N1 相比 Cortex A75：&lt;ul&gt; &lt;li&gt;把 Nano BTB 拆分成 Nano 和 Micro 两级，从而增加容量&lt;/li&gt; &lt;li&gt;通过引入 BTB 压缩优化（即一个 Entry 可以保存 1-2 条分支），使得 Main BTB 能容纳更多的分支&lt;/li&gt; &lt;li&gt;针对 Main BTB 引入 fast path，当只有一个 way 匹配时，只需要 2 周期即可提供预测&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;Cortex A77 相比 Neoverse N1：&lt;ul&gt; &lt;li&gt;通过扩大 Nano BTB，去掉了 Micro BTB，让更多分支可以享受 1 周期的延迟&lt;/li&gt; &lt;li&gt;继续扩大 Main BTB&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;Neoverse V1 相比 Cortex A77：&lt;ul&gt; &lt;li&gt;在 Nano 和 Main BTB 上引入 two taken 预测，增加吞吐&lt;/li&gt; &lt;li&gt;减少 Main BTB 延迟，从 2-3 周期变成固定 2 周期&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;注：各代 Cortex 与 Neoverse 对应关系以及代号：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Cortex-A73(Artemis)&lt;/li&gt; &lt;li&gt;Cortex-A75(Prometheus)&lt;/li&gt; &lt;li&gt;Cortex-A76(Enyo)/Neoverse-N1(Ares)&lt;/li&gt; &lt;li&gt;Cortex-A77(Deimos)&lt;/li&gt; &lt;li&gt;Cortex-A78(Hercules)/Cortex-X1(Hera)/Neoverse-V1(Zeus, based on Cortex-X1)&lt;/li&gt; &lt;li&gt;Cortex-A710(Matterhorn)/Cortex-X2(Matterhorn ELP)/Neoverse-N2(Perseus, based on Cortex-A710)&lt;/li&gt; &lt;/ul&gt;</description> <link>https://jia.je/hardware/2025/06/23/arm-neoverse-v1-btb/</link> <pubDate>Mon, 23 Jun 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2025/06/23/arm-neoverse-v1-btb/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2025/06/23/arm-neoverse-v1-btb.png" type="image/png" length="60696" /> </item> <item> <title>在鸿蒙电脑上的虚拟机内启动 Linux</title> <category>arm64</category> <category>hardware</category> <category>harmonyos</category> <category>huawei</category> <category>linux</category> <category>matebook</category> <category>matebookpro</category> <description>&lt;h1 id=&#34;在鸿蒙电脑上的虚拟机内启动-linux&#34;&gt;在鸿蒙电脑上的虚拟机内启动 Linux&lt;a class=&#34;headerlink&#34; href=&#34;#在鸿蒙电脑上的虚拟机内启动-linux&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;最近在研究鸿蒙电脑，群友 &lt;a href=&#34;https://github.com/Fearyncess&#34;&gt;@Fearyncess&lt;/a&gt; 摸索出了，如何在鸿蒙电脑上的虚拟机内启动 Linux，而不是 Windows。在此做个复现并记录。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;方法&#34;&gt;方法&lt;a class=&#34;headerlink&#34; href=&#34;#方法&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;目前鸿蒙的应用市场上有两家虚拟机，我用 Oseasy 虚拟机，但是理论上铠大师也是可以的。（P.S. @driver1998 反馈：“铠大师测试也能启动，但键盘左右方向键的处理有点问题，虚拟机内收不到按键松开的信号，EFI 和 Linux 里 面都是这样。目前建议用 OSEasy。”）&lt;/p&gt; &lt;p&gt;首先需要在 U 盘上，把一个 UEFI arm64 的 Linux 安装盘写进去。我用的是 Ventoy + Debian Installer，理论上直接写例如 Debian 发行版的安装 ISO 也是可以的。&lt;/p&gt; &lt;p&gt;然后把 U 盘插到鸿蒙电脑上，打开 Windows 虚拟机，直通到虚拟机里面，保证虚拟机里面可以看到 U 盘。&lt;/p&gt; &lt;p&gt;接着，进入 Windows 磁盘管理，缩小 Windows 的 NTFS 分区，留出空间。注意 Windows 启动的时候会自动 growpart，所以装 Debian 前，不要回到 Windows。装好以后，可以继续用 Windows。&lt;/p&gt; &lt;p&gt;接着，重启 Windows，同时按住 Escape，进入 OVMF 的界面，然后选择 Boot Manager，从 U 盘启动，然后就进入 Ventoy 的界面了。（注：根据 @quiccat 群友提醒，在 Windows 内，通过设置-&amp;gt;系统-&amp;gt;恢复-&amp;gt;高级启动-&amp;gt;UEFI 固件设置也可以进入 OVMF 的设置界面）&lt;/p&gt; &lt;p&gt;剩下的就是正常的 Linux 安装过程了，分区的时候，注意保留 Windows 已有的 NTFS，可以和 Windows 用同一个 ESP 分区。网络的话，配置静态 IP 是 172.16.100.2，默认网关是 172.16.100.1 即可。重启以后，在 grub 界面，修改 linux 配置，在 cmdline 一栏添加 &lt;code&gt;modprobe.blacklist=vmwgfx&lt;/code&gt;，这样就能启动了。内核版本是 Debian Bookworm 的 6.1。&lt;/p&gt; &lt;p&gt;各内核版本启动情况：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;5.10 from debian：正常&lt;/li&gt; &lt;li&gt;6.1 from debian：正常&lt;/li&gt; &lt;li&gt;6.2/6.3/6.4 from kernel.ubuntu.com: &lt;code&gt;echo simpledrm &amp;gt; /etc/modules-load.d/simpledrm.conf&lt;/code&gt; 后正常，否则系统可以启动但是图形界面起不来&lt;/li&gt; &lt;li&gt;6.5 from kernel.ubuntu.com：起不来，需要强制关机&lt;/li&gt; &lt;li&gt;6.12 from debian：起不来，需要强制关机&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;经过 @Fearyncess 的二分，找到了导致问题的 &lt;a href=&#34;https://github.com/torvalds/linux/commit/edc25898f0b6cceed6c90b0e79916bd04de7dd19&#34;&gt;commit&lt;/a&gt;。&lt;/p&gt; &lt;p&gt;最终效果：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../../software/linux-vm-on-harmonyos-computer.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;主要的遗憾是分辨率：屏幕两侧有黑边，并且由于宽度不同，触摸屏的位置映射会偏中间。&lt;/p&gt; &lt;h2 id=&#34;附录&#34;&gt;附录&lt;a class=&#34;headerlink&#34; href=&#34;#附录&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;Geekbench 6 测试结果：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;6 核：&lt;a href=&#34;https://browser.geekbench.com/v6/cpu/12309313&#34;&gt;Windows Single-Core 1436, Multi-Core 5296&lt;/a&gt;, &lt;a href=&#34;https://browser.geekbench.com/v6/cpu/12373700&#34;&gt;Linux Single-Core 1500, Multi-Core 5699&lt;/a&gt;&lt;/li&gt; &lt;li&gt;8 核：&lt;a href=&#34;https://browser.geekbench.com/v6/cpu/12309427&#34;&gt;Windows Single-Core 1462, Multi-Core 7043&lt;/a&gt;, &lt;a href=&#34;https://browser.geekbench.com/v6/cpu/12373488&#34;&gt;Linux Single-Core 1489, Multi-Core 6076&lt;/a&gt;, &lt;a href=&#34;https://browser.geekbench.com/v6/cpu/12373797&#34;&gt;Linux Single-Core 1503, Multi-Core 6289&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;如果没有 blacklist 的话，vmwgfx 驱动的报错：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-0-1&#34;&gt;&lt;a id=&#34;__codelineno-0-1&#34; name=&#34;__codelineno-0-1&#34; href=&#34;#__codelineno-0-1&#34;&gt;&lt;/a&gt;vmwgfx 0000:00:04.0: [drm] FIFO at 0x0000000020000000 size is 2048 kiB &lt;/span&gt;&lt;span id=&#34;__span-0-2&#34;&gt;&lt;a id=&#34;__codelineno-0-2&#34; name=&#34;__codelineno-0-2&#34; href=&#34;#__codelineno-0-2&#34;&gt;&lt;/a&gt;vmwgfx 0000:00:04.0: [drm] VRAM at 0x0000000010000000 size is 262144 kiB &lt;/span&gt;&lt;span id=&#34;__span-0-3&#34;&gt;&lt;a id=&#34;__codelineno-0-3&#34; name=&#34;__codelineno-0-3&#34; href=&#34;#__codelineno-0-3&#34;&gt;&lt;/a&gt;vmwgfx 0000:00:04.0: [drm] *ERROR* Unsupported SVGA ID 0xffffffff on chipset 0x405 &lt;/span&gt;&lt;span id=&#34;__span-0-4&#34;&gt;&lt;a id=&#34;__codelineno-0-4&#34; name=&#34;__codelineno-0-4&#34; href=&#34;#__codelineno-0-4&#34;&gt;&lt;/a&gt;vmwgfx: probe of 0000:00:04.0 failed with error -38 &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;blacklist vmwgfx 后用的是 efifb：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-1-1&#34;&gt;&lt;a id=&#34;__codelineno-1-1&#34; name=&#34;__codelineno-1-1&#34; href=&#34;#__codelineno-1-1&#34;&gt;&lt;/a&gt;[ 0.465898] pci 0000:00:04.0: BAR 1: assigned to efifb &lt;/span&gt;&lt;span id=&#34;__span-1-2&#34;&gt;&lt;a id=&#34;__codelineno-1-2&#34; name=&#34;__codelineno-1-2&#34; href=&#34;#__codelineno-1-2&#34;&gt;&lt;/a&gt;[ 1.197638] efifb: probing for efifb &lt;/span&gt;&lt;span id=&#34;__span-1-3&#34;&gt;&lt;a id=&#34;__codelineno-1-3&#34; name=&#34;__codelineno-1-3&#34; href=&#34;#__codelineno-1-3&#34;&gt;&lt;/a&gt;[ 1.197705] efifb: framebuffer at 0x10000000, using 7500k, total 7500k &lt;/span&gt;&lt;span id=&#34;__span-1-4&#34;&gt;&lt;a id=&#34;__codelineno-1-4&#34; name=&#34;__codelineno-1-4&#34; href=&#34;#__codelineno-1-4&#34;&gt;&lt;/a&gt;[ 1.197708] efifb: mode is 1600x1200x32, linelength=6400, pages=1 &lt;/span&gt;&lt;span id=&#34;__span-1-5&#34;&gt;&lt;a id=&#34;__codelineno-1-5&#34; name=&#34;__codelineno-1-5&#34; href=&#34;#__codelineno-1-5&#34;&gt;&lt;/a&gt;[ 1.197711] efifb: scrolling: redraw &lt;/span&gt;&lt;span id=&#34;__span-1-6&#34;&gt;&lt;a id=&#34;__codelineno-1-6&#34; name=&#34;__codelineno-1-6&#34; href=&#34;#__codelineno-1-6&#34;&gt;&lt;/a&gt;[ 1.197712] efifb: Truecolor: size=8:8:8:8, shift=24:16:8:0 &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;虚拟机的 IP 地址，从宿主机也可以直接访问，通过 WVMBr 访问，目测是直接 Tap 接出来，然后建了个 Bridge，外加 NAT，只是没有 DHCP。&lt;/p&gt;</description> <link>https://jia.je/hardware/2025/06/10/linux-vm-on-harmonyos-computer/</link> <pubDate>Tue, 10 Jun 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2025/06/10/linux-vm-on-harmonyos-computer/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2025/06/10/linux-vm-on-harmonyos-computer.png" type="image/png" length="50372" /> </item> <item> <title>终端模拟器的文字绘制</title> <category>arm64</category> <category>hardware</category> <category>harmonyos</category> <category>huawei</category> <category>matebook</category> <category>matebookpro</category> <category>termony</category> <description>&lt;h1 id=&#34;终端模拟器的文字绘制&#34;&gt;终端模拟器的文字绘制&lt;a class=&#34;headerlink&#34; href=&#34;#终端模拟器的文字绘制&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;最近在造鸿蒙电脑上的终端模拟器 &lt;a href=&#34;https://github.com/jiegec/Termony&#34;&gt;Termony&lt;/a&gt;，一开始用 ArkTS 的 Text + Span 空间来绘制终端，后来发现这样性能和可定制性比较差，就选择了自己用 OpenGL 实现，顺带学习了一下终端模拟器的文字绘制是什么样的一个过程。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;读取字形&#34;&gt;读取字形&lt;a class=&#34;headerlink&#34; href=&#34;#读取字形&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;文本绘制，首先就要从字体文件中读取字形，提取出 Bitmap 来，然后把 Bitmap 绘制到该去的地方。为了提取这些信息，首先用 FreeType 库，它可以解析字体文件，然后计算出给定大小的给定字符的 Bitmap。但是，这个 Bitmap 它只记录字体非空白的部分（准确的说，是 Bounding Box），如下图的 width * height 部分：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../../software/terminal-emulator-text-rendering-font.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;（图源：&lt;a href=&#34;https://freetype.org/freetype2/docs/tutorial/step2.html&#34;&gt;Managing Glyphs - FreeType Tutorial II&lt;/a&gt;）&lt;/p&gt; &lt;p&gt;其中 x 轴，应该是同一行的字体对齐的，这样才会看到有高有低的字符出现在同一行，而不是全部上对齐或者下对齐。得到的 Bitmap 是行优先的，也就是说：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;图中左上角，坐标 (xMin, yMax) 对应 Bitmap 数组的下标是 &lt;code&gt;0&lt;/code&gt;&lt;/li&gt; &lt;li&gt;图中右上角，坐标 (xMax, yMax) 对应 Bitmap 数组的下标是 &lt;code&gt;width-1&lt;/code&gt;&lt;/li&gt; &lt;li&gt;图中左下角，坐标 (xMin, yMin) 对应 Bitmap 数组的下标是 &lt;code&gt;width*(height-1)&lt;/code&gt;&lt;/li&gt; &lt;li&gt;图中右下角，坐标 (xMax, yMax) 对应 Bitmap 数组的下标是 &lt;code&gt;width*(height-1)+width-1&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;得到这个 Bitmap 后，如果我们不用 OpenGL，而是直接生成 PNG，那就直接进行一次 copy 甚至 blend 就可以把文字绘制上去了。但是，我们要用 OpenGL 的 shader，就需要把 bitmap 放到 texture 里面。由于目前我们用的就是单色的字体，所以它对应只有一个 channel 的 texture。&lt;/p&gt; &lt;p&gt;OpenGL 的 texture，里面也是保存的 bitmap，但它的坐标系统的命名方式不太一样：它的水平向右方向是 U 轴，竖直向上方向是 V 轴，然后它的 bitmap 保存个数也是行优先，但是从 (0, 0) 坐标开始保存像素，然后 U 和 V 的范围都是 0 到 1。&lt;/p&gt; &lt;p&gt;所以，如果我们创建一个 width*height 的单通道 texture，直接把上面的 bitmap 拷贝到 texture 内部，实际的效果大概是：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-0-1&#34;&gt;&lt;a id=&#34;__codelineno-0-1&#34; name=&#34;__codelineno-0-1&#34; href=&#34;#__codelineno-0-1&#34;&gt;&lt;/a&gt; V &lt;/span&gt;&lt;span id=&#34;__span-0-2&#34;&gt;&lt;a id=&#34;__codelineno-0-2&#34; name=&#34;__codelineno-0-2&#34; href=&#34;#__codelineno-0-2&#34;&gt;&lt;/a&gt; ^ &lt;/span&gt;&lt;span id=&#34;__span-0-3&#34;&gt;&lt;a id=&#34;__codelineno-0-3&#34; name=&#34;__codelineno-0-3&#34; href=&#34;#__codelineno-0-3&#34;&gt;&lt;/a&gt; | &lt;/span&gt;&lt;span id=&#34;__span-0-4&#34;&gt;&lt;a id=&#34;__codelineno-0-4&#34; name=&#34;__codelineno-0-4&#34; href=&#34;#__codelineno-0-4&#34;&gt;&lt;/a&gt; C D &lt;/span&gt;&lt;span id=&#34;__span-0-5&#34;&gt;&lt;a id=&#34;__codelineno-0-5&#34; name=&#34;__codelineno-0-5&#34; href=&#34;#__codelineno-0-5&#34;&gt;&lt;/a&gt; | &lt;/span&gt;&lt;span id=&#34;__span-0-6&#34;&gt;&lt;a id=&#34;__codelineno-0-6&#34; name=&#34;__codelineno-0-6&#34; href=&#34;#__codelineno-0-6&#34;&gt;&lt;/a&gt; | &lt;/span&gt;&lt;span id=&#34;__span-0-7&#34;&gt;&lt;a id=&#34;__codelineno-0-7&#34; name=&#34;__codelineno-0-7&#34; href=&#34;#__codelineno-0-7&#34;&gt;&lt;/a&gt; A------B---&amp;gt;U &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;上图中几个点的坐标以及对应的 bitmap 数组的下标：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;A 点：U = 0，V = 0，对应 bitmap 数组下标 &lt;code&gt;0&lt;/code&gt;&lt;/li&gt; &lt;li&gt;B 点：U = 1，V = 0，对应 bitmap 数组下标 &lt;code&gt;width-1&lt;/code&gt;&lt;/li&gt; &lt;li&gt;C 点：U = 0，V = 1，对应 bitmap 数组下标 &lt;code&gt;width*(height-1)&lt;/code&gt;&lt;/li&gt; &lt;li&gt;D 点：U = 1，V = 1，对应 bitmap 数组下标 &lt;code&gt;width*(height-1)+width-1&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;所以在向 OpenGL 的 texture 保存 bitmap 的时候，相当于做了一个上下翻转，不过这没有关系，后续在指定三角形顶点的 U V 坐标的时候，保证对应关系即可。&lt;/p&gt; &lt;h2 id=&#34;逐个字符绘制&#34;&gt;逐个字符绘制&lt;a class=&#34;headerlink&#34; href=&#34;#逐个字符绘制&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;有了这个基础以后，就可以实现逐个字符绘制：提前把所有要用到的字符，从字体提取出对应的 Bitmap，每个字符对应到一个 Texture。然后要绘制文字的时候，逐个字符，用对应的 Texture，在想要绘制的位置上，绘制一个字符。为了实现这个目的，写一个简单的 Shader：&lt;/p&gt; &lt;div class=&#34;language-c highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-1-1&#34;&gt;&lt;a id=&#34;__codelineno-1-1&#34; name=&#34;__codelineno-1-1&#34; href=&#34;#__codelineno-1-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// vertex shader&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-2&#34;&gt;&lt;a id=&#34;__codelineno-1-2&#34; name=&#34;__codelineno-1-2&#34; href=&#34;#__codelineno-1-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cp&#34;&gt;#version 320 es&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-3&#34;&gt;&lt;a id=&#34;__codelineno-1-3&#34; name=&#34;__codelineno-1-3&#34; href=&#34;#__codelineno-1-3&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-4&#34;&gt;&lt;a id=&#34;__codelineno-1-4&#34; name=&#34;__codelineno-1-4&#34; href=&#34;#__codelineno-1-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vertex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// xy is position, zw is its texture coordinates&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-5&#34;&gt;&lt;a id=&#34;__codelineno-1-5&#34; name=&#34;__codelineno-1-5&#34; href=&#34;#__codelineno-1-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;texCoors&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// output texture coordinates&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-6&#34;&gt;&lt;a id=&#34;__codelineno-1-6&#34; name=&#34;__codelineno-1-6&#34; href=&#34;#__codelineno-1-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-7&#34;&gt;&lt;a id=&#34;__codelineno-1-7&#34; name=&#34;__codelineno-1-7&#34; href=&#34;#__codelineno-1-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gl_Position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xy&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vertex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-8&#34;&gt;&lt;a id=&#34;__codelineno-1-8&#34; name=&#34;__codelineno-1-8&#34; href=&#34;#__codelineno-1-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gl_Position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// we don&amp;#39;t care about depth now&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-9&#34;&gt;&lt;a id=&#34;__codelineno-1-9&#34; name=&#34;__codelineno-1-9&#34; href=&#34;#__codelineno-1-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gl_Position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;w&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// (x, y, z, w) corresponds to (x/w, y/w, z/w), so we set w = 1.0&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-10&#34;&gt;&lt;a id=&#34;__codelineno-1-10&#34; name=&#34;__codelineno-1-10&#34; href=&#34;#__codelineno-1-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;texCoords&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vertex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;zw&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-11&#34;&gt;&lt;a id=&#34;__codelineno-1-11&#34; name=&#34;__codelineno-1-11&#34; href=&#34;#__codelineno-1-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-12&#34;&gt;&lt;a id=&#34;__codelineno-1-12&#34; name=&#34;__codelineno-1-12&#34; href=&#34;#__codelineno-1-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// fragment shader&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-13&#34;&gt;&lt;a id=&#34;__codelineno-1-13&#34; name=&#34;__codelineno-1-13&#34; href=&#34;#__codelineno-1-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cp&#34;&gt;#version 320 es&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-14&#34;&gt;&lt;a id=&#34;__codelineno-1-14&#34; name=&#34;__codelineno-1-14&#34; href=&#34;#__codelineno-1-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;precision&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lowp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-15&#34;&gt;&lt;a id=&#34;__codelineno-1-15&#34; name=&#34;__codelineno-1-15&#34; href=&#34;#__codelineno-1-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;texCoords&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-16&#34;&gt;&lt;a id=&#34;__codelineno-1-16&#34; name=&#34;__codelineno-1-16&#34; href=&#34;#__codelineno-1-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-17&#34;&gt;&lt;a id=&#34;__codelineno-1-17&#34; name=&#34;__codelineno-1-17&#34; href=&#34;#__codelineno-1-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;uniform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sampler2D&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-18&#34;&gt;&lt;a id=&#34;__codelineno-1-18&#34; name=&#34;__codelineno-1-18&#34; href=&#34;#__codelineno-1-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-19&#34;&gt;&lt;a id=&#34;__codelineno-1-19&#34; name=&#34;__codelineno-1-19&#34; href=&#34;#__codelineno-1-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;texture&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;texCoords&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-20&#34;&gt;&lt;a id=&#34;__codelineno-1-20&#34; name=&#34;__codelineno-1-20&#34; href=&#34;#__codelineno-1-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-21&#34;&gt;&lt;a id=&#34;__codelineno-1-21&#34; name=&#34;__codelineno-1-21&#34; href=&#34;#__codelineno-1-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;在这里，我们给每个顶点设置四个属性，包在一个 vec4 中：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;xy：记录了这个顶点的坐标，x 和 y 范围都是 -1 到 1&lt;/li&gt; &lt;li&gt;zw：记录了这个顶点的 texture 坐标 u 和 v，范围都是 0 到 1&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;vertex shader 只是简单地把这些信息传递到顶点的坐标和 fragment shader。fragment shader 做的事情是：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;根据当前点经过插值出来的 u v 坐标，在 texture 中进行采样&lt;/li&gt; &lt;li&gt;由于这个 texture 只有单通道，所以它的第一个 channel 也就是 &lt;code&gt;texture(text, texCoords).r&lt;/code&gt; 就代表了这个字体在这个位置的 alpha 值&lt;/li&gt; &lt;li&gt;然后把 alpha 值输出：&lt;code&gt;(1.0, 1.0, 1.0, alpha)&lt;/code&gt;，即带有 alpha 的白色&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;在绘制文字之前，先绘制好背景色，然后通过设置 blending function：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-2-1&#34;&gt;&lt;a id=&#34;__codelineno-2-1&#34; name=&#34;__codelineno-2-1&#34; href=&#34;#__codelineno-2-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;glEnable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;GL_BLEND&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-2&#34;&gt;&lt;a id=&#34;__codelineno-2-2&#34; name=&#34;__codelineno-2-2&#34; href=&#34;#__codelineno-2-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;glBlendFunc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;GL_SRC_ALPHA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;GL_ONE_MINUS_SRC_ALPHA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;它使得 blending 采用如下的公式：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-3-1&#34;&gt;&lt;a id=&#34;__codelineno-3-1&#34; name=&#34;__codelineno-3-1&#34; href=&#34;#__codelineno-3-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;这里 dest 就是绘制文本前的颜色，src 就是 fragment shader 输出的颜色，也就是 &lt;code&gt;(1.0, 1.0, 1.0, alpha)&lt;/code&gt;。代入公式，就知道最终的结果是：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-4-1&#34;&gt;&lt;a id=&#34;__codelineno-4-1&#34; name=&#34;__codelineno-4-1&#34; href=&#34;#__codelineno-4-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-2&#34;&gt;&lt;a id=&#34;__codelineno-4-2&#34; name=&#34;__codelineno-4-2&#34; href=&#34;#__codelineno-4-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-3&#34;&gt;&lt;a id=&#34;__codelineno-4-3&#34; name=&#34;__codelineno-4-3&#34; href=&#34;#__codelineno-4-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;也就是以 alpha 为不透明度，把白色和背景颜色进行了一次 blend。&lt;/p&gt; &lt;p&gt;如果要设置字体颜色，只需要修改一下 fragment shader：&lt;/p&gt; &lt;div class=&#34;language-c highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-5-1&#34;&gt;&lt;a id=&#34;__codelineno-5-1&#34; name=&#34;__codelineno-5-1&#34; href=&#34;#__codelineno-5-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cp&#34;&gt;#version 320 es&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-2&#34;&gt;&lt;a id=&#34;__codelineno-5-2&#34; name=&#34;__codelineno-5-2&#34; href=&#34;#__codelineno-5-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;precision&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lowp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-3&#34;&gt;&lt;a id=&#34;__codelineno-5-3&#34; name=&#34;__codelineno-5-3&#34; href=&#34;#__codelineno-5-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;texCoords&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-4&#34;&gt;&lt;a id=&#34;__codelineno-5-4&#34; name=&#34;__codelineno-5-4&#34; href=&#34;#__codelineno-5-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-5&#34;&gt;&lt;a id=&#34;__codelineno-5-5&#34; name=&#34;__codelineno-5-5&#34; href=&#34;#__codelineno-5-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;uniform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sampler2D&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-6&#34;&gt;&lt;a id=&#34;__codelineno-5-6&#34; name=&#34;__codelineno-5-6&#34; href=&#34;#__codelineno-5-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;uniform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec3&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;textColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-7&#34;&gt;&lt;a id=&#34;__codelineno-5-7&#34; name=&#34;__codelineno-5-7&#34; href=&#34;#__codelineno-5-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-8&#34;&gt;&lt;a id=&#34;__codelineno-5-8&#34; name=&#34;__codelineno-5-8&#34; href=&#34;#__codelineno-5-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;texture&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;texCoords&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-9&#34;&gt;&lt;a id=&#34;__codelineno-5-9&#34; name=&#34;__codelineno-5-9&#34; href=&#34;#__codelineno-5-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;textColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-10&#34;&gt;&lt;a id=&#34;__codelineno-5-10&#34; name=&#34;__codelineno-5-10&#34; href=&#34;#__codelineno-5-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;此时 src 等于 &lt;code&gt;(textColor.r, textColor.g, textColor.b, alpha)&lt;/code&gt;，经过融合后的结果为：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-6-1&#34;&gt;&lt;a id=&#34;__codelineno-6-1&#34; name=&#34;__codelineno-6-1&#34; href=&#34;#__codelineno-6-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;textColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-2&#34;&gt;&lt;a id=&#34;__codelineno-6-2&#34; name=&#34;__codelineno-6-2&#34; href=&#34;#__codelineno-6-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;textColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-3&#34;&gt;&lt;a id=&#34;__codelineno-6-3&#34; name=&#34;__codelineno-6-3&#34; href=&#34;#__codelineno-6-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;textColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;即最终颜色，等于字体颜色和原来背景颜色，基于 bitmap 的 alpha 值的融合。&lt;/p&gt; &lt;p&gt;解决了颜色，接下来考虑如何设置顶点的信息。前面提到，得到的 bitmap 是一个矩形，而 OpenGL 绘图的基本元素是三角形，因此我们需要拆分成两个三角形来绘图，假如说要绘制一个矩形，它个四个顶点如下：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-7-1&#34;&gt;&lt;a id=&#34;__codelineno-7-1&#34; name=&#34;__codelineno-7-1&#34; href=&#34;#__codelineno-7-1&#34;&gt;&lt;/a&gt;3-4 &lt;/span&gt;&lt;span id=&#34;__span-7-2&#34;&gt;&lt;a id=&#34;__codelineno-7-2&#34; name=&#34;__codelineno-7-2&#34; href=&#34;#__codelineno-7-2&#34;&gt;&lt;/a&gt;| | &lt;/span&gt;&lt;span id=&#34;__span-7-3&#34;&gt;&lt;a id=&#34;__codelineno-7-3&#34; name=&#34;__codelineno-7-3&#34; href=&#34;#__codelineno-7-3&#34;&gt;&lt;/a&gt;1-2 &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;如果确定左下角 3 这个顶点的坐标是 (xpos, ypos)，然后矩形的宽度是 w，高度是 h，考虑到 OpenGL 的坐标系也是向右 X 正方向，向上 Y 正方向，那么这四个顶点的坐标：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;顶点 1：(xpos, ypos)&lt;/li&gt; &lt;li&gt;顶点 2：(xpos + w, ypos)&lt;/li&gt; &lt;li&gt;顶点 3：(xpos, ypos + h)&lt;/li&gt; &lt;li&gt;顶点 4：(xpos + w, ypos + h)&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;接下来考虑这些顶点对应的 uv 坐标。首先，我们知道这些顶点对应的 bitmap 的下标在哪里；然后我们又知道这些 bitmap 的下标对应的 uv 坐标，那就每个顶点找一次对应关系：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;顶点 1：(xpos, ypos)，下标是 &lt;code&gt;width*(height-1)&lt;/code&gt;，uv 坐标是 (0, 1)&lt;/li&gt; &lt;li&gt;顶点 2：(xpos + w, ypos)，下标是 &lt;code&gt;width*(height-1)+width-1&lt;/code&gt;，uv 坐标是 (1, 1)&lt;/li&gt; &lt;li&gt;顶点 3：(xpos, ypos + h)，下标是 &lt;code&gt;0&lt;/code&gt;，uv 坐标是 (0, 0)&lt;/li&gt; &lt;li&gt;顶点 4：(xpos + w, ypos + h)，下标是 &lt;code&gt;width-1&lt;/code&gt;，uv 坐标是 (1, 0)&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;为了绘制这个矩形，绘制两个三角形，分别是 3-&amp;gt;1-&amp;gt;2 和 3-&amp;gt;2-&amp;gt;4，一共六个顶点的 (x, y, u, v) 信息就是：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;3: (xpos , ypos + h, 0, 0)&lt;/li&gt; &lt;li&gt;1: (xpos , ypos , 0, 1)&lt;/li&gt; &lt;li&gt;2: (xpos + w, ypos , 1, 1)&lt;/li&gt; &lt;li&gt;3: (xpos , ypos + h, 0, 0)&lt;/li&gt; &lt;li&gt;2: (xpos + w, ypos , 1, 1)&lt;/li&gt; &lt;li&gt;4: (xpos + w, ypos + h, 1, 0)&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;把这些数传递给 vertex shader，就可以画出来这个字符了。&lt;/p&gt; &lt;p&gt;最后还有一个小细节：上述的 xpos 和 ypos 说的是矩形左下角的坐标，但是我们画图的时候，实际上期望的是把字符都画到同一条线上。也就是说，我们指定 origin 的 xy 坐标，然后根据每个字符的 bearingX 和 bearingY 来算出它的矩形的左下角的坐标 xpos 和 ypos：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;xpos = originX + bearingX&lt;/li&gt; &lt;li&gt;ypos = originY + bearingY - height&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;至此就实现了逐个字符绘制需要的所有内容。这也是 &lt;a href=&#34;https://learnopengl.com/In-Practice/Text-Rendering&#34;&gt;Text Rendering - Learn OpenGL&lt;/a&gt; 这篇文章所讲的内容。&lt;/p&gt; &lt;h2 id=&#34;texture-atlas&#34;&gt;Texture Atlas&lt;a class=&#34;headerlink&#34; href=&#34;#texture-atlas&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;上面这种逐字符绘制的方法比较简单，但是也有硬伤，比如每次绘制字符，都需要切换 texture，更新 buffer，再进行一次 glDrawArrays 进行绘制，效率比较低。所以一个想法是，把这些 bitmap 拼接起来，合成一个大的 texture，然后把每个字符在这个大的 texture 内的 uv 坐标保存下来。这样，可以一次性把所有字符的所有三角形都传递给 OpenGL，一次绘制完成，不涉及到 texture 的切换。这样效率会高很多。&lt;/p&gt; &lt;p&gt;具体到代码上，也就是分成两步：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;bitmap 的拼接，这一步比较灵活，理想情况下是构造一个比较紧密的排布，但也可以留一些空间，直接对齐到最大宽度/高度的整数倍网格上，然后进行 uv 坐标的计算&lt;/li&gt; &lt;li&gt;剩下的，就是在计算顶点信息的时候，用计算好的 uv 坐标，其中 left/right 对应 bitmap 左右两侧的 u 坐标，top/bottom 对应 bitmap 上下两侧的 v 坐标（注意 top 比 bottom 小，因为竖直方向是反的）：&lt;ul&gt; &lt;li&gt;3: (xpos , ypos + h, left , top )&lt;/li&gt; &lt;li&gt;1: (xpos , ypos , left , bottom)&lt;/li&gt; &lt;li&gt;2: (xpos + w, ypos , right, bottom)&lt;/li&gt; &lt;li&gt;3: (xpos , ypos + h, left , top )&lt;/li&gt; &lt;li&gt;2: (xpos + w, ypos , right, bottom)&lt;/li&gt; &lt;li&gt;4: (xpos + w, ypos + h, right, top )&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;此外，在前面的 shader 代码里，字体颜色用的是 uniform，也就是每次调用只能用同一种颜色。修改的方法，就是把它也变成顶点的属性，从 vertex shader 直接传给 fragment shader，替代 uniform 变量。不过由于 vec4 已经放不下更多的维度了，所以需要另外开一个 attribute：&lt;/p&gt; &lt;div class=&#34;language-c highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-8-1&#34;&gt;&lt;a id=&#34;__codelineno-8-1&#34; name=&#34;__codelineno-8-1&#34; href=&#34;#__codelineno-8-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// vertex shader&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-2&#34;&gt;&lt;a id=&#34;__codelineno-8-2&#34; name=&#34;__codelineno-8-2&#34; href=&#34;#__codelineno-8-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cp&#34;&gt;#version 320 es&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-3&#34;&gt;&lt;a id=&#34;__codelineno-8-3&#34; name=&#34;__codelineno-8-3&#34; href=&#34;#__codelineno-8-3&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-4&#34;&gt;&lt;a id=&#34;__codelineno-8-4&#34; name=&#34;__codelineno-8-4&#34; href=&#34;#__codelineno-8-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vertex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// xy is position, zw is its texture coordinates&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-5&#34;&gt;&lt;a id=&#34;__codelineno-8-5&#34; name=&#34;__codelineno-8-5&#34; href=&#34;#__codelineno-8-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec3&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;textColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-6&#34;&gt;&lt;a id=&#34;__codelineno-8-6&#34; name=&#34;__codelineno-8-6&#34; href=&#34;#__codelineno-8-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;texCoors&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// output texture coordinates&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-7&#34;&gt;&lt;a id=&#34;__codelineno-8-7&#34; name=&#34;__codelineno-8-7&#34; href=&#34;#__codelineno-8-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec3&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fragTextColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// send to fragment shader&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-8&#34;&gt;&lt;a id=&#34;__codelineno-8-8&#34; name=&#34;__codelineno-8-8&#34; href=&#34;#__codelineno-8-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-9&#34;&gt;&lt;a id=&#34;__codelineno-8-9&#34; name=&#34;__codelineno-8-9&#34; href=&#34;#__codelineno-8-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gl_Position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xy&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vertex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-10&#34;&gt;&lt;a id=&#34;__codelineno-8-10&#34; name=&#34;__codelineno-8-10&#34; href=&#34;#__codelineno-8-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gl_Position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// we don&amp;#39;t care about depth now&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-11&#34;&gt;&lt;a id=&#34;__codelineno-8-11&#34; name=&#34;__codelineno-8-11&#34; href=&#34;#__codelineno-8-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gl_Position&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;w&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// (x, y, z, w) corresponds to (x/w, y/w, z/w), so we set w = 1.0&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-12&#34;&gt;&lt;a id=&#34;__codelineno-8-12&#34; name=&#34;__codelineno-8-12&#34; href=&#34;#__codelineno-8-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;texCoords&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vertex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;zw&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-13&#34;&gt;&lt;a id=&#34;__codelineno-8-13&#34; name=&#34;__codelineno-8-13&#34; href=&#34;#__codelineno-8-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fragTextColor&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;textColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-14&#34;&gt;&lt;a id=&#34;__codelineno-8-14&#34; name=&#34;__codelineno-8-14&#34; href=&#34;#__codelineno-8-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-15&#34;&gt;&lt;a id=&#34;__codelineno-8-15&#34; name=&#34;__codelineno-8-15&#34; href=&#34;#__codelineno-8-15&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-16&#34;&gt;&lt;a id=&#34;__codelineno-8-16&#34; name=&#34;__codelineno-8-16&#34; href=&#34;#__codelineno-8-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// fragment shader&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-17&#34;&gt;&lt;a id=&#34;__codelineno-8-17&#34; name=&#34;__codelineno-8-17&#34; href=&#34;#__codelineno-8-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cp&#34;&gt;#version 320 es&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-18&#34;&gt;&lt;a id=&#34;__codelineno-8-18&#34; name=&#34;__codelineno-8-18&#34; href=&#34;#__codelineno-8-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;precision&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lowp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-19&#34;&gt;&lt;a id=&#34;__codelineno-8-19&#34; name=&#34;__codelineno-8-19&#34; href=&#34;#__codelineno-8-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;texCoords&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-20&#34;&gt;&lt;a id=&#34;__codelineno-8-20&#34; name=&#34;__codelineno-8-20&#34; href=&#34;#__codelineno-8-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec3&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fragTextColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-21&#34;&gt;&lt;a id=&#34;__codelineno-8-21&#34; name=&#34;__codelineno-8-21&#34; href=&#34;#__codelineno-8-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-22&#34;&gt;&lt;a id=&#34;__codelineno-8-22&#34; name=&#34;__codelineno-8-22&#34; href=&#34;#__codelineno-8-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;uniform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sampler2D&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-23&#34;&gt;&lt;a id=&#34;__codelineno-8-23&#34; name=&#34;__codelineno-8-23&#34; href=&#34;#__codelineno-8-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-24&#34;&gt;&lt;a id=&#34;__codelineno-8-24&#34; name=&#34;__codelineno-8-24&#34; href=&#34;#__codelineno-8-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;texture&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;texCoords&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-25&#34;&gt;&lt;a id=&#34;__codelineno-8-25&#34; name=&#34;__codelineno-8-25&#34; href=&#34;#__codelineno-8-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;color&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fragTextColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-26&#34;&gt;&lt;a id=&#34;__codelineno-8-26&#34; name=&#34;__codelineno-8-26&#34; href=&#34;#__codelineno-8-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h2 id=&#34;背景和光标绘制&#34;&gt;背景和光标绘制&lt;a class=&#34;headerlink&#34; href=&#34;#背景和光标绘制&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;接下来回到终端模拟器，它除了绘制字符，还需要绘制背景颜色和光标。前面在绘制字符的时候，只把 bounding box 绘制了出来，那么剩下的空白部分是没有绘制的。但是终端里，每一个位置的背景颜色都可能不同，所以还需要给每个位置绘制对应的背景颜色。这里有两种做法：&lt;/p&gt; &lt;p&gt;第一种做法是，把前面每个字符的 bitmap 扩展到终端里一个固定的位置的大小，这样每次绘制的矩形，就是完整的一个位置的区域，这个时候再去绘制背景颜色，就比较容易了：修改 vertex shader 和 fragment shader，在内部进行一次 blend：&lt;code&gt;color = vec4(fragTextColor.rgb * alpha + fragBackgroundColor.rgb * (1.0 - alpha), 1.0)&lt;/code&gt;，相当于是丢掉了 OpenGL 的 blend function，自己完成了前景和后景的绘制。&lt;/p&gt; &lt;p&gt;但这个方法有个问题：并非所有的字符的 bitmap 都可以放到一个固定大小的矩形里的。有一些特殊字符，要么长的太高，要么在很下面的位置。后续可能还有更复杂的需求，比如 CJK 和 Emoji，那么字符的宽度又不一样了。所以这个时候导出了第二种做法：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一轮，先绘制出终端每个位置的背景颜色&lt;/li&gt; &lt;li&gt;第二轮，再绘制出每个位置的字符，和背景进行融合&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;这时候 shader 没法自己做 blend，所以这考虑怎么用 blend function 来实现这个 blend 的计算。首先，要考虑我们最终需要的结果是：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-9-1&#34;&gt;&lt;a id=&#34;__codelineno-9-1&#34; name=&#34;__codelineno-9-1&#34; href=&#34;#__codelineno-9-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;textColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-2&#34;&gt;&lt;a id=&#34;__codelineno-9-2&#34; name=&#34;__codelineno-9-2&#34; href=&#34;#__codelineno-9-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;textColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-3&#34;&gt;&lt;a id=&#34;__codelineno-9-3&#34; name=&#34;__codelineno-9-3&#34; href=&#34;#__codelineno-9-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;textColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-4&#34;&gt;&lt;a id=&#34;__codelineno-9-4&#34; name=&#34;__codelineno-9-4&#34; href=&#34;#__codelineno-9-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;由于是 OpenGL 做的 blending，我们需要用 OpenGL 自带的 blending mode 来实现上述公式。OpenGL 可以指定 RGB 的 source 和 dest 的 blending 方式，比如：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;GL_ONE：乘以 1 的系数&lt;/li&gt; &lt;li&gt;GL_ONE_MINUS_SRC_ALPHA：乘以 (1 - source.a) 的系数&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;根据这个，就可以想到，设置 &lt;code&gt;source = vec4(textColor.rgb * alpha, alpha)&lt;/code&gt;，设置 source 采用 GL_ONE 方式，dest 采用 GL_ONE_MINUS_SRC_ALPHA 模式，那么 OpenGL 负责剩下的 blending 工作 &lt;code&gt;final = source * 1 + dest * (1 - source.a)&lt;/code&gt;（要求 &lt;code&gt;dest.a = 1.0&lt;/code&gt;）：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-10-1&#34;&gt;&lt;a id=&#34;__codelineno-10-1&#34; name=&#34;__codelineno-10-1&#34; href=&#34;#__codelineno-10-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;textColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-2&#34;&gt;&lt;a id=&#34;__codelineno-10-2&#34; name=&#34;__codelineno-10-2&#34; href=&#34;#__codelineno-10-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;textColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-3&#34;&gt;&lt;a id=&#34;__codelineno-10-3&#34; name=&#34;__codelineno-10-3&#34; href=&#34;#__codelineno-10-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;textColor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-4&#34;&gt;&lt;a id=&#34;__codelineno-10-4&#34; name=&#34;__codelineno-10-4&#34; href=&#34;#__codelineno-10-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;正好实现了想要的计算公式。这个方法来自于 &lt;a href=&#34;https://github.com/servo/webrender/blob/main/webrender/doc/text-rendering.md&#34;&gt;Text Rendering - WebRender&lt;/a&gt;。有了这个推导后，就可以分两轮，完成终端里前后景的绘制了。&lt;/p&gt; &lt;p&gt;目前 &lt;a href=&#34;https://github.com/jiegec/Termony&#34;&gt;Termony&lt;/a&gt; 用的就是这种实现方法：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;首先把不同字重的各种字符的 bitmap 拼在一起，放在一个 texture 内部&lt;/li&gt; &lt;li&gt;使用两阶段绘制，第一阶段&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;注：如果在 source 使用 GL_SRC_ALPHA，设置 &lt;code&gt;source = vec4(textColor.rgb, alpha)&lt;/code&gt;，这样 &lt;code&gt;final.r = source.r * source.a + dest.r * (1 - source.a) = textColor.r * alpha + dest.r * (1 - alpha)&lt;/code&gt;，结果是上面是一样的，不过这个时候 final 的 alpha 值等于 &lt;code&gt;source.a * source.a + dest.a * (1 - source.a)&lt;/code&gt; 是 alpha 和 dest.a 经过 blend 以后的结果，不再是 1.0，如果不用它就无所谓。上面这种 &lt;code&gt;vec4(textColor.rgb * alpha, alpha)&lt;/code&gt; 的计算方法，叫做 premultiplied alpha，也就是预先把 alpha 乘到颜色项里，可以方便后续的计算。&lt;/p&gt; &lt;h2 id=&#34;在鸿蒙上使用-opengl-渲染&#34;&gt;在鸿蒙上使用 OpenGL 渲染&lt;a class=&#34;headerlink&#34; href=&#34;#在鸿蒙上使用-opengl-渲染&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;最后再简单列举一下，在鸿蒙上用 OpenGL 渲染都需要哪些事情：&lt;/p&gt; &lt;p&gt;首先，在 ArkTS 中，插入一个 XComponent，然后在 XComponentController 的回调函数中，通知 native api：&lt;/p&gt; &lt;div class=&#34;language-javascript highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-11-1&#34;&gt;&lt;a id=&#34;__codelineno-11-1&#34; name=&#34;__codelineno-11-1&#34; href=&#34;#__codelineno-11-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;testNapi&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;from&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;libentry.so&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-2&#34;&gt;&lt;a id=&#34;__codelineno-11-2&#34; name=&#34;__codelineno-11-2&#34; href=&#34;#__codelineno-11-2&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-3&#34;&gt;&lt;a id=&#34;__codelineno-11-3&#34; name=&#34;__codelineno-11-3&#34; href=&#34;#__codelineno-11-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;MyXComponentController&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;extends&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;XComponentController&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-4&#34;&gt;&lt;a id=&#34;__codelineno-11-4&#34; name=&#34;__codelineno-11-4&#34; href=&#34;#__codelineno-11-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;onSurfaceCreated&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;surfaceId&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;ow&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-5&#34;&gt;&lt;a id=&#34;__codelineno-11-5&#34; name=&#34;__codelineno-11-5&#34; href=&#34;#__codelineno-11-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;hilog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;DOMAIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;testTag&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;onSurfaceCreated surfaceId: %{public}s&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;surfaceId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-6&#34;&gt;&lt;a id=&#34;__codelineno-11-6&#34; name=&#34;__codelineno-11-6&#34; href=&#34;#__codelineno-11-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;testNapi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;createSurface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;BigInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;surfaceId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-7&#34;&gt;&lt;a id=&#34;__codelineno-11-7&#34; name=&#34;__codelineno-11-7&#34; href=&#34;#__codelineno-11-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-8&#34;&gt;&lt;a id=&#34;__codelineno-11-8&#34; name=&#34;__codelineno-11-8&#34; href=&#34;#__codelineno-11-8&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-9&#34;&gt;&lt;a id=&#34;__codelineno-11-9&#34; name=&#34;__codelineno-11-9&#34; href=&#34;#__codelineno-11-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;onSurfaceChanged&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;surfaceId&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;rect&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;SurfaceRect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;ow&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-10&#34;&gt;&lt;a id=&#34;__codelineno-11-10&#34; name=&#34;__codelineno-11-10&#34; href=&#34;#__codelineno-11-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;hilog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;DOMAIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;testTag&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;onSurfaceChanged surfaceId: %{public}s rect: %{public}s&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;surfaceId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;JSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stringify&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;rect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-11&#34;&gt;&lt;a id=&#34;__codelineno-11-11&#34; name=&#34;__codelineno-11-11&#34; href=&#34;#__codelineno-11-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;testNapi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;resizeSurface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;BigInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;surfaceId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;rect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;surfaceWidth&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;rect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;surfaceHeight&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-12&#34;&gt;&lt;a id=&#34;__codelineno-11-12&#34; name=&#34;__codelineno-11-12&#34; href=&#34;#__codelineno-11-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-13&#34;&gt;&lt;a id=&#34;__codelineno-11-13&#34; name=&#34;__codelineno-11-13&#34; href=&#34;#__codelineno-11-13&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-14&#34;&gt;&lt;a id=&#34;__codelineno-11-14&#34; name=&#34;__codelineno-11-14&#34; href=&#34;#__codelineno-11-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;onSurfaceDestroyed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;surfaceId&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;ow&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-15&#34;&gt;&lt;a id=&#34;__codelineno-11-15&#34; name=&#34;__codelineno-11-15&#34; href=&#34;#__codelineno-11-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;hilog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;DOMAIN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;testTag&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;onSurfaceDestroyed surfaceId: %{public}s&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;surfaceId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-16&#34;&gt;&lt;a id=&#34;__codelineno-11-16&#34; name=&#34;__codelineno-11-16&#34; href=&#34;#__codelineno-11-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;testNapi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;destroySurface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;BigInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;surfaceId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-17&#34;&gt;&lt;a id=&#34;__codelineno-11-17&#34; name=&#34;__codelineno-11-17&#34; href=&#34;#__codelineno-11-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-18&#34;&gt;&lt;a id=&#34;__codelineno-11-18&#34; name=&#34;__codelineno-11-18&#34; href=&#34;#__codelineno-11-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-19&#34;&gt;&lt;a id=&#34;__codelineno-11-19&#34; name=&#34;__codelineno-11-19&#34; href=&#34;#__codelineno-11-19&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-20&#34;&gt;&lt;a id=&#34;__codelineno-11-20&#34; name=&#34;__codelineno-11-20&#34; href=&#34;#__codelineno-11-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Component&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-21&#34;&gt;&lt;a id=&#34;__codelineno-11-21&#34; name=&#34;__codelineno-11-21&#34; href=&#34;#__codelineno-11-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nx&#34;&gt;struct&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Index&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-22&#34;&gt;&lt;a id=&#34;__codelineno-11-22&#34; name=&#34;__codelineno-11-22&#34; href=&#34;#__codelineno-11-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;xComponentController&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;XComponentController&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;ow&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;MyXComponentController&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-23&#34;&gt;&lt;a id=&#34;__codelineno-11-23&#34; name=&#34;__codelineno-11-23&#34; href=&#34;#__codelineno-11-23&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-24&#34;&gt;&lt;a id=&#34;__codelineno-11-24&#34; name=&#34;__codelineno-11-24&#34; href=&#34;#__codelineno-11-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;build&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-25&#34;&gt;&lt;a id=&#34;__codelineno-11-25&#34; name=&#34;__codelineno-11-25&#34; href=&#34;#__codelineno-11-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// ...&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-26&#34;&gt;&lt;a id=&#34;__codelineno-11-26&#34; name=&#34;__codelineno-11-26&#34; href=&#34;#__codelineno-11-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;XComponent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-27&#34;&gt;&lt;a id=&#34;__codelineno-11-27&#34; name=&#34;__codelineno-11-27&#34; href=&#34;#__codelineno-11-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;XComponentType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;SURFACE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-28&#34;&gt;&lt;a id=&#34;__codelineno-11-28&#34; name=&#34;__codelineno-11-28&#34; href=&#34;#__codelineno-11-28&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;controller&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;xComponentController&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-29&#34;&gt;&lt;a id=&#34;__codelineno-11-29&#34; name=&#34;__codelineno-11-29&#34; href=&#34;#__codelineno-11-29&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-30&#34;&gt;&lt;a id=&#34;__codelineno-11-30&#34; name=&#34;__codelineno-11-30&#34; href=&#34;#__codelineno-11-30&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-31&#34;&gt;&lt;a id=&#34;__codelineno-11-31&#34; name=&#34;__codelineno-11-31&#34; href=&#34;#__codelineno-11-31&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;native 部分需要实现至少两个函数：createSurface 和 resizeSurface。其中主要的工作在 CreateSurface 中完成，ResizeSurface 会在窗口大小变化的时候被调用。&lt;/p&gt; &lt;p&gt;CreateSurface 要做的事情：&lt;/p&gt; &lt;p&gt;读取 surface id：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-12-1&#34;&gt;&lt;a id=&#34;__codelineno-12-1&#34; name=&#34;__codelineno-12-1&#34; href=&#34;#__codelineno-12-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kt&#34;&gt;size_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-2&#34;&gt;&lt;a id=&#34;__codelineno-12-2&#34; name=&#34;__codelineno-12-2&#34; href=&#34;#__codelineno-12-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;napi_value&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;nullptr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-3&#34;&gt;&lt;a id=&#34;__codelineno-12-3&#34; name=&#34;__codelineno-12-3&#34; href=&#34;#__codelineno-12-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;napi_get_cb_info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;env&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;nullptr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;nullptr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-4&#34;&gt;&lt;a id=&#34;__codelineno-12-4&#34; name=&#34;__codelineno-12-4&#34; href=&#34;#__codelineno-12-4&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-5&#34;&gt;&lt;a id=&#34;__codelineno-12-5&#34; name=&#34;__codelineno-12-5&#34; href=&#34;#__codelineno-12-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kt&#34;&gt;int64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;surface_id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-6&#34;&gt;&lt;a id=&#34;__codelineno-12-6&#34; name=&#34;__codelineno-12-6&#34; href=&#34;#__codelineno-12-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lossless&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-7&#34;&gt;&lt;a id=&#34;__codelineno-12-7&#34; name=&#34;__codelineno-12-7&#34; href=&#34;#__codelineno-12-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;napi_status&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;napi_get_value_bigint_int64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;env&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;surface_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lossless&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-8&#34;&gt;&lt;a id=&#34;__codelineno-12-8&#34; name=&#34;__codelineno-12-8&#34; href=&#34;#__codelineno-12-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;assert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;napi_ok&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;创建 OHNativeWindow：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-13-1&#34;&gt;&lt;a id=&#34;__codelineno-13-1&#34; name=&#34;__codelineno-13-1&#34; href=&#34;#__codelineno-13-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;OHNativeWindow&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;native_window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-13-2&#34;&gt;&lt;a id=&#34;__codelineno-13-2&#34; name=&#34;__codelineno-13-2&#34; href=&#34;#__codelineno-13-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;OH_NativeWindow_CreateNativeWindowFromSurfaceId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;surface_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;native_window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-13-3&#34;&gt;&lt;a id=&#34;__codelineno-13-3&#34; name=&#34;__codelineno-13-3&#34; href=&#34;#__codelineno-13-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;assert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;native_window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;创建 EGLDisplay：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-14-1&#34;&gt;&lt;a id=&#34;__codelineno-14-1&#34; name=&#34;__codelineno-14-1&#34; href=&#34;#__codelineno-14-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;EGLNativeWindowType&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_window&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGLNativeWindowType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;native_window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-14-2&#34;&gt;&lt;a id=&#34;__codelineno-14-2&#34; name=&#34;__codelineno-14-2&#34; href=&#34;#__codelineno-14-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;EGLDisplay&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_display&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eglGetDisplay&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_DEFAULT_DISPLAY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-14-3&#34;&gt;&lt;a id=&#34;__codelineno-14-3&#34; name=&#34;__codelineno-14-3&#34; href=&#34;#__codelineno-14-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;assert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_display&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_NO_DISPLAY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;初始化 EGL：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-15-1&#34;&gt;&lt;a id=&#34;__codelineno-15-1&#34; name=&#34;__codelineno-15-1&#34; href=&#34;#__codelineno-15-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;EGLint&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;major_version&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-15-2&#34;&gt;&lt;a id=&#34;__codelineno-15-2&#34; name=&#34;__codelineno-15-2&#34; href=&#34;#__codelineno-15-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;EGLint&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;minor_version&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-15-3&#34;&gt;&lt;a id=&#34;__codelineno-15-3&#34; name=&#34;__codelineno-15-3&#34; href=&#34;#__codelineno-15-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;EGLBoolean&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_res&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eglInitialize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;major_version&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;minor_version&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-15-4&#34;&gt;&lt;a id=&#34;__codelineno-15-4&#34; name=&#34;__codelineno-15-4&#34; href=&#34;#__codelineno-15-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;assert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_res&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;选择 EGL 配置：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-16-1&#34;&gt;&lt;a id=&#34;__codelineno-16-1&#34; name=&#34;__codelineno-16-1&#34; href=&#34;#__codelineno-16-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGLint&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;attrib&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_SURFACE_TYPE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-2&#34;&gt;&lt;a id=&#34;__codelineno-16-2&#34; name=&#34;__codelineno-16-2&#34; href=&#34;#__codelineno-16-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_WINDOW_BIT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-3&#34;&gt;&lt;a id=&#34;__codelineno-16-3&#34; name=&#34;__codelineno-16-3&#34; href=&#34;#__codelineno-16-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_RENDERABLE_TYPE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-4&#34;&gt;&lt;a id=&#34;__codelineno-16-4&#34; name=&#34;__codelineno-16-4&#34; href=&#34;#__codelineno-16-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_OPENGL_ES2_BIT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-5&#34;&gt;&lt;a id=&#34;__codelineno-16-5&#34; name=&#34;__codelineno-16-5&#34; href=&#34;#__codelineno-16-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_RED_SIZE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-6&#34;&gt;&lt;a id=&#34;__codelineno-16-6&#34; name=&#34;__codelineno-16-6&#34; href=&#34;#__codelineno-16-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-7&#34;&gt;&lt;a id=&#34;__codelineno-16-7&#34; name=&#34;__codelineno-16-7&#34; href=&#34;#__codelineno-16-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_GREEN_SIZE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-8&#34;&gt;&lt;a id=&#34;__codelineno-16-8&#34; name=&#34;__codelineno-16-8&#34; href=&#34;#__codelineno-16-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-9&#34;&gt;&lt;a id=&#34;__codelineno-16-9&#34; name=&#34;__codelineno-16-9&#34; href=&#34;#__codelineno-16-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_BLUE_SIZE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-10&#34;&gt;&lt;a id=&#34;__codelineno-16-10&#34; name=&#34;__codelineno-16-10&#34; href=&#34;#__codelineno-16-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-11&#34;&gt;&lt;a id=&#34;__codelineno-16-11&#34; name=&#34;__codelineno-16-11&#34; href=&#34;#__codelineno-16-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_ALPHA_SIZE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-12&#34;&gt;&lt;a id=&#34;__codelineno-16-12&#34; name=&#34;__codelineno-16-12&#34; href=&#34;#__codelineno-16-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-13&#34;&gt;&lt;a id=&#34;__codelineno-16-13&#34; name=&#34;__codelineno-16-13&#34; href=&#34;#__codelineno-16-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_DEPTH_SIZE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-14&#34;&gt;&lt;a id=&#34;__codelineno-16-14&#34; name=&#34;__codelineno-16-14&#34; href=&#34;#__codelineno-16-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;24&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-15&#34;&gt;&lt;a id=&#34;__codelineno-16-15&#34; name=&#34;__codelineno-16-15&#34; href=&#34;#__codelineno-16-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_STENCIL_SIZE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-16&#34;&gt;&lt;a id=&#34;__codelineno-16-16&#34; name=&#34;__codelineno-16-16&#34; href=&#34;#__codelineno-16-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-17&#34;&gt;&lt;a id=&#34;__codelineno-16-17&#34; name=&#34;__codelineno-16-17&#34; href=&#34;#__codelineno-16-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_SAMPLE_BUFFERS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-18&#34;&gt;&lt;a id=&#34;__codelineno-16-18&#34; name=&#34;__codelineno-16-18&#34; href=&#34;#__codelineno-16-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-19&#34;&gt;&lt;a id=&#34;__codelineno-16-19&#34; name=&#34;__codelineno-16-19&#34; href=&#34;#__codelineno-16-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_SAMPLES&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-20&#34;&gt;&lt;a id=&#34;__codelineno-16-20&#34; name=&#34;__codelineno-16-20&#34; href=&#34;#__codelineno-16-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Request 4 samples for multisampling&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-21&#34;&gt;&lt;a id=&#34;__codelineno-16-21&#34; name=&#34;__codelineno-16-21&#34; href=&#34;#__codelineno-16-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_NONE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-22&#34;&gt;&lt;a id=&#34;__codelineno-16-22&#34; name=&#34;__codelineno-16-22&#34; href=&#34;#__codelineno-16-22&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-23&#34;&gt;&lt;a id=&#34;__codelineno-16-23&#34; name=&#34;__codelineno-16-23&#34; href=&#34;#__codelineno-16-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGLint&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;max_config_size&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-24&#34;&gt;&lt;a id=&#34;__codelineno-16-24&#34; name=&#34;__codelineno-16-24&#34; href=&#34;#__codelineno-16-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;EGLint&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num_configs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-25&#34;&gt;&lt;a id=&#34;__codelineno-16-25&#34; name=&#34;__codelineno-16-25&#34; href=&#34;#__codelineno-16-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;EGLConfig&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-26&#34;&gt;&lt;a id=&#34;__codelineno-16-26&#34; name=&#34;__codelineno-16-26&#34; href=&#34;#__codelineno-16-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;egl_res&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eglChooseConfig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;attrib&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;max_config_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num_configs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-16-27&#34;&gt;&lt;a id=&#34;__codelineno-16-27&#34; name=&#34;__codelineno-16-27&#34; href=&#34;#__codelineno-16-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;assert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_res&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;创建 EGLSurface：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-17-1&#34;&gt;&lt;a id=&#34;__codelineno-17-1&#34; name=&#34;__codelineno-17-1&#34; href=&#34;#__codelineno-17-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;EGLSurface&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_surface&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eglCreateWindowSurface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;创建 EGLContext：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-18-1&#34;&gt;&lt;a id=&#34;__codelineno-18-1&#34; name=&#34;__codelineno-18-1&#34; href=&#34;#__codelineno-18-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;EGLint&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context_attributes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_CONTEXT_CLIENT_VERSION&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_NONE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-18-2&#34;&gt;&lt;a id=&#34;__codelineno-18-2&#34; name=&#34;__codelineno-18-2&#34; href=&#34;#__codelineno-18-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;EGLContext&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_context&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eglCreateContext&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;EGL_NO_CONTEXT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context_attributes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;在当前线程启用 EGL：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-19-1&#34;&gt;&lt;a id=&#34;__codelineno-19-1&#34; name=&#34;__codelineno-19-1&#34; href=&#34;#__codelineno-19-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;eglMakeCurrent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_surface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_surface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;在这之后就可以用 OpenGL 的各种函数了。OpenGL 绘制完成以后，更新到窗口上：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-20-1&#34;&gt;&lt;a id=&#34;__codelineno-20-1&#34; name=&#34;__codelineno-20-1&#34; href=&#34;#__codelineno-20-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;eglSwapBuffers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_display&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;egl_surface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;在 ResizeSurface 中，主要是更新 glViewport，让它按照新的 surface 大小来绘制。&lt;/p&gt; &lt;h2 id=&#34;参考&#34;&gt;参考&lt;a class=&#34;headerlink&#34; href=&#34;#参考&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://learnopengl.com/In-Practice/Text-Rendering&#34;&gt;Text Rendering - Learn OpenGL&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://github.com/servo/webrender/blob/main/webrender/doc/text-rendering.md&#34;&gt;Text Rendering - WebRender&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;</description> <link>https://jia.je/hardware/2025/06/10/terminal-emulator-text-rendering/</link> <pubDate>Tue, 10 Jun 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2025/06/10/terminal-emulator-text-rendering/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2025/06/10/terminal-emulator-text-rendering.png" type="image/png" length="49171" /> </item> <item> <title>鸿蒙电脑 MateBook Pro 开箱体验</title> <category>arm64</category> <category>hardware</category> <category>harmonyos</category> <category>huawei</category> <category>matebook</category> <category>matebookpro</category> <description>&lt;h1 id=&#34;鸿蒙电脑-matebook-pro-开箱体验&#34;&gt;鸿蒙电脑 MateBook Pro 开箱体验&lt;a class=&#34;headerlink&#34; href=&#34;#鸿蒙电脑-matebook-pro-开箱体验&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;购买&#34;&gt;购买&lt;a class=&#34;headerlink&#34; href=&#34;#购买&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;2025.6.6 号正式开卖，当华为线上商城显示没货的时候，果断去线下门店买了一台回来。购买的是 32GB 内存，1TB SSD 存储，加柔光屏的版本，型号 HAD-W32，原价 9999，国补后 7999。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;开箱&#34;&gt;开箱&lt;a class=&#34;headerlink&#34; href=&#34;#开箱&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;由于用了国补，需要当面激活，就在店里直接激活了，所以没有体验到鸿蒙系统的扫码激活功能，有点可惜。激活前的第一次开机需要插电，直接按电源键是没有反应的。激活过程也很简单，联网，创建用户，登录华为账号，输入指纹，就可以了。包装盒里还有 140W 单口 Type-C 电源适配器，体积挺小的。此外附赠了一条 Type-C to Type-C 的线，还有一个 Type-C 有线耳机，外加一个 Type-A 母口加 Type-C 公口的线，可以用来接 Type-A 公口的外设。此外还有快速指南和一个超纤抛光布。店家还贴心地提供了一个虚拟机的安装教程。&lt;/p&gt; &lt;p&gt;外形上，就是 MateBook X Pro 加了一个 HarmonyOS 的标识，上手很轻，不愧是不到一公斤的笔记本，对于习惯用 MacBookAir 轻薄本的我来说，是很大的一个亮点。不像 MacBookAir，这台鸿蒙电脑有风扇，有点小小的不习惯，但还算安静。&lt;/p&gt; &lt;p&gt;规格如下：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;970g 重量&lt;/li&gt; &lt;li&gt;14.2 寸显示器&lt;/li&gt; &lt;li&gt;3120x2080 分辨率，120 Hz 刷新率&lt;/li&gt; &lt;li&gt;1.8mm 键程键盘&lt;/li&gt; &lt;li&gt;70 Wh 电池&lt;/li&gt; &lt;/ul&gt; &lt;h2 id=&#34;系统体验&#34;&gt;系统体验&lt;a class=&#34;headerlink&#34; href=&#34;#系统体验&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;预装的版本是 HarmonyOS 5.0.1.305，有更新 5.0.1.310 SP9（SP9C00E301R9P2patch02，内核 1.9.5 2025-05-26），首先更新了一下系统。这是我的第一台支持触屏的笔记本，所以用起来还有点新奇。这个柔光屏用起来触感不错，和之前买的柔光屏 MatePad 的触感类似。&lt;/p&gt; &lt;p&gt;底部状态栏的颜色会随着情况变化，比如在桌面的时候，默认壁纸是黑色的，状态栏也就是黑色的。如果打开了设置，设置是白色的，状态栏也就是白色的。之后可以多测试一下它具体的变色逻辑。&lt;/p&gt; &lt;p&gt;系统里预装了 WPS Office，迅雷，亿图，中望 CAD，剪映，好压，抖音等，面向的客户群体很显然了。虽然预装，但都可以卸载。&lt;/p&gt; &lt;p&gt;内置了控制手机屏幕的功能，有略微的不跟手，但由于电脑本身也是触屏，所以体验还是和手机很接近的。下方是经典的三个按钮。这个协同，可以电脑和手机同时操作，还是挺好的，不会说电脑控制了手机，手机就不能用的情况。手机界面左上角会提示协同中。键鼠共享功能不错，可以把手机当屏幕，然后用电脑的键盘和触摸板控制，外接的鼠标也可以。&lt;/p&gt; &lt;p&gt;触摸板手势方面，可以在设置里修改，比如菜单弹出改成双指点按或轻点。触摸板的手感比苹果还是有一定的差距，但是屏幕触摸弥补了这个问题。没有找到三指拖拽的手势，它用的是类似 Windows 的轻点两次，第二次不抬起的做法。&lt;/p&gt; &lt;p&gt;屏幕分辨率 2080 x 3120，14.2 英寸。&lt;/p&gt; &lt;p&gt;2025-06-17 推送了 5.0.1.310 SP9，SP9C00E301R9P2patch05，内核 1.9.5 2025-05-26。&lt;/p&gt; &lt;p&gt;2025-06-24 推送了 5.0.1.315 SP12，SP12C00E302R9P3patch01，内核 1.9.5 2025-06-20。&lt;/p&gt; &lt;p&gt;2025-06-30 推送了 5.0.1.315 SP17，SP17C00E302R9P3，内核 1.9.5 2025-06-24。&lt;/p&gt; &lt;h2 id=&#34;应用体验&#34;&gt;应用体验&lt;a class=&#34;headerlink&#34; href=&#34;#应用体验&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;目前（2025 年 6 月 6 日）应用商城有这些软件：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Bilibili&lt;/li&gt; &lt;li&gt;飞书&lt;/li&gt; &lt;li&gt;钉钉&lt;/li&gt; &lt;li&gt;腾讯会议&lt;/li&gt; &lt;li&gt;QQ（在应用尝鲜内）&lt;/li&gt; &lt;li&gt;CodeArts IDE（在应用尝鲜内，需要开发者模式）&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;暂时还没有微信，可以通过操控手机来发微信，但是在消息栏里按回车是换行，没找到发送按钮对应的电脑按键，需要手动操。但是居然有企业微信。&lt;/p&gt; &lt;p&gt;UPDATE: 2025-06-26 微信正式上架。&lt;/p&gt; &lt;p&gt;UPDATE: 2025-06-13 收到了微信的测试短信，可以体验了，版本是 4.0.1.30。2025-06-14 推送了 4.0.1.31 测试版本。2025-06-19 推送了 4.0.1.32 版本。&lt;/p&gt; &lt;p&gt;支持应用接续，在手机上播放的 B 站视频，可以在电脑上接续继续看。&lt;/p&gt; &lt;p&gt;期待一个功能，当电脑上出现需要扫的二维码的时候，可以通过协同功能，不用操作手机，让手机直接扫电脑的屏幕。不过反过来，如果电脑上有需要输入手机短信验证码的场景，就已经很方便了。&lt;/p&gt; &lt;p&gt;试了一下腾讯会议，声音，视频，共享屏幕都是正常工作的。但是共享的屏幕只有笔记本自己的屏幕，还不能选取共享哪个屏幕的内容，也不能选取共享哪个窗口。&lt;/p&gt; &lt;h2 id=&#34;开发者模式&#34;&gt;开发者模式&lt;a class=&#34;headerlink&#34; href=&#34;#开发者模式&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;开发者模式的打开方式和手机上一样，在设置里狂点软件版本。自带了一个 Terminal App，会提示你如何打开开发者模式。&lt;/p&gt; &lt;p&gt;打开以后就可以访问终端了。shell 是用的 toybox。df 如下：&lt;/p&gt; &lt;div class=&#34;language-shell highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-0-1&#34;&gt;&lt;a id=&#34;__codelineno-0-1&#34; name=&#34;__codelineno-0-1&#34; href=&#34;#__codelineno-0-1&#34;&gt;&lt;/a&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;df&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-h &lt;/span&gt;&lt;span id=&#34;__span-0-2&#34;&gt;&lt;a id=&#34;__codelineno-0-2&#34; name=&#34;__codelineno-0-2&#34; href=&#34;#__codelineno-0-2&#34;&gt;&lt;/a&gt;Filesystem&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Size&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Used&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Avail&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Use%&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Mounted&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;on &lt;/span&gt;&lt;span id=&#34;__span-0-3&#34;&gt;&lt;a id=&#34;__codelineno-0-3&#34; name=&#34;__codelineno-0-3&#34; href=&#34;#__codelineno-0-3&#34;&gt;&lt;/a&gt;tmpfs&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;16G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;52K&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;16G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;%&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/ &lt;/span&gt;&lt;span id=&#34;__span-0-4&#34;&gt;&lt;a id=&#34;__codelineno-0-4&#34; name=&#34;__codelineno-0-4&#34; href=&#34;#__codelineno-0-4&#34;&gt;&lt;/a&gt;tmpfs&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;16G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;16G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;%&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/storage/hmdfs &lt;/span&gt;&lt;span id=&#34;__span-0-5&#34;&gt;&lt;a id=&#34;__codelineno-0-5&#34; name=&#34;__codelineno-0-5&#34; href=&#34;#__codelineno-0-5&#34;&gt;&lt;/a&gt;/dev/block/dm-4&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;.7M&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;.7M&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;%&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/cust &lt;/span&gt;&lt;span id=&#34;__span-0-6&#34;&gt;&lt;a id=&#34;__codelineno-0-6&#34; name=&#34;__codelineno-0-6&#34; href=&#34;#__codelineno-0-6&#34;&gt;&lt;/a&gt;/dev/block/dm-6&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;.1G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;.1G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;%&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/preload &lt;/span&gt;&lt;span id=&#34;__span-0-7&#34;&gt;&lt;a id=&#34;__codelineno-0-7&#34; name=&#34;__codelineno-0-7&#34; href=&#34;#__codelineno-0-7&#34;&gt;&lt;/a&gt;/dev/block/dm-0&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;.0G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;.0G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;%&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/system/variant &lt;/span&gt;&lt;span id=&#34;__span-0-8&#34;&gt;&lt;a id=&#34;__codelineno-0-8&#34; name=&#34;__codelineno-0-8&#34; href=&#34;#__codelineno-0-8&#34;&gt;&lt;/a&gt;/dev/block/dm-5&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;.0K&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;.0K&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;%&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/version &lt;/span&gt;&lt;span id=&#34;__span-0-9&#34;&gt;&lt;a id=&#34;__codelineno-0-9&#34; name=&#34;__codelineno-0-9&#34; href=&#34;#__codelineno-0-9&#34;&gt;&lt;/a&gt;/dev/block/platform/b0000000.hi_pcie/by-name/userdata&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;928G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;59G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;869G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;7&lt;/span&gt;%&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/data/service/hnp &lt;/span&gt;&lt;span id=&#34;__span-0-10&#34;&gt;&lt;a id=&#34;__codelineno-0-10&#34; name=&#34;__codelineno-0-10&#34; href=&#34;#__codelineno-0-10&#34;&gt;&lt;/a&gt;tmpfs&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;16G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;16G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;%&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/module_update &lt;/span&gt;&lt;span id=&#34;__span-0-11&#34;&gt;&lt;a id=&#34;__codelineno-0-11&#34; name=&#34;__codelineno-0-11&#34; href=&#34;#__codelineno-0-11&#34;&gt;&lt;/a&gt;/dev/block/dm-2&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;9&lt;/span&gt;.3G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;.1G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;.1G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;88&lt;/span&gt;%&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/sys_prod &lt;/span&gt;&lt;span id=&#34;__span-0-12&#34;&gt;&lt;a id=&#34;__codelineno-0-12&#34; name=&#34;__codelineno-0-12&#34; href=&#34;#__codelineno-0-12&#34;&gt;&lt;/a&gt;devfs&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;15G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;104M&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;15G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;%&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/dev &lt;/span&gt;&lt;span id=&#34;__span-0-13&#34;&gt;&lt;a id=&#34;__codelineno-0-13&#34; name=&#34;__codelineno-0-13&#34; href=&#34;#__codelineno-0-13&#34;&gt;&lt;/a&gt;/data/service/el2/100/hmdfs/non_account&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;928G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;59G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;869G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;7&lt;/span&gt;%&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/mnt/hmdfs/100/non_account &lt;/span&gt;&lt;span id=&#34;__span-0-14&#34;&gt;&lt;a id=&#34;__codelineno-0-14&#34; name=&#34;__codelineno-0-14&#34; href=&#34;#__codelineno-0-14&#34;&gt;&lt;/a&gt;/dev/block/loop0&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;114M&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;112M&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;%&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/module_update/ArkWebCore &lt;/span&gt;&lt;span id=&#34;__span-0-15&#34;&gt;&lt;a id=&#34;__codelineno-0-15&#34; name=&#34;__codelineno-0-15&#34; href=&#34;#__codelineno-0-15&#34;&gt;&lt;/a&gt;tmpfs&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;.0G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;608K&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;.9G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;%&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/dev/shm &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;查看 &lt;a href=&#34;../../../../huawei-matebook-pro-cpuinfo.txt&#34;&gt;&lt;code&gt;/proc/cpuinfo&lt;/code&gt;&lt;/a&gt;。四个 0xd42（2.0 GHz），八个 0xd43（2.0 GHz），八个 0xd03（2.3 GHz），共 20 个逻辑核。从 part id 来看，0xd03 和 0xd42 对应麒麟 9010 的大核和中核，但 0xd43 是新的 part id。&lt;/p&gt; &lt;p&gt;使用 &lt;a href=&#34;https://github.com/jiegec/SPECCPU2017Harmony&#34;&gt;https://github.com/jiegec/SPECCPU2017Harmony&lt;/a&gt; 性能测试：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;X90 P-Core 2.3 GHz 0xd03 Full: INT 4.87 FP 7.42&lt;/li&gt; &lt;li&gt;X90 E-Core 2.0 GHz 0xd43 Full: INT 4.28 FP 6.52&lt;/li&gt; &lt;li&gt;X90 LPE-Core 2.0 GHz 0xd42 Full: INT 3.25 FP TODO&lt;/li&gt; &lt;li&gt;9010 P-Core 2.3 GHz 0xd03 Best: INT 4.18 FP 6.22&lt;/li&gt; &lt;li&gt;9010 P-Core 2.3 GHz 0xd03 Full: INT 3.96 FP 5.86&lt;/li&gt; &lt;li&gt;9010 E-Core 2.2 GHz 0xd42 Full: INT 3.21 FP 4.72&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;详细数据： &lt;a href=&#34;https://github.com/jiegec/SPECCPU2017Harmony/tree/master/results&#34;&gt;https://github.com/jiegec/SPECCPU2017Harmony/tree/master/results&lt;/a&gt;。Best 代表每一项单独跑，散热条件好，Full 代表顺着跑一遍，散热条件差。由于编译器和编译选项不同，不能和在其他平台上跑的 SPEC CPU 2017 成绩直接对比，仅供参考。&lt;/p&gt; &lt;p&gt;大概性能排序：X90 P-Core &amp;gt; X90 E-Core &amp;gt; 9010 P-Core &amp;gt; X90 LPE-Core &amp;gt; 9010 E-Core &amp;gt; 9010 LPE-Core。&lt;/p&gt; &lt;p&gt;即使是同样的 2.3 GHz 0xd03 的核，X90 比 9010 快上 20%：可能是散热问题，或者缓存大小和内存带宽的问题，或许连微架构都是不一样的，这些都需要后续进一步测试。而 X90 的中核也比 9010 的大核要快。&lt;/p&gt; &lt;h3 id=&#34;codearts-ide&#34;&gt;CodeArts IDE&lt;a class=&#34;headerlink&#34; href=&#34;#codearts-ide&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;试了一下从应用商城安装的 CodeArts IDE，显示支持 Java 和 Python 开发，UI 上有点像 JetBrains，但应该是基于 VSCode 做的二次开发。实际测了一下，用它创建 Python 项目后，可以在 CodeArts IDE 的命令行里用 Python3：&lt;/p&gt; &lt;div class=&#34;language-shell highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-1-1&#34;&gt;&lt;a id=&#34;__codelineno-1-1&#34; name=&#34;__codelineno-1-1&#34; href=&#34;#__codelineno-1-1&#34;&gt;&lt;/a&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;pwd&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-2&#34;&gt;&lt;a id=&#34;__codelineno-1-2&#34; name=&#34;__codelineno-1-2&#34; href=&#34;#__codelineno-1-2&#34;&gt;&lt;/a&gt;/storage/Users/currentUser/IDEProjects/pythonProject &lt;/span&gt;&lt;span id=&#34;__span-1-3&#34;&gt;&lt;a id=&#34;__codelineno-1-3&#34; name=&#34;__codelineno-1-3&#34; href=&#34;#__codelineno-1-3&#34;&gt;&lt;/a&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;python3&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main.py &lt;/span&gt;&lt;span id=&#34;__span-1-4&#34;&gt;&lt;a id=&#34;__codelineno-1-4&#34; name=&#34;__codelineno-1-4&#34; href=&#34;#__codelineno-1-4&#34;&gt;&lt;/a&gt;Hello&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;World! &lt;/span&gt;&lt;span id=&#34;__span-1-5&#34;&gt;&lt;a id=&#34;__codelineno-1-5&#34; name=&#34;__codelineno-1-5&#34; href=&#34;#__codelineno-1-5&#34;&gt;&lt;/a&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;which&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;python3 &lt;/span&gt;&lt;span id=&#34;__span-1-6&#34;&gt;&lt;a id=&#34;__codelineno-1-6&#34; name=&#34;__codelineno-1-6&#34; href=&#34;#__codelineno-1-6&#34;&gt;&lt;/a&gt;/storage/Users/currentUser/IDEProjects/pythonProject/venv/bin/python3o &lt;/span&gt;&lt;span id=&#34;__span-1-7&#34;&gt;&lt;a id=&#34;__codelineno-1-7&#34; name=&#34;__codelineno-1-7&#34; href=&#34;#__codelineno-1-7&#34;&gt;&lt;/a&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;/data/app/bin/python&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--version &lt;/span&gt;&lt;span id=&#34;__span-1-8&#34;&gt;&lt;a id=&#34;__codelineno-1-8&#34; name=&#34;__codelineno-1-8&#34; href=&#34;#__codelineno-1-8&#34;&gt;&lt;/a&gt;Python&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;.12.5 &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;这里的 &lt;code&gt;/storage/Users/currentUser/&lt;/code&gt; 就是 HOME 目录，对应文件管理器的个人目录。&lt;/p&gt; &lt;p&gt;看了看 &lt;code&gt;/data/app/bin&lt;/code&gt; 目录，下面有 git，python，unzip, vi，rg，java（bisheng jdk 8/17），ssh，electron（用来跑 LSP！）等等。&lt;/p&gt; &lt;p&gt;试了试 pip，也是工作的：&lt;/p&gt; &lt;div class=&#34;language-shell highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-2-1&#34;&gt;&lt;a id=&#34;__codelineno-2-1&#34; name=&#34;__codelineno-2-1&#34; href=&#34;#__codelineno-2-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;venv&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;python3&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-m&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;pip&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;install&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;requests &lt;/span&gt;&lt;span id=&#34;__span-2-2&#34;&gt;&lt;a id=&#34;__codelineno-2-2&#34; name=&#34;__codelineno-2-2&#34; href=&#34;#__codelineno-2-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;venv&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;python3 &lt;/span&gt;&lt;span id=&#34;__span-2-3&#34;&gt;&lt;a id=&#34;__codelineno-2-3&#34; name=&#34;__codelineno-2-3&#34; href=&#34;#__codelineno-2-3&#34;&gt;&lt;/a&gt;Python&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;.12.5&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;main,&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Aug&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;28&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2024&lt;/span&gt;,&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;01&lt;/span&gt;:18:17&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;Clang&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;15&lt;/span&gt;.0.4&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;llvm-project&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;81cdec3cd117b1e6e3a9f1ebc4695d790c978463&lt;span class=&#34;o&#34;&gt;)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;on&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;linux &lt;/span&gt;&lt;span id=&#34;__span-2-4&#34;&gt;&lt;a id=&#34;__codelineno-2-4&#34; name=&#34;__codelineno-2-4&#34; href=&#34;#__codelineno-2-4&#34;&gt;&lt;/a&gt;Type&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;help&amp;quot;&lt;/span&gt;,&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;copyright&amp;quot;&lt;/span&gt;,&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;credits&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;or&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;license&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;more&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;information. &lt;/span&gt;&lt;span id=&#34;__span-2-5&#34;&gt;&lt;a id=&#34;__codelineno-2-5&#34; name=&#34;__codelineno-2-5&#34; href=&#34;#__codelineno-2-5&#34;&gt;&lt;/a&gt;&amp;gt;&amp;gt;&amp;gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;import&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;requests &lt;/span&gt;&lt;span id=&#34;__span-2-6&#34;&gt;&lt;a id=&#34;__codelineno-2-6&#34; name=&#34;__codelineno-2-6&#34; href=&#34;#__codelineno-2-6&#34;&gt;&lt;/a&gt;&amp;gt;&amp;gt;&amp;gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;requests.get&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;https://github.com&amp;quot;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;.status_code &lt;/span&gt;&lt;span id=&#34;__span-2-7&#34;&gt;&lt;a id=&#34;__codelineno-2-7&#34; name=&#34;__codelineno-2-7&#34; href=&#34;#__codelineno-2-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;m&#34;&gt;200&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-8&#34;&gt;&lt;a id=&#34;__codelineno-2-8&#34; name=&#34;__codelineno-2-8&#34; href=&#34;#__codelineno-2-8&#34;&gt;&lt;/a&gt;&amp;gt;&amp;gt;&amp;gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;需要 native 编译的库，比如 numpy 还不行，会提示找不到 make。&lt;/p&gt; &lt;p&gt;终端里的 ssh 是可以用的，实测 ssh 到远程的 linux 上是没问题的。&lt;/p&gt; &lt;p&gt;终端里的括号补全有一些问题，等待修复。CodeArts IDE 的 Python 单步调试功能也是工作的。&lt;/p&gt; &lt;p&gt;似乎没有安装 Remote 开发的插件，也没有安装插件的菜单。&lt;/p&gt; &lt;p&gt;既然可以跑 shell，意味着可以 execve 了，意味着可以做 termux 的类似物了。期待鸿蒙 5 上早日有 Termux 用，直接跑 Linux 发行版。实际测了一下，Popen 确实是工作的。&lt;/p&gt; &lt;p&gt;UPDATE: 开了个坑：&lt;a href=&#34;https://github.com/jiegec/Termony&#34;&gt;https://github.com/jiegec/Termony&lt;/a&gt;，目前已经能跑很多命令了，包括在鸿蒙电脑上编译 C/C++ 代码。&lt;/p&gt; &lt;p&gt;试了一下 HOME 目录，发现它里面不能有可执行的文件，所以可能还是得打包到一个 App 里面，通过 &lt;code&gt;/data/app/bin&lt;/code&gt; 类似的路径来访问。&lt;/p&gt; &lt;p&gt;在 CodeArts IDE 里，可以访问 /data/storage/el1/bundle 目录，里面有一个 pc_entry.hap 文件，可以通过 &lt;code&gt;cat /data/storage/el1/bundle/pc_entry.hap | ssh hostname &#34;cat - &amp;gt; pc_entry.hap&#34;&lt;/code&gt; 拷贝到其他机器上。这个文件有 1.9GB，可以看到在 &lt;code&gt;/data/app&lt;/code&gt; 下面的各种文件，其实是来自于这个 &lt;code&gt;pc_entry.hap&lt;/code&gt; 的 &lt;code&gt;hnp/arm64-v8a&lt;/code&gt; 下面的一系列文件，例如 &lt;code&gt;git.hnp&lt;/code&gt; 就是一个 zip 压缩包，里面就是 &lt;code&gt;/data/app/git.org/git_1.2&lt;/code&gt; 目录的内容，这个东西叫做 &lt;code&gt;应用包内 Native 包（.hnp）&lt;/code&gt;。这些文件在 module.json 里声明，对应 &lt;a href=&#34;https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/module-configuration-file#hnppackages%E6%A0%87%E7%AD%BE&#34;&gt;hnpPackages 标签&lt;/a&gt;：&lt;/p&gt; &lt;div class=&#34;language-json highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-3-1&#34;&gt;&lt;a id=&#34;__codelineno-3-1&#34; name=&#34;__codelineno-3-1&#34; href=&#34;#__codelineno-3-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-2&#34;&gt;&lt;a id=&#34;__codelineno-3-2&#34; name=&#34;__codelineno-3-2&#34; href=&#34;#__codelineno-3-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;module&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-3&#34;&gt;&lt;a id=&#34;__codelineno-3-3&#34; name=&#34;__codelineno-3-3&#34; href=&#34;#__codelineno-3-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;hnpPackages&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-4&#34;&gt;&lt;a id=&#34;__codelineno-3-4&#34; name=&#34;__codelineno-3-4&#34; href=&#34;#__codelineno-3-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-5&#34;&gt;&lt;a id=&#34;__codelineno-3-5&#34; name=&#34;__codelineno-3-5&#34; href=&#34;#__codelineno-3-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;package&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;electron.hnp&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-6&#34;&gt;&lt;a id=&#34;__codelineno-3-6&#34; name=&#34;__codelineno-3-6&#34; href=&#34;#__codelineno-3-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;private&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-7&#34;&gt;&lt;a id=&#34;__codelineno-3-7&#34; name=&#34;__codelineno-3-7&#34; href=&#34;#__codelineno-3-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-8&#34;&gt;&lt;a id=&#34;__codelineno-3-8&#34; name=&#34;__codelineno-3-8&#34; href=&#34;#__codelineno-3-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-9&#34;&gt;&lt;a id=&#34;__codelineno-3-9&#34; name=&#34;__codelineno-3-9&#34; href=&#34;#__codelineno-3-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;package&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;huaweicloud-smartassist-java-ls.hnp&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-10&#34;&gt;&lt;a id=&#34;__codelineno-3-10&#34; name=&#34;__codelineno-3-10&#34; href=&#34;#__codelineno-3-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;private&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-11&#34;&gt;&lt;a id=&#34;__codelineno-3-11&#34; name=&#34;__codelineno-3-11&#34; href=&#34;#__codelineno-3-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-12&#34;&gt;&lt;a id=&#34;__codelineno-3-12&#34; name=&#34;__codelineno-3-12&#34; href=&#34;#__codelineno-3-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-13&#34;&gt;&lt;a id=&#34;__codelineno-3-13&#34; name=&#34;__codelineno-3-13&#34; href=&#34;#__codelineno-3-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;package&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;bishengjdk8.hnp&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-14&#34;&gt;&lt;a id=&#34;__codelineno-3-14&#34; name=&#34;__codelineno-3-14&#34; href=&#34;#__codelineno-3-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;private&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-15&#34;&gt;&lt;a id=&#34;__codelineno-3-15&#34; name=&#34;__codelineno-3-15&#34; href=&#34;#__codelineno-3-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-16&#34;&gt;&lt;a id=&#34;__codelineno-3-16&#34; name=&#34;__codelineno-3-16&#34; href=&#34;#__codelineno-3-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-17&#34;&gt;&lt;a id=&#34;__codelineno-3-17&#34; name=&#34;__codelineno-3-17&#34; href=&#34;#__codelineno-3-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;package&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;rg.hnp&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-18&#34;&gt;&lt;a id=&#34;__codelineno-3-18&#34; name=&#34;__codelineno-3-18&#34; href=&#34;#__codelineno-3-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;private&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-19&#34;&gt;&lt;a id=&#34;__codelineno-3-19&#34; name=&#34;__codelineno-3-19&#34; href=&#34;#__codelineno-3-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-20&#34;&gt;&lt;a id=&#34;__codelineno-3-20&#34; name=&#34;__codelineno-3-20&#34; href=&#34;#__codelineno-3-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-21&#34;&gt;&lt;a id=&#34;__codelineno-3-21&#34; name=&#34;__codelineno-3-21&#34; href=&#34;#__codelineno-3-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;package&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;unzip.hnp&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-22&#34;&gt;&lt;a id=&#34;__codelineno-3-22&#34; name=&#34;__codelineno-3-22&#34; href=&#34;#__codelineno-3-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;private&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-23&#34;&gt;&lt;a id=&#34;__codelineno-3-23&#34; name=&#34;__codelineno-3-23&#34; href=&#34;#__codelineno-3-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-24&#34;&gt;&lt;a id=&#34;__codelineno-3-24&#34; name=&#34;__codelineno-3-24&#34; href=&#34;#__codelineno-3-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-25&#34;&gt;&lt;a id=&#34;__codelineno-3-25&#34; name=&#34;__codelineno-3-25&#34; href=&#34;#__codelineno-3-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;package&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;git.hnp&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-26&#34;&gt;&lt;a id=&#34;__codelineno-3-26&#34; name=&#34;__codelineno-3-26&#34; href=&#34;#__codelineno-3-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;private&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-27&#34;&gt;&lt;a id=&#34;__codelineno-3-27&#34; name=&#34;__codelineno-3-27&#34; href=&#34;#__codelineno-3-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-28&#34;&gt;&lt;a id=&#34;__codelineno-3-28&#34; name=&#34;__codelineno-3-28&#34; href=&#34;#__codelineno-3-28&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-29&#34;&gt;&lt;a id=&#34;__codelineno-3-29&#34; name=&#34;__codelineno-3-29&#34; href=&#34;#__codelineno-3-29&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;package&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;bishengjdk17.hnp&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-30&#34;&gt;&lt;a id=&#34;__codelineno-3-30&#34; name=&#34;__codelineno-3-30&#34; href=&#34;#__codelineno-3-30&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;private&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-31&#34;&gt;&lt;a id=&#34;__codelineno-3-31&#34; name=&#34;__codelineno-3-31&#34; href=&#34;#__codelineno-3-31&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-32&#34;&gt;&lt;a id=&#34;__codelineno-3-32&#34; name=&#34;__codelineno-3-32&#34; href=&#34;#__codelineno-3-32&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-33&#34;&gt;&lt;a id=&#34;__codelineno-3-33&#34; name=&#34;__codelineno-3-33&#34; href=&#34;#__codelineno-3-33&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;package&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;python.hnp&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-34&#34;&gt;&lt;a id=&#34;__codelineno-3-34&#34; name=&#34;__codelineno-3-34&#34; href=&#34;#__codelineno-3-34&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;private&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-35&#34;&gt;&lt;a id=&#34;__codelineno-3-35&#34; name=&#34;__codelineno-3-35&#34; href=&#34;#__codelineno-3-35&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-36&#34;&gt;&lt;a id=&#34;__codelineno-3-36&#34; name=&#34;__codelineno-3-36&#34; href=&#34;#__codelineno-3-36&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-37&#34;&gt;&lt;a id=&#34;__codelineno-3-37&#34; name=&#34;__codelineno-3-37&#34; href=&#34;#__codelineno-3-37&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;pc_entry&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-38&#34;&gt;&lt;a id=&#34;__codelineno-3-38&#34; name=&#34;__codelineno-3-38&#34; href=&#34;#__codelineno-3-38&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;packageName&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;pc_entry&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-39&#34;&gt;&lt;a id=&#34;__codelineno-3-39&#34; name=&#34;__codelineno-3-39&#34; href=&#34;#__codelineno-3-39&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-40&#34;&gt;&lt;a id=&#34;__codelineno-3-40&#34; name=&#34;__codelineno-3-40&#34; href=&#34;#__codelineno-3-40&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;解压 &lt;code&gt;git.hnp&lt;/code&gt; 后，里面的文件会被复制到 &lt;code&gt;/data/app/git.org/git_1.2&lt;/code&gt; 目录下，然后有一个 &lt;code&gt;hnp.json&lt;/code&gt; 指定了在 &lt;code&gt;/data/app/bin&lt;/code&gt; 创建哪些文件的软连接，比如：&lt;/p&gt; &lt;div class=&#34;language-json highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-4-1&#34;&gt;&lt;a id=&#34;__codelineno-4-1&#34; name=&#34;__codelineno-4-1&#34; href=&#34;#__codelineno-4-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-2&#34;&gt;&lt;a id=&#34;__codelineno-4-2&#34; name=&#34;__codelineno-4-2&#34; href=&#34;#__codelineno-4-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;install&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-3&#34;&gt;&lt;a id=&#34;__codelineno-4-3&#34; name=&#34;__codelineno-4-3&#34; href=&#34;#__codelineno-4-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;links&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-4&#34;&gt;&lt;a id=&#34;__codelineno-4-4&#34; name=&#34;__codelineno-4-4&#34; href=&#34;#__codelineno-4-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-5&#34;&gt;&lt;a id=&#34;__codelineno-4-5&#34; name=&#34;__codelineno-4-5&#34; href=&#34;#__codelineno-4-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;source&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;bin/expr&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-6&#34;&gt;&lt;a id=&#34;__codelineno-4-6&#34; name=&#34;__codelineno-4-6&#34; href=&#34;#__codelineno-4-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;target&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;expr&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-7&#34;&gt;&lt;a id=&#34;__codelineno-4-7&#34; name=&#34;__codelineno-4-7&#34; href=&#34;#__codelineno-4-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-8&#34;&gt;&lt;a id=&#34;__codelineno-4-8&#34; name=&#34;__codelineno-4-8&#34; href=&#34;#__codelineno-4-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-9&#34;&gt;&lt;a id=&#34;__codelineno-4-9&#34; name=&#34;__codelineno-4-9&#34; href=&#34;#__codelineno-4-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;source&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;bin/git&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-10&#34;&gt;&lt;a id=&#34;__codelineno-4-10&#34; name=&#34;__codelineno-4-10&#34; href=&#34;#__codelineno-4-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;target&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;git&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-11&#34;&gt;&lt;a id=&#34;__codelineno-4-11&#34; name=&#34;__codelineno-4-11&#34; href=&#34;#__codelineno-4-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-12&#34;&gt;&lt;a id=&#34;__codelineno-4-12&#34; name=&#34;__codelineno-4-12&#34; href=&#34;#__codelineno-4-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-13&#34;&gt;&lt;a id=&#34;__codelineno-4-13&#34; name=&#34;__codelineno-4-13&#34; href=&#34;#__codelineno-4-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-14&#34;&gt;&lt;a id=&#34;__codelineno-4-14&#34; name=&#34;__codelineno-4-14&#34; href=&#34;#__codelineno-4-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;git&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-15&#34;&gt;&lt;a id=&#34;__codelineno-4-15&#34; name=&#34;__codelineno-4-15&#34; href=&#34;#__codelineno-4-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;hnp-config&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-16&#34;&gt;&lt;a id=&#34;__codelineno-4-16&#34; name=&#34;__codelineno-4-16&#34; href=&#34;#__codelineno-4-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;quot;version&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;1.2&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-17&#34;&gt;&lt;a id=&#34;__codelineno-4-17&#34; name=&#34;__codelineno-4-17&#34; href=&#34;#__codelineno-4-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;在 HarmonyOS SDK 里，有一个 hnpcli，可以用来生成 .hnp 文件。&lt;/p&gt; &lt;p&gt;除此之外，就是 VSCode 加各种插件了。&lt;/p&gt; &lt;p&gt;鸿蒙电脑上，可以访问各个 App 的内部目录了，无论是自带的文件浏览器，还是通过 DevEco Studio。这给调试带来了很多便利。&lt;/p&gt; &lt;p&gt;UPDATE: 2025-06-21 推送了 1.0.3 版本。实测在 shell 里面输入括号，不会出现括号补全跑到错误的位置的问题了。&lt;/p&gt; &lt;p&gt;UPDATE: 2025-12-01 尝试 CodeArts 1.0.9 版本，可以创建 C++ 项目了，编译没问题并且有自签名的提示，但是执行编译出来的程序还是会报错，估计还是自签名的机制还有问题。&lt;/p&gt; &lt;p&gt;UPDATE: 2025-12-11 经 @w12101111 群友提醒，在设置-&amp;gt;隐私和安全-&amp;gt;高级-&amp;gt;勾选运行外部来源的扩展程序之后，就可以在 CodeArts IDE 里运行和调试编译出来的 C++ 程序了。至此，鸿蒙电脑自己运行自己编译的 ELF 已经是可行的了。&lt;/p&gt; &lt;h3 id=&#34;deveco-studio&#34;&gt;DevEco Studio&lt;a class=&#34;headerlink&#34; href=&#34;#deveco-studio&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;2025-12-01 拿到了 DevEco Studio 的内测资格（直接网上申请即可），测试了一下 DevEco Studio 6.0.5.220 鸿蒙预览版。目前能够构建 hap，并且安装在鸿蒙电脑上，通过 USB 连接鸿蒙手机也可以正常安装。&lt;/p&gt; &lt;h2 id=&#34;虚拟机&#34;&gt;虚拟机&lt;a class=&#34;headerlink&#34; href=&#34;#虚拟机&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;目前应用商城有两家虚拟机：Oseasy 和铠大师。两者都是提示安装 ARM64 版本的 Windows，尝试了一下给它一个 Debian 的安装 ISO，它不认。用的 unattended install，不需要进行什么操作。Oseasy 和铠大师的虚拟机不能同时开，但是可以一边安装完，再去安装另一边的 Windows。&lt;/p&gt; &lt;p&gt;试了试在虚拟机里装 WSL，说没有硬件虚拟化，大概是没有打开嵌套虚拟化的功能。&lt;/p&gt; &lt;p&gt;在 6 核 Oseasy 虚拟机里运行 ARM64 Geekbench 6：&lt;a href=&#34;https://browser.geekbench.com/v6/cpu/12309313&#34;&gt;Single-Core 1436, Multi-Core 5296&lt;/a&gt;。Oseasy 8 核：&lt;a href=&#34;https://browser.geekbench.com/v6/cpu/12309427&#34;&gt;Single-Core 1462, Multi-Core 7043&lt;/a&gt;。算上剩下的 12 个逻辑核，考虑虚拟化的开销，多核分数达到网传的 11640 分，感觉是可能的。&lt;/p&gt; &lt;p&gt;Oseasy 虚拟机只允许开到 8 个核心，实测下来，会优先调度到 0xD03 的八个逻辑核中其中四个逻辑核（不同时用一个物理核的两个逻辑核），之后再调度到 0xD43 的八个逻辑核中的四个逻辑核（也不同时用同一个物理核的两个逻辑核）。在 Oseasy 虚拟机里看到的 CPU 信息是 Cortex-A53，没有正确暴露外面的处理器信息，从 cpuinfo 来看，也没有暴露 SVE。&lt;/p&gt; &lt;p&gt;UPDATE: 能跑 Linux 了，见 &lt;a href=&#34;../../10/linux-vm-on-harmonyos-computer/&#34;&gt;在鸿蒙电脑上的虚拟机内启动 Linux&lt;/a&gt;。&lt;/p&gt; &lt;h2 id=&#34;外设&#34;&gt;外设&lt;a class=&#34;headerlink&#34; href=&#34;#外设&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;把 Type-C Hub 接到 MateBook Pro 上，显示器，键盘鼠标都正常工作了。&lt;/p&gt; &lt;h2 id=&#34;侧载&#34;&gt;侧载&lt;a class=&#34;headerlink&#34; href=&#34;#侧载&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;打开开发者模式后，在设置里，可以打开 USB 调试：把电脑右边的 USB Type-C 接到另一台电脑上，就可以用 hdc 连接了。&lt;/p&gt; &lt;p&gt;然后给自己的项目加上 2in1 的 device type：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-5-1&#34;&gt;&lt;a id=&#34;__codelineno-5-1&#34; name=&#34;__codelineno-5-1&#34; href=&#34;#__codelineno-5-1&#34;&gt;&lt;/a&gt;diff --git a/entry/build-profile.json5 b/entry/build-profile.json5 &lt;/span&gt;&lt;span id=&#34;__span-5-2&#34;&gt;&lt;a id=&#34;__codelineno-5-2&#34; name=&#34;__codelineno-5-2&#34; href=&#34;#__codelineno-5-2&#34;&gt;&lt;/a&gt;index 38bdcc9..ad6fd45 100644 &lt;/span&gt;&lt;span id=&#34;__span-5-3&#34;&gt;&lt;a id=&#34;__codelineno-5-3&#34; name=&#34;__codelineno-5-3&#34; href=&#34;#__codelineno-5-3&#34;&gt;&lt;/a&gt;--- a/entry/build-profile.json5 &lt;/span&gt;&lt;span id=&#34;__span-5-4&#34;&gt;&lt;a id=&#34;__codelineno-5-4&#34; name=&#34;__codelineno-5-4&#34; href=&#34;#__codelineno-5-4&#34;&gt;&lt;/a&gt;+++ b/entry/build-profile.json5 &lt;/span&gt;&lt;span id=&#34;__span-5-5&#34;&gt;&lt;a id=&#34;__codelineno-5-5&#34; name=&#34;__codelineno-5-5&#34; href=&#34;#__codelineno-5-5&#34;&gt;&lt;/a&gt;@@ -30,7 +30,13 @@ &lt;/span&gt;&lt;span id=&#34;__span-5-6&#34;&gt;&lt;a id=&#34;__codelineno-5-6&#34; name=&#34;__codelineno-5-6&#34; href=&#34;#__codelineno-5-6&#34;&gt;&lt;/a&gt; ], &lt;/span&gt;&lt;span id=&#34;__span-5-7&#34;&gt;&lt;a id=&#34;__codelineno-5-7&#34; name=&#34;__codelineno-5-7&#34; href=&#34;#__codelineno-5-7&#34;&gt;&lt;/a&gt; &amp;quot;targets&amp;quot;: [ &lt;/span&gt;&lt;span id=&#34;__span-5-8&#34;&gt;&lt;a id=&#34;__codelineno-5-8&#34; name=&#34;__codelineno-5-8&#34; href=&#34;#__codelineno-5-8&#34;&gt;&lt;/a&gt; { &lt;/span&gt;&lt;span id=&#34;__span-5-9&#34;&gt;&lt;a id=&#34;__codelineno-5-9&#34; name=&#34;__codelineno-5-9&#34; href=&#34;#__codelineno-5-9&#34;&gt;&lt;/a&gt;- &amp;quot;name&amp;quot;: &amp;quot;default&amp;quot; &lt;/span&gt;&lt;span id=&#34;__span-5-10&#34;&gt;&lt;a id=&#34;__codelineno-5-10&#34; name=&#34;__codelineno-5-10&#34; href=&#34;#__codelineno-5-10&#34;&gt;&lt;/a&gt;+ &amp;quot;name&amp;quot;: &amp;quot;default&amp;quot;, &lt;/span&gt;&lt;span id=&#34;__span-5-11&#34;&gt;&lt;a id=&#34;__codelineno-5-11&#34; name=&#34;__codelineno-5-11&#34; href=&#34;#__codelineno-5-11&#34;&gt;&lt;/a&gt;+ &amp;quot;config&amp;quot;: { &lt;/span&gt;&lt;span id=&#34;__span-5-12&#34;&gt;&lt;a id=&#34;__codelineno-5-12&#34; name=&#34;__codelineno-5-12&#34; href=&#34;#__codelineno-5-12&#34;&gt;&lt;/a&gt;+ &amp;quot;deviceType&amp;quot;: [ &lt;/span&gt;&lt;span id=&#34;__span-5-13&#34;&gt;&lt;a id=&#34;__codelineno-5-13&#34; name=&#34;__codelineno-5-13&#34; href=&#34;#__codelineno-5-13&#34;&gt;&lt;/a&gt;+ &amp;quot;default&amp;quot;, &lt;/span&gt;&lt;span id=&#34;__span-5-14&#34;&gt;&lt;a id=&#34;__codelineno-5-14&#34; name=&#34;__codelineno-5-14&#34; href=&#34;#__codelineno-5-14&#34;&gt;&lt;/a&gt;+ &amp;quot;2in1&amp;quot; &lt;/span&gt;&lt;span id=&#34;__span-5-15&#34;&gt;&lt;a id=&#34;__codelineno-5-15&#34; name=&#34;__codelineno-5-15&#34; href=&#34;#__codelineno-5-15&#34;&gt;&lt;/a&gt;+ ] &lt;/span&gt;&lt;span id=&#34;__span-5-16&#34;&gt;&lt;a id=&#34;__codelineno-5-16&#34; name=&#34;__codelineno-5-16&#34; href=&#34;#__codelineno-5-16&#34;&gt;&lt;/a&gt;+ } &lt;/span&gt;&lt;span id=&#34;__span-5-17&#34;&gt;&lt;a id=&#34;__codelineno-5-17&#34; name=&#34;__codelineno-5-17&#34; href=&#34;#__codelineno-5-17&#34;&gt;&lt;/a&gt; }, &lt;/span&gt;&lt;span id=&#34;__span-5-18&#34;&gt;&lt;a id=&#34;__codelineno-5-18&#34; name=&#34;__codelineno-5-18&#34; href=&#34;#__codelineno-5-18&#34;&gt;&lt;/a&gt; { &lt;/span&gt;&lt;span id=&#34;__span-5-19&#34;&gt;&lt;a id=&#34;__codelineno-5-19&#34; name=&#34;__codelineno-5-19&#34; href=&#34;#__codelineno-5-19&#34;&gt;&lt;/a&gt; &amp;quot;name&amp;quot;: &amp;quot;ohosTest&amp;quot;, &lt;/span&gt;&lt;span id=&#34;__span-5-20&#34;&gt;&lt;a id=&#34;__codelineno-5-20&#34; name=&#34;__codelineno-5-20&#34; href=&#34;#__codelineno-5-20&#34;&gt;&lt;/a&gt;diff --git a/entry/src/main/module.json5 b/entry/src/main/module.json5 &lt;/span&gt;&lt;span id=&#34;__span-5-21&#34;&gt;&lt;a id=&#34;__codelineno-5-21&#34; name=&#34;__codelineno-5-21&#34; href=&#34;#__codelineno-5-21&#34;&gt;&lt;/a&gt;index 7b8532f..76c009c 100644 &lt;/span&gt;&lt;span id=&#34;__span-5-22&#34;&gt;&lt;a id=&#34;__codelineno-5-22&#34; name=&#34;__codelineno-5-22&#34; href=&#34;#__codelineno-5-22&#34;&gt;&lt;/a&gt;--- a/entry/src/main/module.json5 &lt;/span&gt;&lt;span id=&#34;__span-5-23&#34;&gt;&lt;a id=&#34;__codelineno-5-23&#34; name=&#34;__codelineno-5-23&#34; href=&#34;#__codelineno-5-23&#34;&gt;&lt;/a&gt;+++ b/entry/src/main/module.json5 &lt;/span&gt;&lt;span id=&#34;__span-5-24&#34;&gt;&lt;a id=&#34;__codelineno-5-24&#34; name=&#34;__codelineno-5-24&#34; href=&#34;#__codelineno-5-24&#34;&gt;&lt;/a&gt;@@ -5,7 +5,8 @@ &lt;/span&gt;&lt;span id=&#34;__span-5-25&#34;&gt;&lt;a id=&#34;__codelineno-5-25&#34; name=&#34;__codelineno-5-25&#34; href=&#34;#__codelineno-5-25&#34;&gt;&lt;/a&gt; &amp;quot;description&amp;quot;: &amp;quot;$string:module_desc&amp;quot;, &lt;/span&gt;&lt;span id=&#34;__span-5-26&#34;&gt;&lt;a id=&#34;__codelineno-5-26&#34; name=&#34;__codelineno-5-26&#34; href=&#34;#__codelineno-5-26&#34;&gt;&lt;/a&gt; &amp;quot;mainElement&amp;quot;: &amp;quot;EntryAbility&amp;quot;, &lt;/span&gt;&lt;span id=&#34;__span-5-27&#34;&gt;&lt;a id=&#34;__codelineno-5-27&#34; name=&#34;__codelineno-5-27&#34; href=&#34;#__codelineno-5-27&#34;&gt;&lt;/a&gt; &amp;quot;deviceTypes&amp;quot;: [ &lt;/span&gt;&lt;span id=&#34;__span-5-28&#34;&gt;&lt;a id=&#34;__codelineno-5-28&#34; name=&#34;__codelineno-5-28&#34; href=&#34;#__codelineno-5-28&#34;&gt;&lt;/a&gt;- &amp;quot;default&amp;quot; &lt;/span&gt;&lt;span id=&#34;__span-5-29&#34;&gt;&lt;a id=&#34;__codelineno-5-29&#34; name=&#34;__codelineno-5-29&#34; href=&#34;#__codelineno-5-29&#34;&gt;&lt;/a&gt;+ &amp;quot;default&amp;quot;, &lt;/span&gt;&lt;span id=&#34;__span-5-30&#34;&gt;&lt;a id=&#34;__codelineno-5-30&#34; name=&#34;__codelineno-5-30&#34; href=&#34;#__codelineno-5-30&#34;&gt;&lt;/a&gt;+ &amp;quot;2in1&amp;quot; &lt;/span&gt;&lt;span id=&#34;__span-5-31&#34;&gt;&lt;a id=&#34;__codelineno-5-31&#34; name=&#34;__codelineno-5-31&#34; href=&#34;#__codelineno-5-31&#34;&gt;&lt;/a&gt; ], &lt;/span&gt;&lt;span id=&#34;__span-5-32&#34;&gt;&lt;a id=&#34;__codelineno-5-32&#34; name=&#34;__codelineno-5-32&#34; href=&#34;#__codelineno-5-32&#34;&gt;&lt;/a&gt; &amp;quot;requestPermissions&amp;quot;: [ &lt;/span&gt;&lt;span id=&#34;__span-5-33&#34;&gt;&lt;a id=&#34;__codelineno-5-33&#34; name=&#34;__codelineno-5-33&#34; href=&#34;#__codelineno-5-33&#34;&gt;&lt;/a&gt; { &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;就可以在鸿蒙电脑上跑了。我编写的两个鸿蒙上的应用：&lt;a href=&#34;https://github.com/jiegec/SPECCPU2017Harmony&#34;&gt;https://github.com/jiegec/SPECCPU2017Harmony&lt;/a&gt; 和 &lt;a href=&#34;https://github.com/jiegec/NetworkToolsHarmony&#34;&gt;https://github.com/jiegec/NetworkToolsHarmony&lt;/a&gt; 都能正常在 MateBook Pro 上运行。&lt;/p&gt; &lt;p&gt;测试的过程中，发现用 hdc 传文件到电脑比传手机更快：Pura 70 Pro+ 是 24 MB/s，MateBook Pro 是 31 MB/s。&lt;/p&gt; &lt;p&gt;开源的鸿蒙应用也可以编译 + 运行：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://gitee.com/smdsbz/moonlight-ohos&#34;&gt;https://gitee.com/smdsbz/moonlight-ohos&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;目前还没找到怎么让鸿蒙电脑自己调试自己。&lt;/p&gt; &lt;h2 id=&#34;卓易通&#34;&gt;卓易通&lt;a class=&#34;headerlink&#34; href=&#34;#卓易通&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;2025-12-15：在应用市场的应用尝鲜里看到了卓易通，目前只能全屏打开 Android 应用。试了一下 Duolinguo，是左右分屏的显示方式，有点类似双折叠手机，左右各一个竖屏。&lt;/p&gt; &lt;h2 id=&#34;移植问题&#34;&gt;移植问题&lt;a class=&#34;headerlink&#34; href=&#34;#移植问题&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;ioctl(fd, TCSETS) 会失败，ioctl(fd, TCSETSW) 则成功&lt;/li&gt; &lt;li&gt;libc 缺少一些函数，比如 getspnam，有一些函数不可用，例如 getpwuid&lt;/li&gt; &lt;li&gt;openssl 的 hwcap 检测有问题，可能会导致 sigill&lt;/li&gt; &lt;li&gt;无法访问 /proc/stat&lt;/li&gt; &lt;/ul&gt; &lt;h2 id=&#34;termony&#34;&gt;Termony&lt;a class=&#34;headerlink&#34; href=&#34;#termony&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;目前通过 &lt;a href=&#34;https://github.com/jiegec/Termony&#34;&gt;https://github.com/jiegec/Termony&lt;/a&gt; 运行了一些 benchmark：&lt;/p&gt; &lt;div class=&#34;language-shell highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-6-1&#34;&gt;&lt;a id=&#34;__codelineno-6-1&#34; name=&#34;__codelineno-6-1&#34; href=&#34;#__codelineno-6-1&#34;&gt;&lt;/a&gt;$&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;vkpeak&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-2&#34;&gt;&lt;a id=&#34;__codelineno-6-2&#34; name=&#34;__codelineno-6-2&#34; href=&#34;#__codelineno-6-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nv&#34;&gt;device&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Maleoon&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;916&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-3&#34;&gt;&lt;a id=&#34;__codelineno-6-3&#34; name=&#34;__codelineno-6-3&#34; href=&#34;#__codelineno-6-3&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-4&#34;&gt;&lt;a id=&#34;__codelineno-6-4&#34; name=&#34;__codelineno-6-4&#34; href=&#34;#__codelineno-6-4&#34;&gt;&lt;/a&gt;fp32-scalar&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;718&lt;/span&gt;.54&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GFLOPS &lt;/span&gt;&lt;span id=&#34;__span-6-5&#34;&gt;&lt;a id=&#34;__codelineno-6-5&#34; name=&#34;__codelineno-6-5&#34; href=&#34;#__codelineno-6-5&#34;&gt;&lt;/a&gt;fp32-vec4&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1038&lt;/span&gt;.34&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GFLOPS &lt;/span&gt;&lt;span id=&#34;__span-6-6&#34;&gt;&lt;a id=&#34;__codelineno-6-6&#34; name=&#34;__codelineno-6-6&#34; href=&#34;#__codelineno-6-6&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-7&#34;&gt;&lt;a id=&#34;__codelineno-6-7&#34; name=&#34;__codelineno-6-7&#34; href=&#34;#__codelineno-6-7&#34;&gt;&lt;/a&gt;fp16-scalar&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1083&lt;/span&gt;.84&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GFLOPS &lt;/span&gt;&lt;span id=&#34;__span-6-8&#34;&gt;&lt;a id=&#34;__codelineno-6-8&#34; name=&#34;__codelineno-6-8&#34; href=&#34;#__codelineno-6-8&#34;&gt;&lt;/a&gt;fp16-vec4&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1791&lt;/span&gt;.44&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GFLOPS &lt;/span&gt;&lt;span id=&#34;__span-6-9&#34;&gt;&lt;a id=&#34;__codelineno-6-9&#34; name=&#34;__codelineno-6-9&#34; href=&#34;#__codelineno-6-9&#34;&gt;&lt;/a&gt;fp16-matrix&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;.00&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GFLOPS &lt;/span&gt;&lt;span id=&#34;__span-6-10&#34;&gt;&lt;a id=&#34;__codelineno-6-10&#34; name=&#34;__codelineno-6-10&#34; href=&#34;#__codelineno-6-10&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-11&#34;&gt;&lt;a id=&#34;__codelineno-6-11&#34; name=&#34;__codelineno-6-11&#34; href=&#34;#__codelineno-6-11&#34;&gt;&lt;/a&gt;fp64-scalar&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;.00&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GFLOPS &lt;/span&gt;&lt;span id=&#34;__span-6-12&#34;&gt;&lt;a id=&#34;__codelineno-6-12&#34; name=&#34;__codelineno-6-12&#34; href=&#34;#__codelineno-6-12&#34;&gt;&lt;/a&gt;fp64-vec4&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;.00&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GFLOPS &lt;/span&gt;&lt;span id=&#34;__span-6-13&#34;&gt;&lt;a id=&#34;__codelineno-6-13&#34; name=&#34;__codelineno-6-13&#34; href=&#34;#__codelineno-6-13&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-14&#34;&gt;&lt;a id=&#34;__codelineno-6-14&#34; name=&#34;__codelineno-6-14&#34; href=&#34;#__codelineno-6-14&#34;&gt;&lt;/a&gt;int32-scalar&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;303&lt;/span&gt;.34&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GIOPS &lt;/span&gt;&lt;span id=&#34;__span-6-15&#34;&gt;&lt;a id=&#34;__codelineno-6-15&#34; name=&#34;__codelineno-6-15&#34; href=&#34;#__codelineno-6-15&#34;&gt;&lt;/a&gt;int32-vec4&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;316&lt;/span&gt;.56&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GIOPS &lt;/span&gt;&lt;span id=&#34;__span-6-16&#34;&gt;&lt;a id=&#34;__codelineno-6-16&#34; name=&#34;__codelineno-6-16&#34; href=&#34;#__codelineno-6-16&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-17&#34;&gt;&lt;a id=&#34;__codelineno-6-17&#34; name=&#34;__codelineno-6-17&#34; href=&#34;#__codelineno-6-17&#34;&gt;&lt;/a&gt;int16-scalar&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;709&lt;/span&gt;.12&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GIOPS &lt;/span&gt;&lt;span id=&#34;__span-6-18&#34;&gt;&lt;a id=&#34;__codelineno-6-18&#34; name=&#34;__codelineno-6-18&#34; href=&#34;#__codelineno-6-18&#34;&gt;&lt;/a&gt;int16-vec4&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;830&lt;/span&gt;.55&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GIOPS &lt;/span&gt;&lt;span id=&#34;__span-6-19&#34;&gt;&lt;a id=&#34;__codelineno-6-19&#34; name=&#34;__codelineno-6-19&#34; href=&#34;#__codelineno-6-19&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-20&#34;&gt;&lt;a id=&#34;__codelineno-6-20&#34; name=&#34;__codelineno-6-20&#34; href=&#34;#__codelineno-6-20&#34;&gt;&lt;/a&gt;int8-dotprod&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;.00&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GIOPS &lt;/span&gt;&lt;span id=&#34;__span-6-21&#34;&gt;&lt;a id=&#34;__codelineno-6-21&#34; name=&#34;__codelineno-6-21&#34; href=&#34;#__codelineno-6-21&#34;&gt;&lt;/a&gt;int8-matrix&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;.00&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GIOPS &lt;/span&gt;&lt;span id=&#34;__span-6-22&#34;&gt;&lt;a id=&#34;__codelineno-6-22&#34; name=&#34;__codelineno-6-22&#34; href=&#34;#__codelineno-6-22&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-23&#34;&gt;&lt;a id=&#34;__codelineno-6-23&#34; name=&#34;__codelineno-6-23&#34; href=&#34;#__codelineno-6-23&#34;&gt;&lt;/a&gt;bf16-dotprod&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;.00&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GFLOPS &lt;/span&gt;&lt;span id=&#34;__span-6-24&#34;&gt;&lt;a id=&#34;__codelineno-6-24&#34; name=&#34;__codelineno-6-24&#34; href=&#34;#__codelineno-6-24&#34;&gt;&lt;/a&gt;bf16-matrix&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;.00&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;GFLOPS &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h2 id=&#34;未完待续&#34;&gt;未完待续&lt;a class=&#34;headerlink&#34; href=&#34;#未完待续&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt;</description> <link>https://jia.je/hardware/2025/06/06/huawei-matebook-pro/</link> <pubDate>Fri, 06 Jun 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2025/06/06/huawei-matebook-pro/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2025/06/06/huawei-matebook-pro.png" type="image/png" length="54572" /> </item> <item> <title>在 HarmonyOS 5 上运行 Fortran 程序</title> <category>arm64</category> <category>clang</category> <category>flang</category> <category>fortran</category> <category>hardware</category> <category>harmonyos</category> <category>huawei</category> <category>llvm</category> <description>&lt;h1 id=&#34;在-harmonyos-5-上运行-fortran-程序&#34;&gt;在 HarmonyOS 5 上运行 Fortran 程序&lt;a class=&#34;headerlink&#34; href=&#34;#在-harmonyos-5-上运行-fortran-程序&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;前段时间把 SPEC CPU 2017 移植到了鸿蒙 5 上：&lt;a href=&#34;https://github.com/jiegec/SPECCPU2017Harmony&#34;&gt;https://github.com/jiegec/SPECCPU2017Harmony&lt;/a&gt;，由于 SPEC CPU 2017 里有不少 Fortran 程序，所以就研究了一下怎么编译 Fortran 代码，最终搞成了，在这里记录一下。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;过程&#34;&gt;过程&lt;a class=&#34;headerlink&#34; href=&#34;#过程&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;HarmonyOS 5 的工具链用的是 LLVM 15，自带的编译器是 clang，那个时候还没有 LLVM flang。但是，经过实际测试，使用新版本的 flang，也是可以的，只是需要做一些额外的操作。例如 flang 有自己的 runtime（类比 libgcc 和 LLVM 的 compiler-rt），需要交叉编译一个 arm64 的版本，下面是仓库中 &lt;a href=&#34;https://github.com/jiegec/SPECCPU2017Harmony/blob/f02cbe4a043d4c1489ebfae8a190e4a1ab6ca2c8/build-flang.sh&#34;&gt;build-flang.sh&lt;/a&gt; 的内容：&lt;/p&gt; &lt;div class=&#34;language-shell highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-0-1&#34;&gt;&lt;a id=&#34;__codelineno-0-1&#34; name=&#34;__codelineno-0-1&#34; href=&#34;#__codelineno-0-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;ch&#34;&gt;#!/bin/sh&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-2&#34;&gt;&lt;a id=&#34;__codelineno-0-2&#34; name=&#34;__codelineno-0-2&#34; href=&#34;#__codelineno-0-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;# build missing libraries for aarch64-linux-ohos target&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-3&#34;&gt;&lt;a id=&#34;__codelineno-0-3&#34; name=&#34;__codelineno-0-3&#34; href=&#34;#__codelineno-0-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;# assume llvm-project is cloned at $HOME/llvm-project&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-4&#34;&gt;&lt;a id=&#34;__codelineno-0-4&#34; name=&#34;__codelineno-0-4&#34; href=&#34;#__codelineno-0-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-x&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-e &lt;/span&gt;&lt;span id=&#34;__span-0-5&#34;&gt;&lt;a id=&#34;__codelineno-0-5&#34; name=&#34;__codelineno-0-5&#34; href=&#34;#__codelineno-0-5&#34;&gt;&lt;/a&gt;mkdir&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-p&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;flang &lt;/span&gt;&lt;span id=&#34;__span-0-6&#34;&gt;&lt;a id=&#34;__codelineno-0-6&#34; name=&#34;__codelineno-0-6&#34; href=&#34;#__codelineno-0-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;PATH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;~/command-line-tools/sdk/default/openharmony/native/llvm/bin:&lt;span class=&#34;nv&#34;&gt;$PATH&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-7&#34;&gt;&lt;a id=&#34;__codelineno-0-7&#34; name=&#34;__codelineno-0-7&#34; href=&#34;#__codelineno-0-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nv&#34;&gt;DST&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$PWD&lt;/span&gt;/flang &lt;/span&gt;&lt;span id=&#34;__span-0-8&#34;&gt;&lt;a id=&#34;__codelineno-0-8&#34; name=&#34;__codelineno-0-8&#34; href=&#34;#__codelineno-0-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;/llvm-project &lt;/span&gt;&lt;span id=&#34;__span-0-9&#34;&gt;&lt;a id=&#34;__codelineno-0-9&#34; name=&#34;__codelineno-0-9&#34; href=&#34;#__codelineno-0-9&#34;&gt;&lt;/a&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;checkout&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;main &lt;/span&gt;&lt;span id=&#34;__span-0-10&#34;&gt;&lt;a id=&#34;__codelineno-0-10&#34; name=&#34;__codelineno-0-10&#34; href=&#34;#__codelineno-0-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;# match hash in flang-new-20 --version&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-11&#34;&gt;&lt;a id=&#34;__codelineno-0-11&#34; name=&#34;__codelineno-0-11&#34; href=&#34;#__codelineno-0-11&#34;&gt;&lt;/a&gt;git&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;reset&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;7cf14539b644&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--hard &lt;/span&gt;&lt;span id=&#34;__span-0-12&#34;&gt;&lt;a id=&#34;__codelineno-0-12&#34; name=&#34;__codelineno-0-12&#34; href=&#34;#__codelineno-0-12&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-13&#34;&gt;&lt;a id=&#34;__codelineno-0-13&#34; name=&#34;__codelineno-0-13&#34; href=&#34;#__codelineno-0-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;libunwind &lt;/span&gt;&lt;span id=&#34;__span-0-14&#34;&gt;&lt;a id=&#34;__codelineno-0-14&#34; name=&#34;__codelineno-0-14&#34; href=&#34;#__codelineno-0-14&#34;&gt;&lt;/a&gt;rm&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-rf&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;build &lt;/span&gt;&lt;span id=&#34;__span-0-15&#34;&gt;&lt;a id=&#34;__codelineno-0-15&#34; name=&#34;__codelineno-0-15&#34; href=&#34;#__codelineno-0-15&#34;&gt;&lt;/a&gt;mkdir&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-p&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;build &lt;/span&gt;&lt;span id=&#34;__span-0-16&#34;&gt;&lt;a id=&#34;__codelineno-0-16&#34; name=&#34;__codelineno-0-16&#34; href=&#34;#__codelineno-0-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;build &lt;/span&gt;&lt;span id=&#34;__span-0-17&#34;&gt;&lt;a id=&#34;__codelineno-0-17&#34; name=&#34;__codelineno-0-17&#34; href=&#34;#__codelineno-0-17&#34;&gt;&lt;/a&gt;cmake&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;..&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Ninja&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-18&#34;&gt;&lt;a id=&#34;__codelineno-0-18&#34; name=&#34;__codelineno-0-18&#34; href=&#34;#__codelineno-0-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-DCMAKE_C_FLAGS&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;-target aarch64-linux-ohos -fuse-ld=lld&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-19&#34;&gt;&lt;a id=&#34;__codelineno-0-19&#34; name=&#34;__codelineno-0-19&#34; href=&#34;#__codelineno-0-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-DCMAKE_C_COMPILER&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;clang&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-20&#34;&gt;&lt;a id=&#34;__codelineno-0-20&#34; name=&#34;__codelineno-0-20&#34; href=&#34;#__codelineno-0-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-DCMAKE_CXX_FLAGS&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;-target aarch64-linux-ohos -fuse-ld=lld&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-21&#34;&gt;&lt;a id=&#34;__codelineno-0-21&#34; name=&#34;__codelineno-0-21&#34; href=&#34;#__codelineno-0-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-DCMAKE_CXX_COMPILER&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;clang++&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-22&#34;&gt;&lt;a id=&#34;__codelineno-0-22&#34; name=&#34;__codelineno-0-22&#34; href=&#34;#__codelineno-0-22&#34;&gt;&lt;/a&gt;ninja &lt;/span&gt;&lt;span id=&#34;__span-0-23&#34;&gt;&lt;a id=&#34;__codelineno-0-23&#34; name=&#34;__codelineno-0-23&#34; href=&#34;#__codelineno-0-23&#34;&gt;&lt;/a&gt;cp&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;lib/libunwind.a&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$DST&lt;/span&gt;/ &lt;/span&gt;&lt;span id=&#34;__span-0-24&#34;&gt;&lt;a id=&#34;__codelineno-0-24&#34; name=&#34;__codelineno-0-24&#34; href=&#34;#__codelineno-0-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;../../ &lt;/span&gt;&lt;span id=&#34;__span-0-25&#34;&gt;&lt;a id=&#34;__codelineno-0-25&#34; name=&#34;__codelineno-0-25&#34; href=&#34;#__codelineno-0-25&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-26&#34;&gt;&lt;a id=&#34;__codelineno-0-26&#34; name=&#34;__codelineno-0-26&#34; href=&#34;#__codelineno-0-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;flang/lib/Decimal &lt;/span&gt;&lt;span id=&#34;__span-0-27&#34;&gt;&lt;a id=&#34;__codelineno-0-27&#34; name=&#34;__codelineno-0-27&#34; href=&#34;#__codelineno-0-27&#34;&gt;&lt;/a&gt;rm&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-rf&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;build &lt;/span&gt;&lt;span id=&#34;__span-0-28&#34;&gt;&lt;a id=&#34;__codelineno-0-28&#34; name=&#34;__codelineno-0-28&#34; href=&#34;#__codelineno-0-28&#34;&gt;&lt;/a&gt;mkdir&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-p&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;build &lt;/span&gt;&lt;span id=&#34;__span-0-29&#34;&gt;&lt;a id=&#34;__codelineno-0-29&#34; name=&#34;__codelineno-0-29&#34; href=&#34;#__codelineno-0-29&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;build &lt;/span&gt;&lt;span id=&#34;__span-0-30&#34;&gt;&lt;a id=&#34;__codelineno-0-30&#34; name=&#34;__codelineno-0-30&#34; href=&#34;#__codelineno-0-30&#34;&gt;&lt;/a&gt;cmake&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;..&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Ninja&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-31&#34;&gt;&lt;a id=&#34;__codelineno-0-31&#34; name=&#34;__codelineno-0-31&#34; href=&#34;#__codelineno-0-31&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-DCMAKE_C_FLAGS&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;-target aarch64-linux-ohos -fuse-ld=lld -fPIC&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-32&#34;&gt;&lt;a id=&#34;__codelineno-0-32&#34; name=&#34;__codelineno-0-32&#34; href=&#34;#__codelineno-0-32&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-DCMAKE_C_COMPILER&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;clang&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-33&#34;&gt;&lt;a id=&#34;__codelineno-0-33&#34; name=&#34;__codelineno-0-33&#34; href=&#34;#__codelineno-0-33&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-DCMAKE_CXX_FLAGS&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;-target aarch64-linux-ohos -fuse-ld=lld -fPIC&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-34&#34;&gt;&lt;a id=&#34;__codelineno-0-34&#34; name=&#34;__codelineno-0-34&#34; href=&#34;#__codelineno-0-34&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-DCMAKE_CXX_COMPILER&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;clang++&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-35&#34;&gt;&lt;a id=&#34;__codelineno-0-35&#34; name=&#34;__codelineno-0-35&#34; href=&#34;#__codelineno-0-35&#34;&gt;&lt;/a&gt;ninja &lt;/span&gt;&lt;span id=&#34;__span-0-36&#34;&gt;&lt;a id=&#34;__codelineno-0-36&#34; name=&#34;__codelineno-0-36&#34; href=&#34;#__codelineno-0-36&#34;&gt;&lt;/a&gt;cp&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;libFortranDecimal.a&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$DST&lt;/span&gt;/ &lt;/span&gt;&lt;span id=&#34;__span-0-37&#34;&gt;&lt;a id=&#34;__codelineno-0-37&#34; name=&#34;__codelineno-0-37&#34; href=&#34;#__codelineno-0-37&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;../../../../ &lt;/span&gt;&lt;span id=&#34;__span-0-38&#34;&gt;&lt;a id=&#34;__codelineno-0-38&#34; name=&#34;__codelineno-0-38&#34; href=&#34;#__codelineno-0-38&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-39&#34;&gt;&lt;a id=&#34;__codelineno-0-39&#34; name=&#34;__codelineno-0-39&#34; href=&#34;#__codelineno-0-39&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;flang/runtime &lt;/span&gt;&lt;span id=&#34;__span-0-40&#34;&gt;&lt;a id=&#34;__codelineno-0-40&#34; name=&#34;__codelineno-0-40&#34; href=&#34;#__codelineno-0-40&#34;&gt;&lt;/a&gt;rm&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-rf&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;build &lt;/span&gt;&lt;span id=&#34;__span-0-41&#34;&gt;&lt;a id=&#34;__codelineno-0-41&#34; name=&#34;__codelineno-0-41&#34; href=&#34;#__codelineno-0-41&#34;&gt;&lt;/a&gt;mkdir&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-p&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;build &lt;/span&gt;&lt;span id=&#34;__span-0-42&#34;&gt;&lt;a id=&#34;__codelineno-0-42&#34; name=&#34;__codelineno-0-42&#34; href=&#34;#__codelineno-0-42&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;build &lt;/span&gt;&lt;span id=&#34;__span-0-43&#34;&gt;&lt;a id=&#34;__codelineno-0-43&#34; name=&#34;__codelineno-0-43&#34; href=&#34;#__codelineno-0-43&#34;&gt;&lt;/a&gt;cmake&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;..&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-G&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;Ninja&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-44&#34;&gt;&lt;a id=&#34;__codelineno-0-44&#34; name=&#34;__codelineno-0-44&#34; href=&#34;#__codelineno-0-44&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-DCMAKE_C_FLAGS&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;-target aarch64-linux-ohos -fuse-ld=lld -fPIC&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-45&#34;&gt;&lt;a id=&#34;__codelineno-0-45&#34; name=&#34;__codelineno-0-45&#34; href=&#34;#__codelineno-0-45&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-DCMAKE_C_COMPILER&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;clang&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-46&#34;&gt;&lt;a id=&#34;__codelineno-0-46&#34; name=&#34;__codelineno-0-46&#34; href=&#34;#__codelineno-0-46&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-DCMAKE_CXX_FLAGS&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;-target aarch64-linux-ohos -fuse-ld=lld -fPIC&amp;quot;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-47&#34;&gt;&lt;a id=&#34;__codelineno-0-47&#34; name=&#34;__codelineno-0-47&#34; href=&#34;#__codelineno-0-47&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-DCMAKE_CXX_COMPILER&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;clang++&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-48&#34;&gt;&lt;a id=&#34;__codelineno-0-48&#34; name=&#34;__codelineno-0-48&#34; href=&#34;#__codelineno-0-48&#34;&gt;&lt;/a&gt;ninja &lt;/span&gt;&lt;span id=&#34;__span-0-49&#34;&gt;&lt;a id=&#34;__codelineno-0-49&#34; name=&#34;__codelineno-0-49&#34; href=&#34;#__codelineno-0-49&#34;&gt;&lt;/a&gt;cp&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;libFortranRuntime.a&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$DST&lt;/span&gt;/ &lt;/span&gt;&lt;span id=&#34;__span-0-50&#34;&gt;&lt;a id=&#34;__codelineno-0-50&#34; name=&#34;__codelineno-0-50&#34; href=&#34;#__codelineno-0-50&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;../../../ &lt;/span&gt;&lt;span id=&#34;__span-0-51&#34;&gt;&lt;a id=&#34;__codelineno-0-51&#34; name=&#34;__codelineno-0-51&#34; href=&#34;#__codelineno-0-51&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-0-52&#34;&gt;&lt;a id=&#34;__codelineno-0-52&#34; name=&#34;__codelineno-0-52&#34; href=&#34;#__codelineno-0-52&#34;&gt;&lt;/a&gt;ls&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-al&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$DST&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;核心就是以 aarch64-linux-ohos 为 target，编译出三个 &lt;code&gt;.a&lt;/code&gt; 文件，之后再链接上就可以了。需要注意的是，runtime 版本和 flang 版本需要一致。为了偷懒，直接用的是 LLVM APT 提供的 flang-new-20 的 binary，那么它是会随着 apt upgrade 而更新的，这个时候就需要重新编译一次 flang runtime，然后链接到程序里。如果版本不对上，可能遇到一些问题：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-1-1&#34;&gt;&lt;a id=&#34;__codelineno-1-1&#34; name=&#34;__codelineno-1-1&#34; href=&#34;#__codelineno-1-1&#34;&gt;&lt;/a&gt;fatal Fortran runtime error(/home/jiegec/llvm-project/flang/runtime/descriptor.cpp:74): not yet implemented: type category(6) &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;参考 &lt;a href=&#34;https://github.com/llvm/llvm-project/issues/129877&#34;&gt;[flang] fatal Fortran runtime error&lt;/a&gt;，就知道是编译器版本和 runtime 不兼容的问题了。&lt;/p&gt; &lt;p&gt;编译好了 fortran runtime 之后，就可以用 flang-new-20 编译 fortran 代码了。这里给出 CMake 的配置方式，主要涉及到需要用的编译选项：&lt;/p&gt; &lt;div class=&#34;language-cmake highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-2-1&#34;&gt;&lt;a id=&#34;__codelineno-2-1&#34; name=&#34;__codelineno-2-1&#34; href=&#34;#__codelineno-2-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;CMAKE_Fortran_COMPILER_FORCED&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-2&#34;&gt;&lt;a id=&#34;__codelineno-2-2&#34; name=&#34;__codelineno-2-2&#34; href=&#34;#__codelineno-2-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;CMAKE_Fortran_COMPILER&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;flang-new-20&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-3&#34;&gt;&lt;a id=&#34;__codelineno-2-3&#34; name=&#34;__codelineno-2-3&#34; href=&#34;#__codelineno-2-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;CMAKE_Fortran_FLAGS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;quot;-target aarch64-linux-ohos -fuse-ld=lld -L ${CMAKE_CURRENT_SOURCE_DIR}/../../../../flang -nostdlib -L ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../command-line-tools/sdk/default/openharmony/native/sysroot/usr/lib/aarch64-linux-ohos -lc -lm -L ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../command-line-tools/sdk/default/openharmony/native/llvm/lib/clang/15.0.4/lib/aarch64-linux-ohos/ -lclang_rt.builtins -lFortranRuntime -lFortranDecimal&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-4&#34;&gt;&lt;a id=&#34;__codelineno-2-4&#34; name=&#34;__codelineno-2-4&#34; href=&#34;#__codelineno-2-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nb&#34;&gt;enable_language&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;Fortran&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;这里的相对路径，其实就是要找到新编译出来的 flang runtime，以及 HarmonyOS command line tools 里面的一些库，具体路径需要根据实际情况来调整，这里只是一个样例。&lt;/p&gt; &lt;p&gt;到这里，就可以在 HarmonyOS 5 上运行 Fortran 程序了。其实还可以考虑研究一下 GFortran，或许也是能实现的，但目前还没有去做进一步的尝试。&lt;/p&gt;</description> <link>https://jia.je/hardware/2025/06/06/using-fortran-on-harmonyos-5/</link> <pubDate>Fri, 06 Jun 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2025/06/06/using-fortran-on-harmonyos-5/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2025/06/06/using-fortran-on-harmonyos-5.png" type="image/png" length="50699" /> </item> <item> <title>ARM Neoverse N1 (代号 Ares) 的 BTB 结构分析</title> <category>arm</category> <category>btb</category> <category>cpu</category> <category>hardware</category> <category>neoverse</category> <description>&lt;h1 id=&#34;arm-neoverse-n1-代号-ares-的-btb-结构分析&#34;&gt;ARM Neoverse N1 (代号 Ares) 的 BTB 结构分析&lt;a class=&#34;headerlink&#34; href=&#34;#arm-neoverse-n1-代号-ares-的-btb-结构分析&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;p&gt;本文同步发布到本人的&lt;a href=&#34;https://zhuanlan.zhihu.com/p/1926041649617826619&#34;&gt;知乎&lt;/a&gt;。&lt;/p&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;ARM Neoverse N1 是 2019 年发布的比较早的一代 ARM 服务器的处理器，它在很多地方都和 Cortex-A76 类似。它的 BTB 结构比较有意思，所以在这里对它的 BTB 做一些分析。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;官方信息&#34;&gt;官方信息&lt;a class=&#34;headerlink&#34; href=&#34;#官方信息&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;首先收集了一些 ARM Neoverse N1 的 BTB 结构的官方信息：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://hc33.hotchips.org/assets/program/conference/day1/20210818_Hotchips_NeoverseN2.pdf&#34;&gt;Arm Neoverse N2: Arm’s 2nd generation high performance infrastructure CPUs and system IPs&lt;/a&gt; 中对 Neoverse N1 的介绍：&lt;ul&gt; &lt;li&gt;Branch Prediction Width: 8 instrs&lt;/li&gt; &lt;li&gt;Nano BTB (0 cyc taken-branch bubble): 16 entry&lt;/li&gt; &lt;li&gt;Main BTB: 6K entry&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://www.arm.com/-/media/global/solutions/infrastructure/arm-neoverse-n1-platform.pdf&#34;&gt;The Arm Neoverse N1 Platform: Building Blocks for the Next-Gen Cloud-to-Edge Infrastructure SoC&lt;/a&gt; 的介绍：&lt;ul&gt; &lt;li&gt;6K entry Main BTB, 3 cycle access latency&lt;/li&gt; &lt;li&gt;64-entry Micro BTB&lt;/li&gt; &lt;li&gt;16-entry Nano BTB&lt;/li&gt; &lt;li&gt;4-way set associative 64KB L1 ICache&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;简单整理一下官方信息，大概有三级 BTB：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;16-entry Nano BTB, 1 cycle latency (0 cycle bubble)&lt;/li&gt; &lt;li&gt;64-entry Micro BTB&lt;/li&gt; &lt;li&gt;6K-entry Main BTB, 3 cycle latency&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;但是很多细节是缺失的，因此下面结合微架构测试，进一步研究它的内部结构。&lt;/p&gt; &lt;h2 id=&#34;微架构测试&#34;&gt;微架构测试&lt;a class=&#34;headerlink&#34; href=&#34;#微架构测试&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;在之前的博客里，我们已经测试了各种处理器的 BTB，在这里也是一样的：按照一定的 stride 分布无条件直接分支，构成一个链条，然后测量 CPI。&lt;/p&gt; &lt;h3 id=&#34;stride4b&#34;&gt;stride=4B&lt;a class=&#34;headerlink&#34; href=&#34;#stride4b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;首先是 stride=4B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-n1-btb-4b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了三个比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 16 条分支，CPI=1，对应了 16-entry 的 Nano BTB&lt;/li&gt; &lt;li&gt;第二个台阶到 80 条分支，CPI=2，其中 &lt;code&gt;80=16+64&lt;/code&gt;，多出来的部分对应了 64-entry 的 Micro BTB，意味着 Micro BTB 相对 Nano BTB 是 Victim BTB 的地位：Nano BTB 被替换出去的 entry 会进入到 Micro BTB，而命中 Micro BTB 的 entry 会被移动到 Nano BTB&lt;/li&gt; &lt;li&gt;第三个台阶到 8192 条分支，CPI=5，大于 Main BTB 的 3 cycle latency，说明此时没有命中 Main BTB，而是要等到取指和译码后，计算出正确的目的地址再回滚，导致了 5 cycle latency；8192 的性能下降原因还需要进一步研究，16384 的性能下降对应了 64KB 的 ICache，因为 &lt;code&gt;4B*16384=64KB&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;那么 stride=4B 的情况下就遗留了两个问题：为什么没有命中 Main BTB；8192 处为什么出现了性能下降。&lt;/p&gt; &lt;h3 id=&#34;stride8b&#34;&gt;stride=8B&lt;a class=&#34;headerlink&#34; href=&#34;#stride8b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;接下来观察 stride=8B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-n1-btb-8b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了三个比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 16 条分支，CPI=1，对应了 16-entry 的 Nano BTB，和之前一样&lt;/li&gt; &lt;li&gt;第二个台阶到 80 条分支，CPI=2，其中 &lt;code&gt;80=16+64&lt;/code&gt;，多出来的部分对应了 64-entry 的 Micro BTB，和之前一样&lt;/li&gt; &lt;li&gt;第三个台阶到 4096 条分支，CPI=2.75，约等于 Main BTB 的 3 cycle latency，说明此时命中的是 Main BTB，但是它并没有达到宣称的 6144-entry 的 Main BTB 容量；8192 还有一个性能下降，这对应了 64KB 的 ICache：&lt;code&gt;8B*8192=64KB&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;相比 stride=4B，Nano BTB 和 Micro BTB 的行为没有变化；而 Main BTB 开始能够命中，这代表 Main BTB 在分支特别密集的情况下，会出现性能问题。&lt;/p&gt; &lt;p&gt;那么 stride=8B 的情况下遗留了两个问题：为什么 CPI=2.75 而不是 3？为什么只观察到了 4K 的 Main BTB 容量，而不是 6K？&lt;/p&gt; &lt;h3 id=&#34;stride16b&#34;&gt;stride=16B&lt;a class=&#34;headerlink&#34; href=&#34;#stride16b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=16B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-n1-btb-16b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了四个比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 16 条分支，CPI=1，对应了 16-entry 的 Nano BTB，和之前一样&lt;/li&gt; &lt;li&gt;第二个台阶到 80 条分支，CPI=2，其中 &lt;code&gt;80=16+64&lt;/code&gt;，多出来的部分对应了 64-entry 的 Micro BTB，和之前一样&lt;/li&gt; &lt;li&gt;第三个台阶到 4096 条分支，CPI=2.5，比 Main BTB 的 3 cycle latency 略小，但是大于 2，说明此时命中的是 Main BTB，此时遇到了 64KB ICache 的瓶颈：&lt;code&gt;4096*16B=64KB&lt;/code&gt;&lt;/li&gt; &lt;li&gt;第四个台阶到 6144 条分支，CPI=3.5，比 Main BTB 的 3 cycle latency 略大，是因为 64KB ICache 出现了缺失，但这个时候终于显现了宣传的 Main BTB 的 6144 的容量&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;相比 stride=8B，Nano BTB 和 Micro BTB 的行为没有变化；Main BTB 的 6144 容量开始显现，并且出现地比 64KB ICache 更晚。&lt;/p&gt; &lt;p&gt;那么 stride=16B 的情况下遗留了一个问题：为什么出现了 CPI=2.5 的平台？&lt;/p&gt; &lt;h3 id=&#34;stride32b&#34;&gt;stride=32B&lt;a class=&#34;headerlink&#34; href=&#34;#stride32b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=32B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-n1-btb-32b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了三个比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 16 条分支，CPI=1，对应了 16-entry 的 Nano BTB，和之前一样&lt;/li&gt; &lt;li&gt;第二个台阶到 2048 条分支，CPI=2，此时遇到了 64KB ICache 的瓶颈：&lt;code&gt;2048*32B=64KB&lt;/code&gt;，但是这个时候已经超出了 Micro BTB 的容量，而 Main BTB 有 3 cycle 的 latency，为何还能保持 CPI=2 呢&lt;/li&gt; &lt;li&gt;第三个台阶到 6144 条分支，CPI=4，比 Main BTB 的 3 cycle latency 略大，是因为 64KB ICache 出现了缺失，显现的是宣传的 Main BTB 的 6144 的容量，更加说明第二个台阶内 Main BTB 是命中的&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;那么 stride=32B 的情况下遗留了一个问题：为什么在 Main BTB 的范围内出现了 CPI=2 的平台？&lt;/p&gt; &lt;h3 id=&#34;stride64b&#34;&gt;stride=64B&lt;a class=&#34;headerlink&#34; href=&#34;#stride64b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=64B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-n1-btb-64b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了三个比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 16 条分支，CPI=1，对应了 16-entry 的 Nano BTB，和之前一样&lt;/li&gt; &lt;li&gt;第二个台阶到 1024 条分支，CPI=2，此时遇到了 64KB ICache 的瓶颈：&lt;code&gt;1024*64B=64KB&lt;/code&gt;，和之前一样&lt;/li&gt; &lt;li&gt;第三个台阶到 3122 条分支，CPI=6，比 Main BTB 的 3 cycle latency 大，是因为 64KB ICache 出现了缺失，此时 Main BTB 的容量砍半&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;stride=64B 相比 stride=32B 的 Main BTB 容量砍半，这是组相连的表现：如果 PC[5] 在组相连的 index 当中，那么当 stride=64B 时，PC[5] 恒等于 0，意味着只有一半的 set 可以被用到，那也就只有一半的容量了。&lt;/p&gt; &lt;p&gt;Nano BTB 和 Micro BTB 容量没有变小，意味着它们大概率是全相连的：这也和它们的大小相吻合。&lt;/p&gt; &lt;p&gt;那么 stride=64B 的情况下遗留的问题和 stride=32B 一样：为什么在 Main BTB 的范围内出现了 CPI=2 的平台？&lt;/p&gt; &lt;h3 id=&#34;stride128b&#34;&gt;stride=128B&lt;a class=&#34;headerlink&#34; href=&#34;#stride128b&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;继续观察 stride=128B 的情况：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-n1-btb-128b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到，图像上出现了三个比较显著的台阶：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;第一个台阶到 16 条分支，CPI=1，对应了 16-entry 的 Nano BTB，和之前一样&lt;/li&gt; &lt;li&gt;第二个台阶到 512 条分支，CPI=2，此时遇到了 64KB ICache 的瓶颈：&lt;code&gt;512*128B=64KB&lt;/code&gt;，和之前一样&lt;/li&gt; &lt;li&gt;第三个台阶到 1536 条分支，CPI=6.x，比 Main BTB 的 3 cycle latency 大，是因为 64KB ICache 出现了缺失，此时 Main BTB 的容量进一步砍半&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;stride=128B 相比 stride=64B 的 Main BTB 容量进一步砍半，也是组相连的表现，意味着 PC[6] 也在组相连的 idnex 当中，只有四分之一的 set 可以被用到。&lt;/p&gt; &lt;p&gt;那么 stride=128B 的情况下遗留的问题和 stride=32B 一样：为什么在 Main BTB 的范围内出现了 CPI=2 的平台？&lt;/p&gt; &lt;h3 id=&#34;小结&#34;&gt;小结&lt;a class=&#34;headerlink&#34; href=&#34;#小结&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;测试到这里就差不多了，更大的 stride 得到的也是类似的结果，总结一下前面的发现：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Nano BTB 是 16-entry，1 cycle latency，不随着 stride 变化&lt;/li&gt; &lt;li&gt;Micro BTB 是 64-entry，2 cycle latency，也不随着 stride 变化&lt;/li&gt; &lt;li&gt;Main BTB 是 6K-entry，3 cycle latency，容量随着 stride 变化，大概率是 PC[n:5] 这一段被用于 index，使得 stride=64B 开始容量不断减半&lt;/li&gt; &lt;li&gt;64KB ICache 很多时候会比 Main BTB 更早成为瓶颈&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;也总结一下前面发现了各种没有解释的遗留问题：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;stride=4B 的情况下，Main BTB 没有像预期那样工作：解释见后&lt;/li&gt; &lt;li&gt;stride=4B 的情况下，8192 条分支处出现了性能下降：暂无解释&lt;/li&gt; &lt;li&gt;stride=8B 的情况下，只观察到 4096 的 Main BTB 容量，而不是 6144：解释见后&lt;/li&gt; &lt;li&gt;stride=8B 的情况下，在 Main BTB 命中的范围内，CPI=2.75：解释见后&lt;/li&gt; &lt;li&gt;stride=16B 的情况下，在 Main BTB 命中的范围内，CPI=2.5：解释见后&lt;/li&gt; &lt;li&gt;stride=32B 或 64B 或 128B 的情况下，在 Main BTB 命中的范围内，CPI=2：解释见后&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;接下来尝试解析一下这些遗留问题背后的原理。部分遗留问题，并没有被解释出来，欢迎读者提出猜想。&lt;/p&gt; &lt;h2 id=&#34;解析遗留问题&#34;&gt;解析遗留问题&lt;a class=&#34;headerlink&#34; href=&#34;#解析遗留问题&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;stride4b-的情况下main-btb-没有像预期那样工作&#34;&gt;stride=4B 的情况下，Main BTB 没有像预期那样工作&lt;a class=&#34;headerlink&#34; href=&#34;#stride4b-的情况下main-btb-没有像预期那样工作&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;对于这种类似 Cache 的结构，当它看起来总是没有命中的时候，其实就是每一个 Set 内要访问的数据超出了 Way，导致每次新访问的都会缺失。上面分析到，Main BTB 的 Index 大概是 PC[n:5] 这一段，那么一个对齐的 32B 范围内，分支指令都会被映射到同一个 set 内。当 stride=4B 的时候，对齐的 32B 范围内有 8 条指令；而 stride=8B 的时候，只有 4 条指令。8 条指令不行，4 条指令可以，暗示了中间跨越了 Way 的数量。&lt;/p&gt; &lt;p&gt;首先来回顾一下 Main BTB 的 6144-entry 是怎么来的：虽然它没说是几路组相连，但因为 6144 有一个 3 的因子，它不是二的幂次，所以一定是在 Way 数量上产生的。这就导致了至少这样几种可能：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;3-way set associative, 2048 sets&lt;/li&gt; &lt;li&gt;6-way set associative, 1024 sets&lt;/li&gt; &lt;li&gt;12-way set associative, 512 sets&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;回顾前面的分析：4 条指令没有超过 Way 数量，8 条指令超过了，那么只能是上述可能里的 6-way set associative，1024 sets 的情况。&lt;/p&gt; &lt;p&gt;翻阅 &lt;a href=&#34;https://developer.arm.com/documentation/100616/latest/&#34;&gt;Arm® Neoverse™ N1 Core Technical Reference Manual&lt;/a&gt;，它是这么说的：&lt;/p&gt; &lt;p&gt;L1 BTB data location encoding:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;[31:24]&lt;/code&gt;: RAMID = 0x02&lt;/li&gt; &lt;li&gt;&lt;code&gt;[23:20]&lt;/code&gt;: Reserved&lt;/li&gt; &lt;li&gt;&lt;code&gt;[19:18]&lt;/code&gt;: Way&lt;/li&gt; &lt;li&gt;&lt;code&gt;[17:15]&lt;/code&gt;: Reserved&lt;/li&gt; &lt;li&gt;&lt;code&gt;[14:5]&lt;/code&gt;: Index &lt;code&gt;[14:5]&lt;/code&gt;&lt;/li&gt; &lt;li&gt;&lt;code&gt;[4:0]&lt;/code&gt;: Reserved&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;它暗示了 L1 BTB（也就是 Main BTB）的 Index 是 PC[14:5]，这和我们之前的观察一致。这样算出来有 &lt;code&gt;2^(14-5+1)=1024&lt;/code&gt; 个 set，和我们前面的 6-way set associative，1024 sets 的猜测是一致的。&lt;/p&gt; &lt;p&gt;但是，这时候又出现一个问题：&lt;code&gt;[19:18]&lt;/code&gt; 只能记录两位的 Way 编号，也就是说不能超过 4 个 Way，但实际上有 6 个 Way。这似乎又出现了矛盾。&lt;/p&gt; &lt;p&gt;继续去阅读文档里对从 BTB 读出来的数据的描述：&lt;/p&gt; &lt;p&gt;L1 BTB cache format:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Instruction Register 0 [63:0]: Data [63:0]&lt;/li&gt; &lt;li&gt;Instruction Register 1 [17:0]: Data [81:64]&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;这暗示了给定一个 Index 和一个 Way，可以读出来 82 bit 的数据，这不太寻常：一个分支的信息，通常不需要这么多 bit 的数据。一个 BTB Entry，通常需要这些信息：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;valid&lt;/li&gt; &lt;li&gt;branch type: conditional or unconditional, direct or indirect, call or return, etc.&lt;/li&gt; &lt;li&gt;tag&lt;/li&gt; &lt;li&gt;replacement policy&lt;/li&gt; &lt;li&gt;part of target address&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;除非保存了完整的 target address 和 tag，是达不到 82 bit 这么多的。但是这样又显得很浪费，可能还有其他的可能性。&lt;/p&gt; &lt;p&gt;考虑到上面出现的两位的 Way 编号，并且有 3 的素数因子，只能是 3-way 组相连了。如果按 3-way 组相连，1024 个 set 来算，只有 3072 个 entry，距离 Main BTB 的容量 6144 个 entry 刚好只有一半。一个想法诞生了：如果一个 BTB entry 可以保存两个分支的信息呢？82 bit 正好是 2 的倍数，除以二是 41 bit，每个分支存 41 bit 的数据是比较合理的数据。这样，就可以推导出来，它 Main BTB 的组织方式是：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Index: PC[14:5]，有 1024 个 set&lt;/li&gt; &lt;li&gt;3-Way 组相连&lt;/li&gt; &lt;li&gt;每个 Entry 是 82 bit，可以记录两条分支的信息&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;所以 BTB 的 Entry 怎么计算其实会比较复杂，到底是按实际的 Entry 数，还是按分支数，需要深入分析才能理解。&lt;/p&gt; &lt;p&gt;那么，为什么要把两条分支保存在一个 BTB Entry 里呢？Neoverse N1 并没有实现 two taken，似乎并没有放在一起的必要。而且虽然是 3-Way 组相连，匹配的时候还是 6-Way 的，那么这样做的好处是什么呢？&lt;/p&gt; &lt;p&gt;这时候就要提到很多处理器实现的一个优化了：大多数分支，它的目的地址距离它自己是很短的，即使考虑指令支持的最大范围，比如 AArch64 指令里面，B 指令的立即数是 26 位，B.cond 和 CBNZ 的立即数是 19 位，也比完整的虚拟地址空间小很多。针对多数的跳转距离比较短的分支，可以用一个更压缩的表示来保存，使得 BTB 可以保存更多的分支；同时，也保留针对跳转距离比较长的分支的支持。这和前面的这个设计就对上了：对于跳转距离短的分支，每 41 bit 可以保存一条分支的信息；对于跳转距离远的分支，再用 82 bit 来保存一条分支的信息。从另外一个角度来说，41 bit 也确实保存不下完整的虚拟地址，所以需要有一个方案给跳转距离远的分支兜底。&lt;/p&gt; &lt;p&gt;那么如果跳转距离比较远，Main BTB 的容量将会只有一半。感兴趣的读者可以设计实验来验证这一点。&lt;/p&gt; &lt;p&gt;小结：Main BTB 是 1024 set，3 way set associative 的结构，一共 3072 个 entry，每个 entry 可以保存两条分支，Index 是 PC[14:5]。stride=4B 的情况下，会出现一个 set 内 8 条分支的情况，无法在 3 个 entry 内放下，所以总是会出现缺失。一共占用 &lt;code&gt;3072*82=251904&lt;/code&gt; bit 也就是 30.75 KB 的空间。&lt;/p&gt; &lt;h3 id=&#34;stride8b-的情况下只观察到-4096-的-main-btb-容量而不是-6144&#34;&gt;stride=8B 的情况下，只观察到 4096 的 Main BTB 容量，而不是 6144&lt;a class=&#34;headerlink&#34; href=&#34;#stride8b-的情况下只观察到-4096-的-main-btb-容量而不是-6144&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;在 stride=8B 的情况下，只观察到 4096 的 Main BTB 容量，实际上，用刚才分析的 Main BTB 结构，就可以分析出来。&lt;/p&gt; &lt;p&gt;首先，这个测试的构造方法是，给定分支数和 stride，按照这个 stride 在连续的一段虚拟地址上分布这些分支。以 stride=8B 为例，那么分支 i 的地址就是 &lt;code&gt;8*i&lt;/code&gt;（实际情况下高位不是 0，但是所有的分支的高位是相同的，例如 &lt;code&gt;0x100000000+8*i&lt;/code&gt;，但这不影响分析）。我们来观察一下前几个分支的信息：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Branch 0: addr=0x00, index=0&lt;/li&gt; &lt;li&gt;Branch 1: addr=0x08, index=0&lt;/li&gt; &lt;li&gt;Branch 2: addr=0x10, index=0&lt;/li&gt; &lt;li&gt;Branch 3: addr=0x18, index=0&lt;/li&gt; &lt;li&gt;Branch 4: addr=0x20, index=1&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;可以看到从分支 5 开始，到了一个新的 set，第一个 set 内出现了 4 条分支，小于一个 set 内可以保存的最多 6 条分支。接下来看从分支 4096 开始的几个分支：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Branch 4096: addr=0x8000, index=0&lt;/li&gt; &lt;li&gt;Branch 4097: addr=0x8008, index=0&lt;/li&gt; &lt;li&gt;Branch 4098: addr=0x8010, index=0&lt;/li&gt; &lt;li&gt;Branch 4099: addr=0x8018, index=0&lt;/li&gt; &lt;li&gt;Branch 4100: addr=0x8020, index=1&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;可以看到，index=0 这个 set 出现了 8 个 Branch：Branch 0-3 和 Branch 4096-4099，已经大于一个 set 内可以保存的最多 6 条分支。虽然 Main BTB 容量是 6144，但由于分支的排布方式，会首先在一个 set 里出现溢出。然后随着分支继续增加，产生溢出的 set 的比例逐渐上升，直到 8192 条分支的时候，每个 set 都完全溢出了。此时也恰好遇到了 64KB ICache 的瓶颈，如果 ICache 更大，应该会在 8192 的地方观察到一个平台，此时 Main BTB 完全缺失。&lt;/p&gt; &lt;p&gt;继续增加 stride，就没有了这个问题。以 stride=16B 为例子，Branch i 地址是 &lt;code&gt;i*16&lt;/code&gt;，那么这些分支的地址是：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Branch 0: addr=0x00, index=0&lt;/li&gt; &lt;li&gt;Branch 1: addr=0x10, index=0&lt;/li&gt; &lt;li&gt;Branch 2: addr=0x20, index=1&lt;/li&gt; &lt;li&gt;Branch 3: addr=0x30, index=1&lt;/li&gt; &lt;li&gt;... &lt;/li&gt; &lt;li&gt;Branch 2048: addr=0x8000, index=0&lt;/li&gt; &lt;li&gt;Branch 2049: addr=0x8010, index=0&lt;/li&gt; &lt;li&gt;Branch 2050: addr=0x8020, index=1&lt;/li&gt; &lt;li&gt;Branch 2051: addr=0x8030, index=1&lt;/li&gt; &lt;li&gt;... &lt;/li&gt; &lt;li&gt;Branch 4096: addr=0x10000, index=0&lt;/li&gt; &lt;li&gt;Branch 4097: addr=0x10010, index=0&lt;/li&gt; &lt;li&gt;Branch 4098: addr=0x10020, index=1&lt;/li&gt; &lt;li&gt;Branch 4099: addr=0x10030, index=1&lt;/li&gt; &lt;li&gt;... &lt;/li&gt; &lt;li&gt;Branch 6144: addr=0x18000, index=0&lt;/li&gt; &lt;li&gt;Branch 6145: addr=0x18010, index=0&lt;/li&gt; &lt;li&gt;Branch 6146: addr=0x18020, index=1&lt;/li&gt; &lt;li&gt;Branch 6147: addr=0x18030, index=1&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;这个时候，每个 set 会以两个 branch 的粒度来增加，由于 6 是 2 的倍数，所以从 4096 开始，set 逐渐被填满，会等到 6144 条分支才会产生溢出。&lt;/p&gt; &lt;p&gt;小结：由于 Main BTB 的 Index 是 PC[14:5]，所以在 stride=8B 的情况下，每个 set 内以 4 个 branch 的粒度来增加，会有部分 set 已经出现溢出（只能存 6 个分支，但需要存 8 个分支），而另一部分 set 还没有满的情况（能存 6 个分支，但只存了 4 个分支）。这个拐点就是 4096 条分支。&lt;/p&gt; &lt;h3 id=&#34;stride8b-的情况下在-main-btb-命中的范围内cpi275stride16b-的情况下在-main-btb-命中的范围内cpi25stride32b-或-64b-或-128b-的情况下在-main-btb-命中的范围内cpi2&#34;&gt;stride=8B 的情况下，在 Main BTB 命中的范围内，CPI=2.75；stride=16B 的情况下，在 Main BTB 命中的范围内，CPI=2.5；stride=32B 或 64B 或 128B 的情况下，在 Main BTB 命中的范围内，CPI=2&lt;a class=&#34;headerlink&#34; href=&#34;#stride8b-的情况下在-main-btb-命中的范围内cpi275stride16b-的情况下在-main-btb-命中的范围内cpi25stride32b-或-64b-或-128b-的情况下在-main-btb-命中的范围内cpi2&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;前面提到，命中 Main BTB 的时候，其实 CPI 并不是 3，而是 2 到 3 之间的一个数，这似乎意味着 Main BTB 并非总是 3 周期提供一个预测。考虑到 Main BTB 容量比较大，很难单周期提供一个预测，猜测 Main BTB 可以两周期或者三周期提供一个预测。那么为什么会在不同的延迟下给出预测结果呢？&lt;/p&gt; &lt;p&gt;首先来分析一下 Main BTB 是如何做预测的：它首先会用传入的 VA 访问 SRAM，得到 3 个 82-bit 的数据，里面最多可以存 6 条分支指令的信息。得到这些数据以后，进行 tag 比较，筛选出其中匹配的部分。如果没有匹配的，或者只有一个匹配的分支，那都好说。但是，如果有多条匹配的分支呢？&lt;/p&gt; &lt;p&gt;例如，这是一个对齐的 32B 块，里面有 8 条 4 字节的指令：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-0-1&#34;&gt;&lt;a id=&#34;__codelineno-0-1&#34; name=&#34;__codelineno-0-1&#34; href=&#34;#__codelineno-0-1&#34;&gt;&lt;/a&gt;0 4 8 12 16 20 24 28 &lt;/span&gt;&lt;span id=&#34;__span-0-2&#34;&gt;&lt;a id=&#34;__codelineno-0-2&#34; name=&#34;__codelineno-0-2&#34; href=&#34;#__codelineno-0-2&#34;&gt;&lt;/a&gt;+-----+-----+-----+-----+-----+-----+-----+-----+ &lt;/span&gt;&lt;span id=&#34;__span-0-3&#34;&gt;&lt;a id=&#34;__codelineno-0-3&#34; name=&#34;__codelineno-0-3&#34; href=&#34;#__codelineno-0-3&#34;&gt;&lt;/a&gt;| NOP | NOP | Br | NOP | NOP | NOP | Br | NOP | &lt;/span&gt;&lt;span id=&#34;__span-0-4&#34;&gt;&lt;a id=&#34;__codelineno-0-4&#34; name=&#34;__codelineno-0-4&#34; href=&#34;#__codelineno-0-4&#34;&gt;&lt;/a&gt;+-----+-----+-----+-----+-----+-----+-----+-----+ &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;假如要从地址 4 处开始执行，那么 Main BTB 应该要得到的是位于地址 8 的分支的信息；假如要从地址 16 处开始执行，那么 Main BTB 应该要得到的是位于地址 24 的分支的信息。为了实现这个事情，硬件上应该：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;首先找到在同一个 32B 块内的所有分支：通过 tag 比对，找到这个 set 内的在该 32B 内的所有分支&lt;/li&gt; &lt;li&gt;接着，找到比输入的 VA &lt;strong&gt;大于或者等于&lt;/strong&gt;的&lt;strong&gt;第一个&lt;/strong&gt;分支&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;这个逻辑是比较复杂的，首先要筛选出地址大于或等于输入的 VA 的分支，其次要找到其中 VA 最小的分支。一个思路是保证 BTB 里面的 VA 是排好序的，但是硬件上排序并不好做，而且即使排序了，也需要做类似二分搜索的事情。另一个思路就是不管顺序，用组合逻辑把所有可能性都考虑到，计算出要找的分支。&lt;/p&gt; &lt;p&gt;但是这个组合逻辑比较复杂，本质上就是一个 filter+min 操作，需要比较大的延迟。三个周期能做下来，但是两个周期内，就做不下这么复杂的组合逻辑了。那怎么办呢？&lt;/p&gt; &lt;p&gt;观察一下 CPI 比 3 小的情况：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;stride=8B 的 CPI=2.75&lt;/li&gt; &lt;li&gt;stride=16B 的 CPI=2.5&lt;/li&gt; &lt;li&gt;stride=32B 或 64B 或 128B 的 CPI=2&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;可以看到，随着 stride 增加，CPI 逐渐减少，到 stride=32B 的时候，能够稳定地达到 CPI=2 的情况。设想 Main BTB 有一个 2 周期出结果的 fast path，那么它此时可以稳定地触发；而 stride=16B 只有一半的时候可以触发 fast path：&lt;code&gt;0.5*2+0.5*3=2.5&lt;/code&gt;；stride=8B 只有四分之一的时候可以触发 fast path：&lt;code&gt;0.25*2+0.75*3=2.75&lt;/code&gt;。这样这些 CPI 都说得通了，其实就是有多大的概率能够触发 fast path。那么 fast path 生效的比例是：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;stride=8B 有四分之一的概率走 fast path&lt;/li&gt; &lt;li&gt;stride=16B 有二分之一的概率走 fast path&lt;/li&gt; &lt;li&gt;stride=32B 或 64B 或 128B 一定可以走 fast path&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;此时你可能已经发现了一些规律：&lt;code&gt;32/4=8&lt;/code&gt;，然后 &lt;code&gt;32/2=16&lt;/code&gt;。也就是说，当对齐的 32B 块里，有四条分支的时候，平均只有一条分支可以走 fast path；有两条分支的时候，平均也是一条分支可以走 fast path；只有一条分支的时候，它总是可以走 fast path。&lt;/p&gt; &lt;p&gt;再回想一下前面的匹配逻辑：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;找到该 32B 块内所有的分支：这一步免不了&lt;/li&gt; &lt;li&gt;找到大于或等于输入 VA 地址的所有分支：这一步也免不了&lt;/li&gt; &lt;li&gt;找到第一个满足要求的分支：如果只有一条分支，那就不用寻找最小值了，这就是 fast path 的条件&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;这就解释了前面的现象：当 stride=8B 的时候，对齐的 32B 块内部是：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-1-1&#34;&gt;&lt;a id=&#34;__codelineno-1-1&#34; name=&#34;__codelineno-1-1&#34; href=&#34;#__codelineno-1-1&#34;&gt;&lt;/a&gt;0 4 8 12 16 20 24 28 &lt;/span&gt;&lt;span id=&#34;__span-1-2&#34;&gt;&lt;a id=&#34;__codelineno-1-2&#34; name=&#34;__codelineno-1-2&#34; href=&#34;#__codelineno-1-2&#34;&gt;&lt;/a&gt;+-----+-----+-----+-----+-----+-----+-----+-----+ &lt;/span&gt;&lt;span id=&#34;__span-1-3&#34;&gt;&lt;a id=&#34;__codelineno-1-3&#34; name=&#34;__codelineno-1-3&#34; href=&#34;#__codelineno-1-3&#34;&gt;&lt;/a&gt;| Br | NOP | Br | NOP | Br | NOP | Br | NOP | &lt;/span&gt;&lt;span id=&#34;__span-1-4&#34;&gt;&lt;a id=&#34;__codelineno-1-4&#34; name=&#34;__codelineno-1-4&#34; href=&#34;#__codelineno-1-4&#34;&gt;&lt;/a&gt;+-----+-----+-----+-----+-----+-----+-----+-----+ &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;分支预测的时候，用的地址分别是 0、8、16 和 24。当用 0、8 和 16 的输入 VA 查询的时候，分别能找到 4、3 和 2 条 VA 大于或等于输入 VA 的分支。只有在用 24 的输入 VA 查询的时候，只能找到一条分支，不需要再求 min。&lt;/p&gt; &lt;p&gt;stride=16B 的情况类似，在预测第二条分支的时候，只有一条分支满足要求，可以走 fast path。&lt;/p&gt; &lt;p&gt;stride=32B 或更大的时候，对齐的 32B 块内都只有一条分支，满足走 fast path 的条件。&lt;/p&gt; &lt;p&gt;这就解释了前面看到的各种奇怪的 CPI 现象。&lt;/p&gt; &lt;p&gt;那么，为什么只有 Main BTB 会出现这种现象呢，理论上来说，Nano BTB 和 Micro BTB 也可以做类似的优化？这就涉及到了 BTB 的不同的组织方式：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;一种是 Main BTB 这种，每条分支只保存一份，那么为了找到某个 VA 开始的第一条分支，就需要把满足要求的分支都找出来，再寻找地址最小的那一个；具体实现上，也有两种情况：&lt;ol&gt; &lt;li&gt;对于每个可能出现分支指令的地址，都进行一次 BTB 查询（这种结构叫 Instruction BTB）&lt;/li&gt; &lt;li&gt;对于每个对齐的块，记录这个块内的有限条分支的信息（这种结构叫 Region BTB），Main BTB 采用的就是这种，每个对齐的 32B 块内最多保存六条分支&lt;/li&gt; &lt;/ol&gt; &lt;/li&gt; &lt;li&gt;另一种结构，则是直接记录从某个 VA 开始的第一条分支，即给定 VA，查询 BTB 后，匹配到的 entry 里记录的就是从这个 VA 开始的第一条分支（这种结构叫做 Block BTB）；这样一条分支可能会出现在多个 entry 内，此时就不会涉及到上面所述的 fast path 优化&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;那么猜测 Nano BTB 和 Micro BTB 采用了 Block BTB 的方法，或者因为延迟本身就足够低，即使可以做 fast path，也没有引入 fast path 优化。&lt;/p&gt; &lt;p&gt;详细的 BTB 设计分析，可以参考 &lt;a href=&#34;../../../../2024/09/12/brief-into-ooo-3/&#34;&gt;浅谈乱序执行 CPU（三：前端）&lt;/a&gt; 的相关内容。&lt;/p&gt; &lt;p&gt;小结：Main BTB 可以在 2 或 3 周期提供预测，其中 2 周期预测的条件是，只找到一条 VA 大于或等于输入 VA 的分支，此时可以跳过求 min 的组合逻辑，在第二个周期给出预测。&lt;/p&gt; &lt;h2 id=&#34;模拟&#34;&gt;模拟&lt;a class=&#34;headerlink&#34; href=&#34;#模拟&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;既然已经知道了它的 BTB 结构，就写了一段程序来模拟它的工作过程：&lt;/p&gt; &lt;div class=&#34;language-cpp highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-2-1&#34;&gt;&lt;a id=&#34;__codelineno-2-1&#34; name=&#34;__codelineno-2-1&#34; href=&#34;#__codelineno-2-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// Cortex-A76/Neoverse-N1 BTB model&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-2&#34;&gt;&lt;a id=&#34;__codelineno-2-2&#34; name=&#34;__codelineno-2-2&#34; href=&#34;#__codelineno-2-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// 16-entry Nano BTB, fully associative, 1 cycle latency.&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-3&#34;&gt;&lt;a id=&#34;__codelineno-2-3&#34; name=&#34;__codelineno-2-3&#34; href=&#34;#__codelineno-2-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// 64-entry Micro BTB, fully associative, 2 cycle latency.&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-4&#34;&gt;&lt;a id=&#34;__codelineno-2-4&#34; name=&#34;__codelineno-2-4&#34; href=&#34;#__codelineno-2-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// 3072-entry Main BTB, 3-way set associative, 2-3 cycle latency, each entry at&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-5&#34;&gt;&lt;a id=&#34;__codelineno-2-5&#34; name=&#34;__codelineno-2-5&#34; href=&#34;#__codelineno-2-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// most 2 branches, index PC[14:5].&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-6&#34;&gt;&lt;a id=&#34;__codelineno-2-6&#34; name=&#34;__codelineno-2-6&#34; href=&#34;#__codelineno-2-6&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-7&#34;&gt;&lt;a id=&#34;__codelineno-2-7&#34; name=&#34;__codelineno-2-7&#34; href=&#34;#__codelineno-2-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cpf&#34;&gt;&amp;lt;assert.h&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-8&#34;&gt;&lt;a id=&#34;__codelineno-2-8&#34; name=&#34;__codelineno-2-8&#34; href=&#34;#__codelineno-2-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cpf&#34;&gt;&amp;lt;set&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-9&#34;&gt;&lt;a id=&#34;__codelineno-2-9&#34; name=&#34;__codelineno-2-9&#34; href=&#34;#__codelineno-2-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cpf&#34;&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-10&#34;&gt;&lt;a id=&#34;__codelineno-2-10&#34; name=&#34;__codelineno-2-10&#34; href=&#34;#__codelineno-2-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cpf&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-11&#34;&gt;&lt;a id=&#34;__codelineno-2-11&#34; name=&#34;__codelineno-2-11&#34; href=&#34;#__codelineno-2-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cpf&#34;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-12&#34;&gt;&lt;a id=&#34;__codelineno-2-12&#34; name=&#34;__codelineno-2-12&#34; href=&#34;#__codelineno-2-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cpf&#34;&gt;&amp;lt;utility&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-13&#34;&gt;&lt;a id=&#34;__codelineno-2-13&#34; name=&#34;__codelineno-2-13&#34; href=&#34;#__codelineno-2-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cpf&#34;&gt;&amp;lt;vector&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-14&#34;&gt;&lt;a id=&#34;__codelineno-2-14&#34; name=&#34;__codelineno-2-14&#34; href=&#34;#__codelineno-2-14&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-15&#34;&gt;&lt;a id=&#34;__codelineno-2-15&#34; name=&#34;__codelineno-2-15&#34; href=&#34;#__codelineno-2-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BTBEntry&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-16&#34;&gt;&lt;a id=&#34;__codelineno-2-16&#34; name=&#34;__codelineno-2-16&#34; href=&#34;#__codelineno-2-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;valid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-17&#34;&gt;&lt;a id=&#34;__codelineno-2-17&#34; name=&#34;__codelineno-2-17&#34; href=&#34;#__codelineno-2-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-18&#34;&gt;&lt;a id=&#34;__codelineno-2-18&#34; name=&#34;__codelineno-2-18&#34; href=&#34;#__codelineno-2-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-19&#34;&gt;&lt;a id=&#34;__codelineno-2-19&#34; name=&#34;__codelineno-2-19&#34; href=&#34;#__codelineno-2-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-20&#34;&gt;&lt;a id=&#34;__codelineno-2-20&#34; name=&#34;__codelineno-2-20&#34; href=&#34;#__codelineno-2-20&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-21&#34;&gt;&lt;a id=&#34;__codelineno-2-21&#34; name=&#34;__codelineno-2-21&#34; href=&#34;#__codelineno-2-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;typedef&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BTBEntry&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;NanoBTBEntry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-22&#34;&gt;&lt;a id=&#34;__codelineno-2-22&#34; name=&#34;__codelineno-2-22&#34; href=&#34;#__codelineno-2-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;typedef&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BTBEntry&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MicroBTBEntry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-23&#34;&gt;&lt;a id=&#34;__codelineno-2-23&#34; name=&#34;__codelineno-2-23&#34; href=&#34;#__codelineno-2-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;typedef&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BTBEntry&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MainBTBEntry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-24&#34;&gt;&lt;a id=&#34;__codelineno-2-24&#34; name=&#34;__codelineno-2-24&#34; href=&#34;#__codelineno-2-24&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-25&#34;&gt;&lt;a id=&#34;__codelineno-2-25&#34; name=&#34;__codelineno-2-25&#34; href=&#34;#__codelineno-2-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Model&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-26&#34;&gt;&lt;a id=&#34;__codelineno-2-26&#34; name=&#34;__codelineno-2-26&#34; href=&#34;#__codelineno-2-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;NanoBTBEntry&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-27&#34;&gt;&lt;a id=&#34;__codelineno-2-27&#34; name=&#34;__codelineno-2-27&#34; href=&#34;#__codelineno-2-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MicroBTBEntry&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;microBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-28&#34;&gt;&lt;a id=&#34;__codelineno-2-28&#34; name=&#34;__codelineno-2-28&#34; href=&#34;#__codelineno-2-28&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// pretend as 6-way&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-29&#34;&gt;&lt;a id=&#34;__codelineno-2-29&#34; name=&#34;__codelineno-2-29&#34; href=&#34;#__codelineno-2-29&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MainBTBEntry&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-30&#34;&gt;&lt;a id=&#34;__codelineno-2-30&#34; name=&#34;__codelineno-2-30&#34; href=&#34;#__codelineno-2-30&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 64KB ICache, pretend as direct mapped&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-31&#34;&gt;&lt;a id=&#34;__codelineno-2-31&#34; name=&#34;__codelineno-2-31&#34; href=&#34;#__codelineno-2-31&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// index: PC[15:6]&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-32&#34;&gt;&lt;a id=&#34;__codelineno-2-32&#34; name=&#34;__codelineno-2-32&#34; href=&#34;#__codelineno-2-32&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// tag: PC[:16]&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-33&#34;&gt;&lt;a id=&#34;__codelineno-2-33&#34; name=&#34;__codelineno-2-33&#34; href=&#34;#__codelineno-2-33&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;iCache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;64&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-34&#34;&gt;&lt;a id=&#34;__codelineno-2-34&#34; name=&#34;__codelineno-2-34&#34; href=&#34;#__codelineno-2-34&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-35&#34;&gt;&lt;a id=&#34;__codelineno-2-35&#34; name=&#34;__codelineno-2-35&#34; href=&#34;#__codelineno-2-35&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// return latency&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-36&#34;&gt;&lt;a id=&#34;__codelineno-2-36&#34; name=&#34;__codelineno-2-36&#34; href=&#34;#__codelineno-2-36&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// use pc to predict a branch at pc, i.e. pva = pc&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-37&#34;&gt;&lt;a id=&#34;__codelineno-2-37&#34; name=&#34;__codelineno-2-37&#34; href=&#34;#__codelineno-2-37&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-38&#34;&gt;&lt;a id=&#34;__codelineno-2-38&#34; name=&#34;__codelineno-2-38&#34; href=&#34;#__codelineno-2-38&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// BTB miss penalty&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-39&#34;&gt;&lt;a id=&#34;__codelineno-2-39&#34; name=&#34;__codelineno-2-39&#34; href=&#34;#__codelineno-2-39&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Nano BTB at P1&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-40&#34;&gt;&lt;a id=&#34;__codelineno-2-40&#34; name=&#34;__codelineno-2-40&#34; href=&#34;#__codelineno-2-40&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-41&#34;&gt;&lt;a id=&#34;__codelineno-2-41&#34; name=&#34;__codelineno-2-41&#34; href=&#34;#__codelineno-2-41&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-42&#34;&gt;&lt;a id=&#34;__codelineno-2-42&#34; name=&#34;__codelineno-2-42&#34; href=&#34;#__codelineno-2-42&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Nano BTB hit&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-43&#34;&gt;&lt;a id=&#34;__codelineno-2-43&#34; name=&#34;__codelineno-2-43&#34; href=&#34;#__codelineno-2-43&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// LRU: move it to head&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-44&#34;&gt;&lt;a id=&#34;__codelineno-2-44&#34; name=&#34;__codelineno-2-44&#34; href=&#34;#__codelineno-2-44&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-45&#34;&gt;&lt;a id=&#34;__codelineno-2-45&#34; name=&#34;__codelineno-2-45&#34; href=&#34;#__codelineno-2-45&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-46&#34;&gt;&lt;a id=&#34;__codelineno-2-46&#34; name=&#34;__codelineno-2-46&#34; href=&#34;#__codelineno-2-46&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-47&#34;&gt;&lt;a id=&#34;__codelineno-2-47&#34; name=&#34;__codelineno-2-47&#34; href=&#34;#__codelineno-2-47&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-48&#34;&gt;&lt;a id=&#34;__codelineno-2-48&#34; name=&#34;__codelineno-2-48&#34; href=&#34;#__codelineno-2-48&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-49&#34;&gt;&lt;a id=&#34;__codelineno-2-49&#34; name=&#34;__codelineno-2-49&#34; href=&#34;#__codelineno-2-49&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-50&#34;&gt;&lt;a id=&#34;__codelineno-2-50&#34; name=&#34;__codelineno-2-50&#34; href=&#34;#__codelineno-2-50&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;main_btb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-51&#34;&gt;&lt;a id=&#34;__codelineno-2-51&#34; name=&#34;__codelineno-2-51&#34; href=&#34;#__codelineno-2-51&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-52&#34;&gt;&lt;a id=&#34;__codelineno-2-52&#34; name=&#34;__codelineno-2-52&#34; href=&#34;#__codelineno-2-52&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-53&#34;&gt;&lt;a id=&#34;__codelineno-2-53&#34; name=&#34;__codelineno-2-53&#34; href=&#34;#__codelineno-2-53&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-54&#34;&gt;&lt;a id=&#34;__codelineno-2-54&#34; name=&#34;__codelineno-2-54&#34; href=&#34;#__codelineno-2-54&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Nano BTB miss, check Micro BTB at P1&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-55&#34;&gt;&lt;a id=&#34;__codelineno-2-55&#34; name=&#34;__codelineno-2-55&#34; href=&#34;#__codelineno-2-55&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// like victim cache&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-56&#34;&gt;&lt;a id=&#34;__codelineno-2-56&#34; name=&#34;__codelineno-2-56&#34; href=&#34;#__codelineno-2-56&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-57&#34;&gt;&lt;a id=&#34;__codelineno-2-57&#34; name=&#34;__codelineno-2-57&#34; href=&#34;#__codelineno-2-57&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;microBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;microBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-58&#34;&gt;&lt;a id=&#34;__codelineno-2-58&#34; name=&#34;__codelineno-2-58&#34; href=&#34;#__codelineno-2-58&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Micro BTB hit&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-59&#34;&gt;&lt;a id=&#34;__codelineno-2-59&#34; name=&#34;__codelineno-2-59&#34; href=&#34;#__codelineno-2-59&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Move to Nano BTB&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-60&#34;&gt;&lt;a id=&#34;__codelineno-2-60&#34; name=&#34;__codelineno-2-60&#34; href=&#34;#__codelineno-2-60&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-61&#34;&gt;&lt;a id=&#34;__codelineno-2-61&#34; name=&#34;__codelineno-2-61&#34; href=&#34;#__codelineno-2-61&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;microBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;microBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-62&#34;&gt;&lt;a id=&#34;__codelineno-2-62&#34; name=&#34;__codelineno-2-62&#34; href=&#34;#__codelineno-2-62&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-63&#34;&gt;&lt;a id=&#34;__codelineno-2-63&#34; name=&#34;__codelineno-2-63&#34; href=&#34;#__codelineno-2-63&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;microBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-64&#34;&gt;&lt;a id=&#34;__codelineno-2-64&#34; name=&#34;__codelineno-2-64&#34; href=&#34;#__codelineno-2-64&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;microBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-65&#34;&gt;&lt;a id=&#34;__codelineno-2-65&#34; name=&#34;__codelineno-2-65&#34; href=&#34;#__codelineno-2-65&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-66&#34;&gt;&lt;a id=&#34;__codelineno-2-66&#34; name=&#34;__codelineno-2-66&#34; href=&#34;#__codelineno-2-66&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-67&#34;&gt;&lt;a id=&#34;__codelineno-2-67&#34; name=&#34;__codelineno-2-67&#34; href=&#34;#__codelineno-2-67&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-68&#34;&gt;&lt;a id=&#34;__codelineno-2-68&#34; name=&#34;__codelineno-2-68&#34; href=&#34;#__codelineno-2-68&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-69&#34;&gt;&lt;a id=&#34;__codelineno-2-69&#34; name=&#34;__codelineno-2-69&#34; href=&#34;#__codelineno-2-69&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-70&#34;&gt;&lt;a id=&#34;__codelineno-2-70&#34; name=&#34;__codelineno-2-70&#34; href=&#34;#__codelineno-2-70&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-71&#34;&gt;&lt;a id=&#34;__codelineno-2-71&#34; name=&#34;__codelineno-2-71&#34; href=&#34;#__codelineno-2-71&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-72&#34;&gt;&lt;a id=&#34;__codelineno-2-72&#34; name=&#34;__codelineno-2-72&#34; href=&#34;#__codelineno-2-72&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;main_btb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-73&#34;&gt;&lt;a id=&#34;__codelineno-2-73&#34; name=&#34;__codelineno-2-73&#34; href=&#34;#__codelineno-2-73&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-74&#34;&gt;&lt;a id=&#34;__codelineno-2-74&#34; name=&#34;__codelineno-2-74&#34; href=&#34;#__codelineno-2-74&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-75&#34;&gt;&lt;a id=&#34;__codelineno-2-75&#34; name=&#34;__codelineno-2-75&#34; href=&#34;#__codelineno-2-75&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-76&#34;&gt;&lt;a id=&#34;__codelineno-2-76&#34; name=&#34;__codelineno-2-76&#34; href=&#34;#__codelineno-2-76&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Micro BTB miss&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-77&#34;&gt;&lt;a id=&#34;__codelineno-2-77&#34; name=&#34;__codelineno-2-77&#34; href=&#34;#__codelineno-2-77&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;64&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-78&#34;&gt;&lt;a id=&#34;__codelineno-2-78&#34; name=&#34;__codelineno-2-78&#34; href=&#34;#__codelineno-2-78&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;microBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;microBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-79&#34;&gt;&lt;a id=&#34;__codelineno-2-79&#34; name=&#34;__codelineno-2-79&#34; href=&#34;#__codelineno-2-79&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-80&#34;&gt;&lt;a id=&#34;__codelineno-2-80&#34; name=&#34;__codelineno-2-80&#34; href=&#34;#__codelineno-2-80&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;microBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-81&#34;&gt;&lt;a id=&#34;__codelineno-2-81&#34; name=&#34;__codelineno-2-81&#34; href=&#34;#__codelineno-2-81&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;microBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-82&#34;&gt;&lt;a id=&#34;__codelineno-2-82&#34; name=&#34;__codelineno-2-82&#34; href=&#34;#__codelineno-2-82&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-83&#34;&gt;&lt;a id=&#34;__codelineno-2-83&#34; name=&#34;__codelineno-2-83&#34; href=&#34;#__codelineno-2-83&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-84&#34;&gt;&lt;a id=&#34;__codelineno-2-84&#34; name=&#34;__codelineno-2-84&#34; href=&#34;#__codelineno-2-84&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;j&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-85&#34;&gt;&lt;a id=&#34;__codelineno-2-85&#34; name=&#34;__codelineno-2-85&#34; href=&#34;#__codelineno-2-85&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-86&#34;&gt;&lt;a id=&#34;__codelineno-2-86&#34; name=&#34;__codelineno-2-86&#34; href=&#34;#__codelineno-2-86&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-87&#34;&gt;&lt;a id=&#34;__codelineno-2-87&#34; name=&#34;__codelineno-2-87&#34; href=&#34;#__codelineno-2-87&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nanoBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-88&#34;&gt;&lt;a id=&#34;__codelineno-2-88&#34; name=&#34;__codelineno-2-88&#34; href=&#34;#__codelineno-2-88&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-89&#34;&gt;&lt;a id=&#34;__codelineno-2-89&#34; name=&#34;__codelineno-2-89&#34; href=&#34;#__codelineno-2-89&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nl&#34;&gt;main_btb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-90&#34;&gt;&lt;a id=&#34;__codelineno-2-90&#34; name=&#34;__codelineno-2-90&#34; href=&#34;#__codelineno-2-90&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// check Main BTB&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-91&#34;&gt;&lt;a id=&#34;__codelineno-2-91&#34; name=&#34;__codelineno-2-91&#34; href=&#34;#__codelineno-2-91&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// PC[4:2]&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-92&#34;&gt;&lt;a id=&#34;__codelineno-2-92&#34; name=&#34;__codelineno-2-92&#34; href=&#34;#__codelineno-2-92&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;offset&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x1c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-93&#34;&gt;&lt;a id=&#34;__codelineno-2-93&#34; name=&#34;__codelineno-2-93&#34; href=&#34;#__codelineno-2-93&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// PC[14:5]&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-94&#34;&gt;&lt;a id=&#34;__codelineno-2-94&#34; name=&#34;__codelineno-2-94&#34; href=&#34;#__codelineno-2-94&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x7fe0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-95&#34;&gt;&lt;a id=&#34;__codelineno-2-95&#34; name=&#34;__codelineno-2-95&#34; href=&#34;#__codelineno-2-95&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;assert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-96&#34;&gt;&lt;a id=&#34;__codelineno-2-96&#34; name=&#34;__codelineno-2-96&#34; href=&#34;#__codelineno-2-96&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// PC[n:15]&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-97&#34;&gt;&lt;a id=&#34;__codelineno-2-97&#34; name=&#34;__codelineno-2-97&#34; href=&#34;#__codelineno-2-97&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tag&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-98&#34;&gt;&lt;a id=&#34;__codelineno-2-98&#34; name=&#34;__codelineno-2-98&#34; href=&#34;#__codelineno-2-98&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_offset&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;-1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-99&#34;&gt;&lt;a id=&#34;__codelineno-2-99&#34; name=&#34;__codelineno-2-99&#34; href=&#34;#__codelineno-2-99&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;-1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-100&#34;&gt;&lt;a id=&#34;__codelineno-2-100&#34; name=&#34;__codelineno-2-100&#34; href=&#34;#__codelineno-2-100&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;matches&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-101&#34;&gt;&lt;a id=&#34;__codelineno-2-101&#34; name=&#34;__codelineno-2-101&#34; href=&#34;#__codelineno-2-101&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-102&#34;&gt;&lt;a id=&#34;__codelineno-2-102&#34; name=&#34;__codelineno-2-102&#34; href=&#34;#__codelineno-2-102&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// find matches&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-103&#34;&gt;&lt;a id=&#34;__codelineno-2-103&#34; name=&#34;__codelineno-2-103&#34; href=&#34;#__codelineno-2-103&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tag&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;valid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-104&#34;&gt;&lt;a id=&#34;__codelineno-2-104&#34; name=&#34;__codelineno-2-104&#34; href=&#34;#__codelineno-2-104&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// check offset&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-105&#34;&gt;&lt;a id=&#34;__codelineno-2-105&#34; name=&#34;__codelineno-2-105&#34; href=&#34;#__codelineno-2-105&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x1c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;offset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-106&#34;&gt;&lt;a id=&#34;__codelineno-2-106&#34; name=&#34;__codelineno-2-106&#34; href=&#34;#__codelineno-2-106&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;-1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-107&#34;&gt;&lt;a id=&#34;__codelineno-2-107&#34; name=&#34;__codelineno-2-107&#34; href=&#34;#__codelineno-2-107&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-108&#34;&gt;&lt;a id=&#34;__codelineno-2-108&#34; name=&#34;__codelineno-2-108&#34; href=&#34;#__codelineno-2-108&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_offset&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x1c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-109&#34;&gt;&lt;a id=&#34;__codelineno-2-109&#34; name=&#34;__codelineno-2-109&#34; href=&#34;#__codelineno-2-109&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x1c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_offset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-110&#34;&gt;&lt;a id=&#34;__codelineno-2-110&#34; name=&#34;__codelineno-2-110&#34; href=&#34;#__codelineno-2-110&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-111&#34;&gt;&lt;a id=&#34;__codelineno-2-111&#34; name=&#34;__codelineno-2-111&#34; href=&#34;#__codelineno-2-111&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_offset&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x1c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-112&#34;&gt;&lt;a id=&#34;__codelineno-2-112&#34; name=&#34;__codelineno-2-112&#34; href=&#34;#__codelineno-2-112&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-113&#34;&gt;&lt;a id=&#34;__codelineno-2-113&#34; name=&#34;__codelineno-2-113&#34; href=&#34;#__codelineno-2-113&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;matches&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-114&#34;&gt;&lt;a id=&#34;__codelineno-2-114&#34; name=&#34;__codelineno-2-114&#34; href=&#34;#__codelineno-2-114&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-115&#34;&gt;&lt;a id=&#34;__codelineno-2-115&#34; name=&#34;__codelineno-2-115&#34; href=&#34;#__codelineno-2-115&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-116&#34;&gt;&lt;a id=&#34;__codelineno-2-116&#34; name=&#34;__codelineno-2-116&#34; href=&#34;#__codelineno-2-116&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-117&#34;&gt;&lt;a id=&#34;__codelineno-2-117&#34; name=&#34;__codelineno-2-117&#34; href=&#34;#__codelineno-2-117&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-118&#34;&gt;&lt;a id=&#34;__codelineno-2-118&#34; name=&#34;__codelineno-2-118&#34; href=&#34;#__codelineno-2-118&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// hit&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-119&#34;&gt;&lt;a id=&#34;__codelineno-2-119&#34; name=&#34;__codelineno-2-119&#34; href=&#34;#__codelineno-2-119&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_offset&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;offset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-120&#34;&gt;&lt;a id=&#34;__codelineno-2-120&#34; name=&#34;__codelineno-2-120&#34; href=&#34;#__codelineno-2-120&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;matches&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-121&#34;&gt;&lt;a id=&#34;__codelineno-2-121&#34; name=&#34;__codelineno-2-121&#34; href=&#34;#__codelineno-2-121&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// LRU&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-122&#34;&gt;&lt;a id=&#34;__codelineno-2-122&#34; name=&#34;__codelineno-2-122&#34; href=&#34;#__codelineno-2-122&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MainBTBEntry&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;temp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-123&#34;&gt;&lt;a id=&#34;__codelineno-2-123&#34; name=&#34;__codelineno-2-123&#34; href=&#34;#__codelineno-2-123&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-124&#34;&gt;&lt;a id=&#34;__codelineno-2-124&#34; name=&#34;__codelineno-2-124&#34; href=&#34;#__codelineno-2-124&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-125&#34;&gt;&lt;a id=&#34;__codelineno-2-125&#34; name=&#34;__codelineno-2-125&#34; href=&#34;#__codelineno-2-125&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-126&#34;&gt;&lt;a id=&#34;__codelineno-2-126&#34; name=&#34;__codelineno-2-126&#34; href=&#34;#__codelineno-2-126&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;temp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-127&#34;&gt;&lt;a id=&#34;__codelineno-2-127&#34; name=&#34;__codelineno-2-127&#34; href=&#34;#__codelineno-2-127&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-128&#34;&gt;&lt;a id=&#34;__codelineno-2-128&#34; name=&#34;__codelineno-2-128&#34; href=&#34;#__codelineno-2-128&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-129&#34;&gt;&lt;a id=&#34;__codelineno-2-129&#34; name=&#34;__codelineno-2-129&#34; href=&#34;#__codelineno-2-129&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;matches&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-130&#34;&gt;&lt;a id=&#34;__codelineno-2-130&#34; name=&#34;__codelineno-2-130&#34; href=&#34;#__codelineno-2-130&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// fast path&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-131&#34;&gt;&lt;a id=&#34;__codelineno-2-131&#34; name=&#34;__codelineno-2-131&#34; href=&#34;#__codelineno-2-131&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-132&#34;&gt;&lt;a id=&#34;__codelineno-2-132&#34; name=&#34;__codelineno-2-132&#34; href=&#34;#__codelineno-2-132&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-133&#34;&gt;&lt;a id=&#34;__codelineno-2-133&#34; name=&#34;__codelineno-2-133&#34; href=&#34;#__codelineno-2-133&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-134&#34;&gt;&lt;a id=&#34;__codelineno-2-134&#34; name=&#34;__codelineno-2-134&#34; href=&#34;#__codelineno-2-134&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-135&#34;&gt;&lt;a id=&#34;__codelineno-2-135&#34; name=&#34;__codelineno-2-135&#34; href=&#34;#__codelineno-2-135&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;matches&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-136&#34;&gt;&lt;a id=&#34;__codelineno-2-136&#34; name=&#34;__codelineno-2-136&#34; href=&#34;#__codelineno-2-136&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// slow path&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-137&#34;&gt;&lt;a id=&#34;__codelineno-2-137&#34; name=&#34;__codelineno-2-137&#34; href=&#34;#__codelineno-2-137&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-138&#34;&gt;&lt;a id=&#34;__codelineno-2-138&#34; name=&#34;__codelineno-2-138&#34; href=&#34;#__codelineno-2-138&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-139&#34;&gt;&lt;a id=&#34;__codelineno-2-139&#34; name=&#34;__codelineno-2-139&#34; href=&#34;#__codelineno-2-139&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-140&#34;&gt;&lt;a id=&#34;__codelineno-2-140&#34; name=&#34;__codelineno-2-140&#34; href=&#34;#__codelineno-2-140&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-141&#34;&gt;&lt;a id=&#34;__codelineno-2-141&#34; name=&#34;__codelineno-2-141&#34; href=&#34;#__codelineno-2-141&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-142&#34;&gt;&lt;a id=&#34;__codelineno-2-142&#34; name=&#34;__codelineno-2-142&#34; href=&#34;#__codelineno-2-142&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-143&#34;&gt;&lt;a id=&#34;__codelineno-2-143&#34; name=&#34;__codelineno-2-143&#34; href=&#34;#__codelineno-2-143&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-144&#34;&gt;&lt;a id=&#34;__codelineno-2-144&#34; name=&#34;__codelineno-2-144&#34; href=&#34;#__codelineno-2-144&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// miss&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-145&#34;&gt;&lt;a id=&#34;__codelineno-2-145&#34; name=&#34;__codelineno-2-145&#34; href=&#34;#__codelineno-2-145&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-146&#34;&gt;&lt;a id=&#34;__codelineno-2-146&#34; name=&#34;__codelineno-2-146&#34; href=&#34;#__codelineno-2-146&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-147&#34;&gt;&lt;a id=&#34;__codelineno-2-147&#34; name=&#34;__codelineno-2-147&#34; href=&#34;#__codelineno-2-147&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-148&#34;&gt;&lt;a id=&#34;__codelineno-2-148&#34; name=&#34;__codelineno-2-148&#34; href=&#34;#__codelineno-2-148&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-149&#34;&gt;&lt;a id=&#34;__codelineno-2-149&#34; name=&#34;__codelineno-2-149&#34; href=&#34;#__codelineno-2-149&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-150&#34;&gt;&lt;a id=&#34;__codelineno-2-150&#34; name=&#34;__codelineno-2-150&#34; href=&#34;#__codelineno-2-150&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainBTB&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;valid&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-151&#34;&gt;&lt;a id=&#34;__codelineno-2-151&#34; name=&#34;__codelineno-2-151&#34; href=&#34;#__codelineno-2-151&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-152&#34;&gt;&lt;a id=&#34;__codelineno-2-152&#34; name=&#34;__codelineno-2-152&#34; href=&#34;#__codelineno-2-152&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nl&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-153&#34;&gt;&lt;a id=&#34;__codelineno-2-153&#34; name=&#34;__codelineno-2-153&#34; href=&#34;#__codelineno-2-153&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// BTB miss&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-154&#34;&gt;&lt;a id=&#34;__codelineno-2-154&#34; name=&#34;__codelineno-2-154&#34; href=&#34;#__codelineno-2-154&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-155&#34;&gt;&lt;a id=&#34;__codelineno-2-155&#34; name=&#34;__codelineno-2-155&#34; href=&#34;#__codelineno-2-155&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// compute icache penalty&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-156&#34;&gt;&lt;a id=&#34;__codelineno-2-156&#34; name=&#34;__codelineno-2-156&#34; href=&#34;#__codelineno-2-156&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-157&#34;&gt;&lt;a id=&#34;__codelineno-2-157&#34; name=&#34;__codelineno-2-157&#34; href=&#34;#__codelineno-2-157&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tag&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-158&#34;&gt;&lt;a id=&#34;__codelineno-2-158&#34; name=&#34;__codelineno-2-158&#34; href=&#34;#__codelineno-2-158&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;iCache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tag&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-159&#34;&gt;&lt;a id=&#34;__codelineno-2-159&#34; name=&#34;__codelineno-2-159&#34; href=&#34;#__codelineno-2-159&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// extra 4 cycle penalty&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-160&#34;&gt;&lt;a id=&#34;__codelineno-2-160&#34; name=&#34;__codelineno-2-160&#34; href=&#34;#__codelineno-2-160&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-161&#34;&gt;&lt;a id=&#34;__codelineno-2-161&#34; name=&#34;__codelineno-2-161&#34; href=&#34;#__codelineno-2-161&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;iCache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tag&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-162&#34;&gt;&lt;a id=&#34;__codelineno-2-162&#34; name=&#34;__codelineno-2-162&#34; href=&#34;#__codelineno-2-162&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-163&#34;&gt;&lt;a id=&#34;__codelineno-2-163&#34; name=&#34;__codelineno-2-163&#34; href=&#34;#__codelineno-2-163&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-164&#34;&gt;&lt;a id=&#34;__codelineno-2-164&#34; name=&#34;__codelineno-2-164&#34; href=&#34;#__codelineno-2-164&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-165&#34;&gt;&lt;a id=&#34;__codelineno-2-165&#34; name=&#34;__codelineno-2-165&#34; href=&#34;#__codelineno-2-165&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-166&#34;&gt;&lt;a id=&#34;__codelineno-2-166&#34; name=&#34;__codelineno-2-166&#34; href=&#34;#__codelineno-2-166&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-167&#34;&gt;&lt;a id=&#34;__codelineno-2-167&#34; name=&#34;__codelineno-2-167&#34; href=&#34;#__codelineno-2-167&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-168&#34;&gt;&lt;a id=&#34;__codelineno-2-168&#34; name=&#34;__codelineno-2-168&#34; href=&#34;#__codelineno-2-168&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-169&#34;&gt;&lt;a id=&#34;__codelineno-2-169&#34; name=&#34;__codelineno-2-169&#34; href=&#34;#__codelineno-2-169&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;FILE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fopen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;btb_size.csv&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;w&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-170&#34;&gt;&lt;a id=&#34;__codelineno-2-170&#34; name=&#34;__codelineno-2-170&#34; href=&#34;#__codelineno-2-170&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_size&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-171&#34;&gt;&lt;a id=&#34;__codelineno-2-171&#34; name=&#34;__codelineno-2-171&#34; href=&#34;#__codelineno-2-171&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;max_size&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;16384&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-172&#34;&gt;&lt;a id=&#34;__codelineno-2-172&#34; name=&#34;__codelineno-2-172&#34; href=&#34;#__codelineno-2-172&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;max_product&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1048576&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-173&#34;&gt;&lt;a id=&#34;__codelineno-2-173&#34; name=&#34;__codelineno-2-173&#34; href=&#34;#__codelineno-2-173&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vector&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mults&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;13&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;17&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;19&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-174&#34;&gt;&lt;a id=&#34;__codelineno-2-174&#34; name=&#34;__codelineno-2-174&#34; href=&#34;#__codelineno-2-174&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;21&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;23&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;27&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;29&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;31&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;33&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;35&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;37&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;39&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-175&#34;&gt;&lt;a id=&#34;__codelineno-2-175&#34; name=&#34;__codelineno-2-175&#34; href=&#34;#__codelineno-2-175&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-176&#34;&gt;&lt;a id=&#34;__codelineno-2-176&#34; name=&#34;__codelineno-2-176&#34; href=&#34;#__codelineno-2-176&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;pattern,size,stride,min,avg,max&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-177&#34;&gt;&lt;a id=&#34;__codelineno-2-177&#34; name=&#34;__codelineno-2-177&#34; href=&#34;#__codelineno-2-177&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stride&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stride&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;128&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stride&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-178&#34;&gt;&lt;a id=&#34;__codelineno-2-178&#34; name=&#34;__codelineno-2-178&#34; href=&#34;#__codelineno-2-178&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sizes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-179&#34;&gt;&lt;a id=&#34;__codelineno-2-179&#34; name=&#34;__codelineno-2-179&#34; href=&#34;#__codelineno-2-179&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size_base&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;min_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size_base&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;max_product&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stride&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-180&#34;&gt;&lt;a id=&#34;__codelineno-2-180&#34; name=&#34;__codelineno-2-180&#34; href=&#34;#__codelineno-2-180&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size_base&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-181&#34;&gt;&lt;a id=&#34;__codelineno-2-181&#34; name=&#34;__codelineno-2-181&#34; href=&#34;#__codelineno-2-181&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mult&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mults&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-182&#34;&gt;&lt;a id=&#34;__codelineno-2-182&#34; name=&#34;__codelineno-2-182&#34; href=&#34;#__codelineno-2-182&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size_base&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mult&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-183&#34;&gt;&lt;a id=&#34;__codelineno-2-183&#34; name=&#34;__codelineno-2-183&#34; href=&#34;#__codelineno-2-183&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size_base&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mult&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stride&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;max_product&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-184&#34;&gt;&lt;a id=&#34;__codelineno-2-184&#34; name=&#34;__codelineno-2-184&#34; href=&#34;#__codelineno-2-184&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;max_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-185&#34;&gt;&lt;a id=&#34;__codelineno-2-185&#34; name=&#34;__codelineno-2-185&#34; href=&#34;#__codelineno-2-185&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-186&#34;&gt;&lt;a id=&#34;__codelineno-2-186&#34; name=&#34;__codelineno-2-186&#34; href=&#34;#__codelineno-2-186&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sizes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;insert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-187&#34;&gt;&lt;a id=&#34;__codelineno-2-187&#34; name=&#34;__codelineno-2-187&#34; href=&#34;#__codelineno-2-187&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-188&#34;&gt;&lt;a id=&#34;__codelineno-2-188&#34; name=&#34;__codelineno-2-188&#34; href=&#34;#__codelineno-2-188&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-189&#34;&gt;&lt;a id=&#34;__codelineno-2-189&#34; name=&#34;__codelineno-2-189&#34; href=&#34;#__codelineno-2-189&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-190&#34;&gt;&lt;a id=&#34;__codelineno-2-190&#34; name=&#34;__codelineno-2-190&#34; href=&#34;#__codelineno-2-190&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-191&#34;&gt;&lt;a id=&#34;__codelineno-2-191&#34; name=&#34;__codelineno-2-191&#34; href=&#34;#__codelineno-2-191&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sizes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-192&#34;&gt;&lt;a id=&#34;__codelineno-2-192&#34; name=&#34;__codelineno-2-192&#34; href=&#34;#__codelineno-2-192&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Model&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-193&#34;&gt;&lt;a id=&#34;__codelineno-2-193&#34; name=&#34;__codelineno-2-193&#34; href=&#34;#__codelineno-2-193&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-194&#34;&gt;&lt;a id=&#34;__codelineno-2-194&#34; name=&#34;__codelineno-2-194&#34; href=&#34;#__codelineno-2-194&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cycles&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-195&#34;&gt;&lt;a id=&#34;__codelineno-2-195&#34; name=&#34;__codelineno-2-195&#34; href=&#34;#__codelineno-2-195&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;branch_count&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-196&#34;&gt;&lt;a id=&#34;__codelineno-2-196&#34; name=&#34;__codelineno-2-196&#34; href=&#34;#__codelineno-2-196&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// warmup&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-197&#34;&gt;&lt;a id=&#34;__codelineno-2-197&#34; name=&#34;__codelineno-2-197&#34; href=&#34;#__codelineno-2-197&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;branch_count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-198&#34;&gt;&lt;a id=&#34;__codelineno-2-198&#34; name=&#34;__codelineno-2-198&#34; href=&#34;#__codelineno-2-198&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stride&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-199&#34;&gt;&lt;a id=&#34;__codelineno-2-199&#34; name=&#34;__codelineno-2-199&#34; href=&#34;#__codelineno-2-199&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stride&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-200&#34;&gt;&lt;a id=&#34;__codelineno-2-200&#34; name=&#34;__codelineno-2-200&#34; href=&#34;#__codelineno-2-200&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-201&#34;&gt;&lt;a id=&#34;__codelineno-2-201&#34; name=&#34;__codelineno-2-201&#34; href=&#34;#__codelineno-2-201&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-202&#34;&gt;&lt;a id=&#34;__codelineno-2-202&#34; name=&#34;__codelineno-2-202&#34; href=&#34;#__codelineno-2-202&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-203&#34;&gt;&lt;a id=&#34;__codelineno-2-203&#34; name=&#34;__codelineno-2-203&#34; href=&#34;#__codelineno-2-203&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// test&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-204&#34;&gt;&lt;a id=&#34;__codelineno-2-204&#34; name=&#34;__codelineno-2-204&#34; href=&#34;#__codelineno-2-204&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;branch_count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-205&#34;&gt;&lt;a id=&#34;__codelineno-2-205&#34; name=&#34;__codelineno-2-205&#34; href=&#34;#__codelineno-2-205&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stride&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-206&#34;&gt;&lt;a id=&#34;__codelineno-2-206&#34; name=&#34;__codelineno-2-206&#34; href=&#34;#__codelineno-2-206&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint64_t&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;%&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stride&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-207&#34;&gt;&lt;a id=&#34;__codelineno-2-207&#34; name=&#34;__codelineno-2-207&#34; href=&#34;#__codelineno-2-207&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cycles&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;target&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-208&#34;&gt;&lt;a id=&#34;__codelineno-2-208&#34; name=&#34;__codelineno-2-208&#34; href=&#34;#__codelineno-2-208&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-209&#34;&gt;&lt;a id=&#34;__codelineno-2-209&#34; name=&#34;__codelineno-2-209&#34; href=&#34;#__codelineno-2-209&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cpi&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cycles&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;branch_count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-210&#34;&gt;&lt;a id=&#34;__codelineno-2-210&#34; name=&#34;__codelineno-2-210&#34; href=&#34;#__codelineno-2-210&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;0,%d,%d,%.2f,%.2f,%.2f&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stride&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cpi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cpi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cpi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-211&#34;&gt;&lt;a id=&#34;__codelineno-2-211&#34; name=&#34;__codelineno-2-211&#34; href=&#34;#__codelineno-2-211&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fflush&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-212&#34;&gt;&lt;a id=&#34;__codelineno-2-212&#34; name=&#34;__codelineno-2-212&#34; href=&#34;#__codelineno-2-212&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-213&#34;&gt;&lt;a id=&#34;__codelineno-2-213&#34; name=&#34;__codelineno-2-213&#34; href=&#34;#__codelineno-2-213&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-214&#34;&gt;&lt;a id=&#34;__codelineno-2-214&#34; name=&#34;__codelineno-2-214&#34; href=&#34;#__codelineno-2-214&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-215&#34;&gt;&lt;a id=&#34;__codelineno-2-215&#34; name=&#34;__codelineno-2-215&#34; href=&#34;#__codelineno-2-215&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;这个模型只评估了 BTB 和 L1 ICache 的性能影响。下面是模拟和实际的对比图，左边是模拟，右边是实际：&lt;/p&gt; &lt;p&gt;stride=4B：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-n1-btb-4b-model.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;stride=8B：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-n1-btb-8b-model.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;stride=16B：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-n1-btb-16b-model.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;stride=32B：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-n1-btb-32b-model.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;stride=64B：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-n1-btb-64b-model.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;stride=128B：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../arm-neoverse-n1-btb-128b-model.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到模型和实际的表现是非常一致的。&lt;/p&gt; &lt;h2 id=&#34;总结&#34;&gt;总结&lt;a class=&#34;headerlink&#34; href=&#34;#总结&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;最后总结一下 Neoverse N1 的 BTB：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;16-entry Nano BTB, fully associative, 1 cycle latency&lt;/li&gt; &lt;li&gt;64-entry Micro BTB, fully associative, 2 cycle latency, behave as victim BTB of Nano BTB&lt;/li&gt; &lt;li&gt;3072-entry(6144 branches) Main BTB, 3-way(6-branch-way) set associative, 2-3 cycle latency, each entry at most 2 branches, index PC[14:5]&lt;/li&gt; &lt;/ul&gt;</description> <link>https://jia.je/hardware/2025/06/05/arm-neoverse-n1-btb/</link> <pubDate>Thu, 05 Jun 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2025/06/05/arm-neoverse-n1-btb/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2025/06/05/arm-neoverse-n1-btb.png" type="image/png" length="60123" /> </item> <item> <title>Apple M4 微架构评测</title> <category>apple</category> <category>cpu</category> <category>hardware</category> <category>m4</category> <category>performance</category> <category>uarch-review</category> <description>&lt;h1 id=&#34;apple-m4-微架构评测&#34;&gt;Apple M4 微架构评测&lt;a class=&#34;headerlink&#34; href=&#34;#apple-m4-微架构评测&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;最近拿到了 Apple M4 的环境，借此机会测试一下 Apple M4 的微架构，和之前&lt;a href=&#34;../../../../2024/12/26/apple-m1/&#34;&gt;分析的 Apple M1 的微架构&lt;/a&gt;做比较。由于 Asahi Linux 尚不支持 Apple M4，所以这里的测试都在 macOS 上进行。&lt;/p&gt; &lt;!-- more --&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4.png&#34; /&gt;&lt;/p&gt; &lt;details class=&#34;note&#34;&gt; &lt;summary&gt;图片来源&lt;/summary&gt; &lt;p&gt;使用 &lt;a href=&#34;https://github.com/Tongyi-MAI/Z-Image&#34;&gt;Z-Image&lt;/a&gt; 生成，提示词： &lt;code&gt;Create a cover iamge for Apple M4 微架构评测, with a proper Apple M4 MacBookAir in the middle with M4 in the background, your text must be accurate&lt;/code&gt;&lt;/p&gt; &lt;/details&gt; &lt;h2 id=&#34;官方信息&#34;&gt;官方信息&lt;a class=&#34;headerlink&#34; href=&#34;#官方信息&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;Apple M4 的官方信息乏善可陈，关于微架构的信息几乎为零，但能从操作系统汇报的硬件信息中找到一些内容。&lt;/p&gt; &lt;p&gt;UPDATE: 后来苹果发布了 &lt;a href=&#34;https://developer.apple.com/download/apple-silicon-cpu-optimization-guide/&#34;&gt;Apple Silicon CPU Optimization Guide&lt;/a&gt;，算是为数不多的官方信息了。&lt;/p&gt; &lt;h2 id=&#34;现有评测&#34;&gt;现有评测&lt;a class=&#34;headerlink&#34; href=&#34;#现有评测&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;网上已经有针对 Apple M4 微架构的评测和分析，建议阅读：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://www.bilibili.com/video/BV1NJ4m1w7zk/&#34;&gt;苹果 M4 性能分析：尽力了，但芯片工艺快到头了！&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;下面分各个模块分别记录官方提供的信息，以及实测的结果。读者可以对照已有的第三方评测理解。官方信息与实测结果一致的数据会加粗。&lt;/p&gt; &lt;h2 id=&#34;前端&#34;&gt;前端&lt;a class=&#34;headerlink&#34; href=&#34;#前端&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;取指带宽&#34;&gt;取指带宽&lt;a class=&#34;headerlink&#34; href=&#34;#取指带宽&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;h4 id=&#34;p-core&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;为了测试实际的 Fetch 宽度，参考 &lt;a href=&#34;https://zhuanlan.zhihu.com/p/720136752&#34;&gt;如何测量真正的取指带宽（I-fetch width） - JamesAslan&lt;/a&gt; 构造了测试。&lt;/p&gt; &lt;p&gt;其原理是当 Fetch 要跨页的时候，由于两个相邻页可能映射到不同的物理地址，如果要支持单周期跨页取指，需要查询两次 ITLB，或者 ITLB 需要把相邻两个页的映射存在一起。这个场景一般比较少，处理器很少会针对这种特殊情况做优化，但也不是没有。经过测试，把循环放在两个页的边界上，发现 M4 P-Core 微架构遇到跨页的取指时确实会拆成两个周期来进行。&lt;/p&gt; &lt;p&gt;在此基础上，构造一个循环，循环的第一条指令放在第一个页的最后四个字节，其余指令放第二个页上，那么每次循环的取指时间，就是一个周期（读取第一个页内的指令）加上第二个页内指令需要 Fetch 的周期数，多的这一个周期就足以把 Fetch 宽度从后端限制中区分开，实验结果如下：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-if-width.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;图中蓝线（cross-page）表示的就是上面所述的第一条指令放一个页，其余指令放第二个页的情况，横坐标是第二个页内的指令数，那么一次循环的指令数等于横坐标 +1。纵坐标是运行很多次循环的总 cycle 数除以循环次数，也就是平均每次循环耗费的周期数。可以看到每 16 条指令会多一个周期，因此 M4 P-Core 的前端取指宽度确实是 16 条指令，和 Apple M1 的 P-Core 是相同的。&lt;/p&gt; &lt;p&gt;为了确认这个瓶颈是由取指造成的，又构造了一组实验，把循环的所有指令都放到一个页中，这个时候 Fetch 不再成为瓶颈（图中 aligned），两个曲线的对比可以明确地得出上述结论。&lt;/p&gt; &lt;p&gt;随着指令数进一步增加，最终瓶颈在每周期执行的 NOP 指令数，因此两条线重合。&lt;/p&gt; &lt;h4 id=&#34;e-core&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;用相同的方式测试 M4 E-Core，结果如下：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-e-core-if-width.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;由于两个曲线汇合的点太前（NOP 指令执行得不够快），无法确定 M4 E-Core 的取指宽度，但可以确认的是它每周期取值不少于 10 条指令，比 Apple M1 的 E-Core 要更快。如果读者想到什么办法来确认 M4 E-Core 的取指宽度，欢迎在评论区给出。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/if_width_gen.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;l1-icache&#34;&gt;L1 ICache&lt;a class=&#34;headerlink&#34; href=&#34;#l1-icache&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：通过 sysctl 可以看到，P-Core 具有 192KB L1 ICache，E-Core 具有 128KB L1 ICache：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-0-1&#34;&gt;&lt;a id=&#34;__codelineno-0-1&#34; name=&#34;__codelineno-0-1&#34; href=&#34;#__codelineno-0-1&#34;&gt;&lt;/a&gt;hw.perflevel0.l1icachesize: 196608 &lt;/span&gt;&lt;span id=&#34;__span-0-2&#34;&gt;&lt;a id=&#34;__codelineno-0-2&#34; name=&#34;__codelineno-0-2&#34; href=&#34;#__codelineno-0-2&#34;&gt;&lt;/a&gt;hw.perflevel1.l1icachesize: 131072 &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;根据 Apple Silicon CPU Optimization Guide，从 M1 Family 到 M4 Family，A14 Bionic 到 A18 Family，P-Core 的 L1 ICache 的配置都是 192KiB, 6-way, 64B lines；对应处理器的 E-Core 的 L1 ICache 都是 192KiB, 64B lines，其中 M1 Family 和 A14 Bionic 是 8-way，其余处理器（M2 Family 和 A15 Bionic 开始）是 4-way。&lt;/p&gt; &lt;p&gt;延续了从 Apple M1 以来的大小。&lt;/p&gt; &lt;h4 id=&#34;p-core_1&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_1&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;为了测试 L1 ICache 容量，构造一个具有巨大指令 footprint 的循环，由大量的 nop 和最后的分支指令组成。观察在不同 footprint 大小下 M4 P-Core 的 IPC：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-fetch-bandwidth.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到 footprint 在 192 KB 之前时可以达到 10 IPC，之后则快速降到 2.5 IPC，这里的 192 KB 就对应了 M4 P-Core 的 L1 ICache 的容量，和官方信息一致。虽然 Fetch 可以每周期 16 条指令，也就是一条 64B 的缓存行，由于后端的限制，只能观察到 10 的 IPC。&lt;/p&gt; &lt;h4 id=&#34;e-core_1&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_1&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;用相同的方式测试 M4 E-Core，结果如下：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-e-core-fetch-bandwidth.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到 footprint 在 128 KB 之前时可以达到 5 IPC，之后则快速降到 2.0 IPC，这里的 128 KB 就对应了 M4 E-Core 的 L1 ICache 的容量，和官方信息一致。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/fetch_bandwidth_gen.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;btb&#34;&gt;BTB&lt;a class=&#34;headerlink&#34; href=&#34;#btb&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;&lt;a href=&#34;../../../../2024/12/26/apple-m1/&#34;&gt;Apple M1&lt;/a&gt; 的 BTB 设计相对比较简单：1024 项的组相连 L1 BTB，接着是以 192KB L1 ICache 作为兜底的 3 周期的等效 BTB。但是 M4 上的 BTB 测试图像变化很大，下面进行仔细的分析。&lt;/p&gt; &lt;h4 id=&#34;p-core_2&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_2&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;构造大量的无条件分支指令（B 指令），BTB 需要记录这些指令的目的地址，那么如果分支数量超过了 BTB 的容量，性能会出现明显下降。当把大量 B 指令紧密放置，也就是每 4 字节一条 B 指令时：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-btb-4b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到最低的 CPI 能达到接近 0.5（实际值在 0.55），说明 Apple M4 有了一定的每周期执行 2 taken branches 的能力，后面会着重讨论这一点。在经过 CPI 最低点之后，性能出现了先下降后上升再下降的情况，最终在 2048 个分支开始稳定在 2 左右（实际值在 2.10）的 CPI。&lt;/p&gt; &lt;p&gt;这个 2 左右的 CPI 一直稳定维持，一直延续到 49152 个分支。超出 BTB 容量以后，分支预测时，无法从 BTB 中得到哪些指令是分支指令的信息，只能等到取指甚至译码后才能后知后觉地发现这是一条分支指令，这样就出现了性能损失，出现了 2 CPI 的情况。49152 这个拐点，对应的是指令 footprint 超出 L1 ICache 的情况：L1 ICache 是 192KB，按照每 4 字节一个 B 指令计算，最多可以存放 49152 条 B 指令。&lt;/p&gt; &lt;p&gt;这个 2 CPI 的平台在 Apple M1 中是 3 CPI，这是一个巨大的优化，在大多数情况下，通过 L1 ICache 能以每 2 周期一条无条件分支的性能兜底。&lt;/p&gt; &lt;p&gt;接下来降低分支指令的密度，在 B 指令之间插入 NOP 指令，使得每 8 个字节有一条 B 指令，得到如下结果：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-btb-8b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;图像基本就是 4 字节间距情况下，整体左移的结果，说明各级 BTB 结构大概是组相连，当间距为 8 字节，PC[2] 恒为 0 的时候，只有一半的组可以被用到。&lt;/p&gt; &lt;p&gt;继续降低分支指令的密度，在 B 指令之间插入 NOP 指令，使得每 16 个字节有一条 B 指令，得到如下结果：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-btb-16b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;每 32 个字节有一条 B 指令：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-btb-32b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;从间距为 4 字节到间距为 32 字节，整个的图像都是类似的，只是不断在左移。但是当每 64 个字节有一条 B 指令的时候，情况就不同了：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-btb-64b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;整体的 CPI 有比较明显的下降，最低的 CPI 也在 2 以上，这和 Apple M1 上依然是在 4 字节间距的图像的基础上左移有显著的不同。&lt;/p&gt; &lt;p&gt;前面提到，Apple M4 P-Core 出现了每周期 2 taken branches，但是当分支不在同一个 64B 内的时候，性能会有明显下降；另一方面，以 ARM Neoverse V2 为例，它实现的每周期 2 taken branches，即使分支不在同一个 64B 内，也是可以做到的，下面是在 64B 间距下 ARM Neoverse V2 的测试结果：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-neoverse-v2-2-taken.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;根据这些现象，找到了 Apple 的一篇专利 &lt;a href=&#34;https://patents.google.com/patent/US20240028339A1/en&#34;&gt;Using a Next Fetch Predictor Circuit with Short Branches and Return Fetch Groups&lt;/a&gt;，它提到了一种符合上述现象的实现 2 taken branches 的方法：如果在一个 fetch group（在这里是 64B）内，有一条分支，它的目的地址还在这个 fetch group 内，由于 fetch group 的指令都已经取出来了，所以同一个周期内，可以从这条分支的目的地址开始，继续获取指令。下面是一个例子：&lt;/p&gt; &lt;div class=&#34;language-asm highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-1-1&#34;&gt;&lt;a id=&#34;__codelineno-1-1&#34; name=&#34;__codelineno-1-1&#34; href=&#34;#__codelineno-1-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;# the beginning of a fetch group&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-2&#34;&gt;&lt;a id=&#34;__codelineno-1-2&#34; name=&#34;__codelineno-1-2&#34; href=&#34;#__codelineno-1-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nf&#34;&gt;nop&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-3&#34;&gt;&lt;a id=&#34;__codelineno-1-3&#34; name=&#34;__codelineno-1-3&#34; href=&#34;#__codelineno-1-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;# the branch&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-4&#34;&gt;&lt;a id=&#34;__codelineno-1-4&#34; name=&#34;__codelineno-1-4&#34; href=&#34;#__codelineno-1-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nf&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;target&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-5&#34;&gt;&lt;a id=&#34;__codelineno-1-5&#34; name=&#34;__codelineno-1-5&#34; href=&#34;#__codelineno-1-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;# some instructions are skipped between branch and its target&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-6&#34;&gt;&lt;a id=&#34;__codelineno-1-6&#34; name=&#34;__codelineno-1-6&#34; href=&#34;#__codelineno-1-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nf&#34;&gt;svc&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;#0&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-7&#34;&gt;&lt;a id=&#34;__codelineno-1-7&#34; name=&#34;__codelineno-1-7&#34; href=&#34;#__codelineno-1-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;# the branch target resides in the same fetch group&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-8&#34;&gt;&lt;a id=&#34;__codelineno-1-8&#34; name=&#34;__codelineno-1-8&#34; href=&#34;#__codelineno-1-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nl&#34;&gt;target:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-9&#34;&gt;&lt;a id=&#34;__codelineno-1-9&#34; name=&#34;__codelineno-1-9&#34; href=&#34;#__codelineno-1-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;# some instructions after the branch target&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-10&#34;&gt;&lt;a id=&#34;__codelineno-1-10&#34; name=&#34;__codelineno-1-10&#34; href=&#34;#__codelineno-1-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nf&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;x3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;x2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;no&#34;&gt;x1&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-1-11&#34;&gt;&lt;a id=&#34;__codelineno-1-11&#34; name=&#34;__codelineno-1-11&#34; href=&#34;#__codelineno-1-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;nf&#34;&gt;ret&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;那么在传统的设计里，这段代码会被分成两个周期去取指，第一个周期取 &lt;code&gt;nop&lt;/code&gt; 和 &lt;code&gt;b target&lt;/code&gt;，第二个周期取 &lt;code&gt;add x3, x2, x1&lt;/code&gt; 和 &lt;code&gt;ret&lt;/code&gt;；按照这个专利的说法，可以在一个周期内取出所有指令，然后把中间被跳过的 &lt;code&gt;svc #0&lt;/code&gt; 指令跳过去，不去执行它。当然了，分支预测器那边也需要做修改，能够去预测第二个分支的目的地址，用于下一个周期。&lt;/p&gt; &lt;p&gt;如果是这种实现方法，是可能在一个 Coupled 前端内，实现这种有限场景的每周期执行 2 taken branches，核心是每周期依然只访问一次 ICache。&lt;/p&gt; &lt;h4 id=&#34;e-core_2&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_2&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;另一方面，M4 E-Core 的 BTB 设计和 Apple M1 的 E-Core 十分接近，当分支间距是 4 字节时：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-e-core-btb-4b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到 1024 的拐点，1024 之前是 1 IPC，之后增加到 3 IPC。比较奇怪的是，没有看到第二个拐点。&lt;/p&gt; &lt;p&gt;8B 的间距：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-e-core-btb-8b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;拐点前移到 512。&lt;/p&gt; &lt;p&gt;16B 的间距：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-e-core-btb-16b.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;第一个拐点前移到 256，第二个拐点出现在 8192，而 M4 E-Core 的 L1 ICache 容量是 128KB，16B 间距下正好可以保存 8192 个分支。&lt;/p&gt; &lt;p&gt;可见 M4 E-Core 的前端设计和 M4 P-Core 有较大的不同。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/btb_size_basic_gen.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;l1-itlb&#34;&gt;L1 ITLB&lt;a class=&#34;headerlink&#34; href=&#34;#l1-itlb&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：根据 Apple Silicon CPU Optimization Guide，从 M1 Family 到 M4 Family，A14 Bionic 到 A18 Family，其 P-Core 的 L1 ITLB 配置都是一样的：192 entries，考虑到每个页是 16 KiB，对应 3 MiB 的内存；E-Core 的话，M1 Family 和 A14 Bionic 的 L1 ITLB 是 128 entries，之后的处理器（M2 Family 和 A15 Bionic 开始）则 E-Core 也是 192 entries。&lt;/p&gt; &lt;p&gt;因此，M4 的 P-Core L1 ITLB 是 192 entries，E-Core L1 ITLB 也是 192 entries。&lt;/p&gt; &lt;h4 id=&#34;p-core_3&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_3&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;构造一系列的 B 指令，使得 B 指令分布在不同的 page 上，使得 ITLB 成为瓶颈，在 M4 P-Core 上进行测试：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-itlb.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;第一个拐点是由于 L1 BTB 的冲突缺失，之后在 192 个页时从 3 Cycle 快速增加到 12 Cycle，则对应了 192 项的 L1 ITLB 容量，和官方信息一致。这和 M1 P-Core 是一样的。&lt;/p&gt; &lt;h4 id=&#34;e-core_3&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_3&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;在 M4 E-Core 上重复实验：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-e-core-itlb.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;第一个拐点是由于 L1 BTB 的冲突缺失，之后在 192 个页时从 3 Cycle 快速增加到 10 Cycle，则对应了 192 项的 L1 ITLB 容量，和官方信息一致。相比 M1 E-Core 的 128 项，容量变大了，和 M4 P-Core 看齐。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/itlb_size_lib.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;decode&#34;&gt;Decode&lt;a class=&#34;headerlink&#34; href=&#34;#decode&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：根据 Apple Silicon CPU Optimization Guide，M1 Family 的 Sustained uops Per Cycle 最大值，P-Core 是 8，E-Core 是 4；M2 Family 的 P-Core 不变，E-Core 提升到了 5；M3 Family 的 P-Core 提升到了 9，E-Core 和 M2 持平；M4 Family 的 P-Core 进一步提升到了 10，E-Core 继续和 M2 持平。&lt;/p&gt; &lt;p&gt;从前面的测试来看，M4 P-Core 最大观察到 10 IPC，M4 E-Core 最大观察到 5 IPC，那么 Decode 宽度也至少是这么多，暂时也不能排除有更大的 Decode 宽度，和官方信息一致。相比 M1 的 P-Core 8 IPC，E-Core 4 IPC 都有拓宽。&lt;/p&gt; &lt;h3 id=&#34;return-stack&#34;&gt;Return Stack&lt;a class=&#34;headerlink&#34; href=&#34;#return-stack&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;h4 id=&#34;p-core_4&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_4&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;构造不同深度的调用链，测试每次调用花费的平均时间，在 M4 P-Core 上得到下面的图：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-rs.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到调用链深度为 60 时性能突然变差，因此 M4 P-Core 的 Return Stack 深度为 60，比 M1 P-Core 的 50 要更大。这里测试的两个 Variant，对应的是 Return 的目的地址不变还是会变化。&lt;/p&gt; &lt;h4 id=&#34;e-core_4&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_4&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;在 M4 E-Core 上测试：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-e-core-rs.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到调用链深度为 40 时性能突然变差，因此 M4 E-Core 的 Return Stack 深度为 40，比 M1 E-Core 的 32 要更大。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/ras_size_gen.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h2 id=&#34;后端&#34;&gt;后端&lt;a class=&#34;headerlink&#34; href=&#34;#后端&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;物理寄存器堆&#34;&gt;物理寄存器堆&lt;a class=&#34;headerlink&#34; href=&#34;#物理寄存器堆&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;h4 id=&#34;p-core_5&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_5&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;为了测试物理寄存器堆的大小，一般会用两个依赖链很长的操作放在开头和结尾，中间填入若干个无关的指令，并且用这些指令来耗费物理寄存器堆。M4 P-Core 测试结果见下图：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-prf.png&#34; /&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;32b int：测试 speculative 32 位整数寄存器的数量，拐点在 720 左右&lt;/li&gt; &lt;li&gt;64b int：测试 speculative 64 位整数寄存器的数量，拐点在 360 左右，只有 32b 的一半，可见实际的物理寄存器堆有 360 左右个 64 位整数寄存器，但是可以分成两半分别当成 32 位整数寄存器用，这一个优化在 M1 是没有的，即用 32b 或者用 64b 整数，测出来的整数寄存器数量相同&lt;/li&gt; &lt;li&gt;flags：测试 speculative NZCV 寄存器的数量，拐点在 175 左右&lt;/li&gt; &lt;li&gt;32b fp：测试 speculative 32 位浮点寄存器的数量，没有观察到明显的拐点&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;寄存器堆大小和 M1 P-Core 比较类似，但是多了 32 位整数寄存器的优化。&lt;/p&gt; &lt;h4 id=&#34;e-core_5&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_5&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;在 M4 E-Core 上复现相同的测试，发现性能非常不稳定，不确定是什么原因。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/register_file_size_gen.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;load-store-unit--l1-dcache&#34;&gt;Load Store Unit + L1 DCache&lt;a class=&#34;headerlink&#34; href=&#34;#load-store-unit--l1-dcache&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;h4 id=&#34;l1-dcache-容量&#34;&gt;L1 DCache 容量&lt;a class=&#34;headerlink&#34; href=&#34;#l1-dcache-容量&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;官方信息：通过 sysctl 可以看到，M4 P-Core 具有 128KB L1 DCache，M4 E-Core 具有 64KB L1 DCache：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-2-1&#34;&gt;&lt;a id=&#34;__codelineno-2-1&#34; name=&#34;__codelineno-2-1&#34; href=&#34;#__codelineno-2-1&#34;&gt;&lt;/a&gt;hw.perflevel0.l1dcachesize: 131072 &lt;/span&gt;&lt;span id=&#34;__span-2-2&#34;&gt;&lt;a id=&#34;__codelineno-2-2&#34; name=&#34;__codelineno-2-2&#34; href=&#34;#__codelineno-2-2&#34;&gt;&lt;/a&gt;hw.perflevel1.l1dcachesize: 65536 &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;根据 Apple Silicon CPU Optimization Guide，从 M1 Family 到 M4 Family，从 A14 Bionic 到 A18 Family，P-Core 的 L1 DCache 都是 128KiB, 8-way, 64B lines 的配置，E-Core 的 L1 DCache 都是 64KiB, 8-way, 64B lines 的配置。&lt;/p&gt; &lt;p&gt;和 M1 相同。&lt;/p&gt; &lt;h5 id=&#34;p-core_6&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_6&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;构造不同大小 footprint 的 pointer chasing 链，在每个页的开头放一个指针，测试不同 footprint 下每条 load 指令耗费的时间，M4 P-Core 上的结果：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-l1dc.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到 128KB 出现了拐点，对应的就是 128KB 的 L1 DCache 容量，和官方信息一致。当 footprint 比较小的时候，由于 Load Address/Value Predictor 的介入，打破了依赖链，所以出现了 latency 小于正常 load to use 的 3 cycle latency 的情况。&lt;/p&gt; &lt;h5 id=&#34;e-core_6&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_6&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;M4 E-Core 上的结果：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-e-core-l1dc.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到 128KB 出现了明显的拐点，但实际上 M4 E-Core 的 L1 DCache 只有 64KB。猜测这是因为在测试的时候，是在每个 16KB 页的开头放一个指针，但如果 L1 DCache 的 Index 并非都在 16KB 内部，就会导致实际测出来的不是 L1 DCache 的大小。修改测试，使得每 8 字节一个指针，此时测出来的结果就是正确的 64KB 大小：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-e-core-l1dc-2.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;此时 64KB 对应的就是 64KB 的 L1 DCache 容量，和官方信息一致。L1 DCache 范围内延迟是 3 cycle，之后提升到 14+ cycle。由此可见 M4 E-Core 没有 Load Address/Value Predictor，不能打断依赖链。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/memory_latency.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h4 id=&#34;l1-dtlb-容量&#34;&gt;L1 DTLB 容量&lt;a class=&#34;headerlink&#34; href=&#34;#l1-dtlb-容量&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;官方信息：根据 Apple Silicon CPU Optimization Guide，对于 P-Core 来说，除了 M2 Family、A14 Bionic 和 A15 Bionic 的 L1 DTLB 是 256 entries 以外，其余的 M1 Family、M3 Family 到 M4 Family，A16 Bionic 到 A18 Family 的 L1 DTLB 都是 160 entries。对于 E-Core 来说，除了 M1 Family 和 A14 Bionic 是 129 entries，其余的从 M2 Family 到 M4 Family，A15 Bionic 到 A18 Family 都是 192 entries。&lt;/p&gt; &lt;p&gt;因此，M4 的 P-Core L1 DTLB 容量是 160，E-Core L1 DTLB 容量是 192。&lt;/p&gt; &lt;h5 id=&#34;p-core_7&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_7&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;用类似的方法测试 L1 DTLB 容量，只不过这次 pointer chasing 链的指针分布在不同的 page 的不同 cache line 上，使得 DTLB 成为瓶颈，在 M4 P-Core 上：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-l1dtlb.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;从 160 个页开始性能下降，到 200 个页时性能稳定在 9 CPI，认为 M4 P-Core 的 L1 DTLB 有 160 项，大小和 M1 P-Core 相同，和官方信息一致。9 CPI 包括了 L1 DTLB miss L2 TLB hit 带来的额外延迟。中间有时性能特别快，是 Load Address/Value Predictor 的功劳。&lt;/p&gt; &lt;h5 id=&#34;e-core_7&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_7&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;M4 E-Core 测试结果：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-e-core-l1dtlb.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;从 192 个页开始性能下降，到 224 个页时性能稳定在 9 CPI，认为 M4 E-Core 的 L1 DTLB 有 192 项，和官方信息一致，比 M1 E-Core 的 128 项更大，甚至大过了 P-Core。9 CPI 包括了 L1 DTLB miss L2 TLB hit 带来的额外延迟，比 M1 E-Core 少了一个周期。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/dtlb_size.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h4 id=&#34;loadstore-带宽&#34;&gt;Load/Store 带宽&lt;a class=&#34;headerlink&#34; href=&#34;#loadstore-带宽&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;h5 id=&#34;p-core_8&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_8&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;针对 Load Store 带宽，实测 M4 P-Core 每个周期可以完成：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;3x 128b Load + 1x 128b Store&lt;/li&gt; &lt;li&gt;2x 128b Load + 2x 128b Store&lt;/li&gt; &lt;li&gt;1x 128b Load + 2x 128b Store&lt;/li&gt; &lt;li&gt;2x 128b Store&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;如果把每条指令的访存位宽从 128b 改成 256b，读写带宽不变，指令吞吐减半。也就是说最大的读带宽是 48B/cyc，最大的写带宽是 32B/cyc，二者不能同时达到。和 M1 P-Core 相同。&lt;/p&gt; &lt;h5 id=&#34;e-core_8&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_8&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;实测 M4 E-Core 每个周期可以完成：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;2x 128b Load&lt;/li&gt; &lt;li&gt;1x 128b Load + 1x 128b Store&lt;/li&gt; &lt;li&gt;1x 128b Store&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;如果把每条指令的访存位宽从 128b 改成 256b，读写带宽不变，指令吞吐减半。也就是说最大的读带宽是 32B/cyc，最大的写带宽是 16B/cyc，二者不能同时达到。和 M1 E-Core 相同。&lt;/p&gt; &lt;h4 id=&#34;memory-dependency-predictor&#34;&gt;Memory Dependency Predictor&lt;a class=&#34;headerlink&#34; href=&#34;#memory-dependency-predictor&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;为了预测执行 Load，需要保证 Load 和之前的 Store 访问的内存没有 Overlap，那么就需要有一个预测器来预测 Load 和 Store 之前在内存上的依赖。参考 &lt;a href=&#34;https://blog.stuffedcow.net/2014/01/x86-memory-disambiguation/&#34;&gt;Store-to-Load Forwarding and Memory Disambiguation in x86 Processors&lt;/a&gt; 的方法，构造两个指令模式，分别在地址和数据上有依赖：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;数据依赖，地址无依赖：&lt;code&gt;str x3, [x1]&lt;/code&gt; 和 &lt;code&gt;ldr x3, [x2]&lt;/code&gt;&lt;/li&gt; &lt;li&gt;地址依赖，数据无依赖：&lt;code&gt;str x2, [x1]&lt;/code&gt; 和 &lt;code&gt;ldr x1, [x2]&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;初始化时，&lt;code&gt;x1&lt;/code&gt; 和 &lt;code&gt;x2&lt;/code&gt; 指向同一个地址，重复如上的指令模式，观察到多少条 &lt;code&gt;ldr&lt;/code&gt; 指令时会出现性能下降。&lt;/p&gt; &lt;h5 id=&#34;p-core_9&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_9&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;在 M4 P-Core 上测试：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-memory-dependency-predictor.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;数据依赖没有明显的阈值，但从 72 开始出现了一个小的增长，且斜率不为零；地址依赖的阈值是 39。相比 M1 P-Core 有所减小。&lt;/p&gt; &lt;h5 id=&#34;e-core_9&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_9&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;M4 E-Core:&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-e-core-memory-dependency-predictor.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;数据依赖的阈值是 20，地址依赖的阈值是 14。比 M1 E-Core 略大。&lt;/p&gt; &lt;h4 id=&#34;store-to-load-forwarding&#34;&gt;Store to Load Forwarding&lt;a class=&#34;headerlink&#34; href=&#34;#store-to-load-forwarding&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;h5 id=&#34;p-core_10&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_10&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;经过实际测试，M4 P-Core 上如下的情况可以成功转发，对地址 x 的 Store 转发到对地址 y 的 Load 成功时 y-x 的取值范围：&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;Store\Load&lt;/th&gt; &lt;th&gt;8b Load&lt;/th&gt; &lt;th&gt;16b Load&lt;/th&gt; &lt;th&gt;32b Load&lt;/th&gt; &lt;th&gt;64b Load&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;8b Store&lt;/td&gt; &lt;td&gt;{0}&lt;/td&gt; &lt;td&gt;[-1,0]&lt;/td&gt; &lt;td&gt;[-3,0]&lt;/td&gt; &lt;td&gt;[-7,0]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;16b Store&lt;/td&gt; &lt;td&gt;[0,1]&lt;/td&gt; &lt;td&gt;[-1,1]&lt;/td&gt; &lt;td&gt;[-3,1]&lt;/td&gt; &lt;td&gt;[-7,1]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;32b Store&lt;/td&gt; &lt;td&gt;[0,3]&lt;/td&gt; &lt;td&gt;[-1,3]&lt;/td&gt; &lt;td&gt;[-3,3]&lt;/td&gt; &lt;td&gt;[-7,3]&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;64b Store&lt;/td&gt; &lt;td&gt;[0,7]&lt;/td&gt; &lt;td&gt;[-1,7]&lt;/td&gt; &lt;td&gt;[-3,7]&lt;/td&gt; &lt;td&gt;[-7,7]&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;从上表可以看到，所有 Store 和 Load Overlap 的情况，无论地址偏移，都能成功转发。甚至在 Load 或 Store 跨越 64B 缓存行边界时，也可以成功转发，代价是多一个周期。&lt;/p&gt; &lt;p&gt;一个 Load 需要转发两个、四个甚至八个 Store 的数据时，也可以成功转发。即使数据跨越缓存行，也可以转发，只是多耗费 1-2 个周期。但在跨 64B 缓存行的时候，代价可能多于一个周期。相比 M1 P-Core，M4 P-Core 在跨越缓存行的情况下也可以得到比较好的性能。&lt;/p&gt; &lt;p&gt;成功转发时 7 cycle 左右。&lt;/p&gt; &lt;p&gt;小结：Apple M4 P-Core 的 Store to Load Forwarding：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;1 ld + 1 st: 支持&lt;/li&gt; &lt;li&gt;1 ld + 2 st: 支持&lt;/li&gt; &lt;li&gt;1 ld + 4 st: 支持&lt;/li&gt; &lt;li&gt;1 ld + 8 st: 支持&lt;/li&gt; &lt;li&gt;跨 64B 缓存行边界时，性能略微下降&lt;/li&gt; &lt;/ul&gt; &lt;h5 id=&#34;e-core_10&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_10&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;在 M4 E-Core 上，如果 Load 和 Store 访问范围出现重叠，当需要转发一个到两个 Store 的数据时，需要 7 Cycle，无论是否跨缓存行。如果需要转发四个 Store 的数据，则需要 8 Cycle；转发八个 Store 的数据需要 11 Cycle。相比 M1 E-Core，多数情况下获得了性能提升。&lt;/p&gt; &lt;h4 id=&#34;load-to-use-latency&#34;&gt;Load to use latency&lt;a class=&#34;headerlink&#34; href=&#34;#load-to-use-latency&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;官方信息：根据 Apple Silicon CPU Optimization Guide，Apple 实现了 fast pointer chasing with a 3-cycle latency，要求后一个 load 的 base register 和前一个 load 的 destination register 相同。&lt;/p&gt; &lt;h5 id=&#34;p-core_11&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_11&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;实测 M4 P-Core 的 Load to use latency 针对 pointer chasing 场景做了优化，在下列的场景下可以达到 3 cycle:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;ldr x0, [x0]&lt;/code&gt;: load 结果转发到基地址，无偏移&lt;/li&gt; &lt;li&gt;&lt;code&gt;ldr x0, [x0, 8]&lt;/code&gt;：load 结果转发到基地址，有立即数偏移&lt;/li&gt; &lt;li&gt;&lt;code&gt;ldr x0, [x0, x1]&lt;/code&gt;：load 结果转发到基地址，有寄存器偏移&lt;/li&gt; &lt;li&gt;&lt;code&gt;ldp x0, x1, [x0]&lt;/code&gt;：load pair 的第一个目的寄存器转发到基地址，无偏移&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;如果访存跨越了 8B 边界，则退化到 4 cycle。&lt;/p&gt; &lt;p&gt;在下列场景下 Load to use latency 则是 4 cycle：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;load 的目的寄存器作为 alu 的源寄存器（下称 load to alu latency）&lt;/li&gt; &lt;li&gt;&lt;code&gt;ldr x0, [sp, x0, lsl #3]&lt;/code&gt;：load 结果转发到 index&lt;/li&gt; &lt;li&gt;&lt;code&gt;ldp x1, x0, [x0]&lt;/code&gt;：load pair 的第二个目的寄存器转发到基地址，无偏移&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;注意由于 Load Address/Value Predictor 的存在，测试的时候需要排除预测器带来的影响。延迟方面，和 M1 P-Core 相同。&lt;/p&gt; &lt;h5 id=&#34;e-core_11&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_11&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;实测 M4 E-Core 的 Load to use latency 针对 pointer chasing 场景做了优化，在下列的场景下可以达到 3 cycle:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;ldr x0, [x0]&lt;/code&gt;: load 结果转发到基地址，无偏移&lt;/li&gt; &lt;li&gt;&lt;code&gt;ldr x0, [x0, 8]&lt;/code&gt;：load 结果转发到基地址，有立即数偏移&lt;/li&gt; &lt;li&gt;&lt;code&gt;ldr x0, [x0, x1]&lt;/code&gt;：load 结果转发到基地址，有寄存器偏移&lt;/li&gt; &lt;li&gt;&lt;code&gt;ldp x0, x1, [x0]&lt;/code&gt;：load pair 的第一个目的寄存器转发到基地址，无偏移&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;如果访存跨越了 8B/16B/32B 边界，依然是 3 cycle；跨越了 64B 边界则退化到 7 cycle。&lt;/p&gt; &lt;p&gt;在下列场景下 Load to use latency 则是 4 cycle：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;load 的目的寄存器作为 alu 的源寄存器（下称 load to alu latency）&lt;/li&gt; &lt;li&gt;&lt;code&gt;ldr x0, [sp, x0, lsl #3]&lt;/code&gt;：load 结果转发到 index&lt;/li&gt; &lt;li&gt;&lt;code&gt;ldp x1, x0, [x0]&lt;/code&gt;：load pair 的第二个目的寄存器转发到基地址，无偏移&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;延迟方面，和 M1 E-Core 相同。&lt;/p&gt; &lt;h4 id=&#34;virtual-address-utagway-predictor&#34;&gt;Virtual Address UTag/Way-Predictor&lt;a class=&#34;headerlink&#34; href=&#34;#virtual-address-utagway-predictor&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;Linear Address UTag/Way-Predictor 是 AMD 的叫法，但使用相同的测试方法，也可以在 Apple M1 上观察到类似的现象，猜想它也用了类似的基于虚拟地址的 UTag/Way Predictor 方案，并测出来它的 UTag 也有 8 bit，M4 P-Core 和 M4 E-Core 都是相同的：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;VA[14] xor VA[22] xor VA[30] xor VA[38] xor VA[46]&lt;/li&gt; &lt;li&gt;VA[15] xor VA[23] xor VA[31] xor VA[39] xor VA[47]&lt;/li&gt; &lt;li&gt;VA[16] xor VA[24] xor VA[32] xor VA[40]&lt;/li&gt; &lt;li&gt;VA[17] xor VA[25] xor VA[33] xor VA[41]&lt;/li&gt; &lt;li&gt;VA[18] xor VA[26] xor VA[34] xor VA[42]&lt;/li&gt; &lt;li&gt;VA[19] xor VA[27] xor VA[35] xor VA[43]&lt;/li&gt; &lt;li&gt;VA[20] xor VA[28] xor VA[36] xor VA[44]&lt;/li&gt; &lt;li&gt;VA[21] xor VA[29] xor VA[37] xor VA[45]&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;一共有 8 bit，由 VA[47:14] 折叠而来。和 Apple M1 相同。&lt;/p&gt; &lt;h4 id=&#34;load-addressvalue-predictor&#34;&gt;Load Address/Value Predictor&lt;a class=&#34;headerlink&#34; href=&#34;#load-addressvalue-predictor&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;Apple 从 M2 开始引入 Load Address Predictor，从 M3 开始引入 Load Value Predictor，相关的信息如下：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Load Address Predictor：支持 Constant 和 Striding Address 两种模式，专利是 &lt;a href=&#34;https://patents.google.com/patent/US11829763B2/&#34;&gt;Early load execution via constant address and stride prediction&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Load Value Predictor（也称 Load Output Predictor）：只支持 Constant Value，专利是 &lt;a href=&#34;https://patents.google.com/patent/US12067398B1/en&#34;&gt;Shared learning table for load value prediction and load address prediction&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;这两个 Predictor 会对已有的基于 Load 的各种 microbenchmark 带来深刻的影响。&lt;/p&gt; &lt;p&gt;网上已有针对这两个 Predictor 的逆向和攻击：&lt;a href=&#34;https://predictors.fail/&#34;&gt;SLAP: Data Speculation Attacks via Load Address Prediction on Apple Silicon;FLOP Breaking the Apple M3 CPU via False Load Output Predictions&lt;/a&gt;。&lt;/p&gt; &lt;p&gt;苹果还有一个后续的专利：&lt;a href=&#34;https://patents.google.com/patent/US12159142B1/&#34;&gt;Managing table accesses for tagged geometric length (TAGE) load value prediction&lt;/a&gt;，暗示了苹果可能会使用 VTAGE 算法来实现 load value prediction，只是不知道会不会实装，会在哪代处理器上实装，是不是已经实装在已经发布的处理器上了。&lt;/p&gt; &lt;h5 id=&#34;p-core_12&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_12&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;构造依赖链，但是实际测试可以观察到打破依赖链的情况，比串行执行要更快。测试下来，大概可以跟踪 60 条 Load 指令的地址并实现预测。&lt;/p&gt; &lt;h5 id=&#34;e-core_12&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_12&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h5&gt; &lt;p&gt;M4 E-Core 没有实现 Load Address/Value Predictor。&lt;/p&gt; &lt;h3 id=&#34;执行单元&#34;&gt;执行单元&lt;a class=&#34;headerlink&#34; href=&#34;#执行单元&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：根据 Apple Silicon CPU Optimization Guide，M4 Family 的 P-Core 包括如下计算单元：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;ALU/f, BRc/i&lt;/li&gt; &lt;li&gt;ALU/f, BRc&lt;/li&gt; &lt;li&gt;ALU/f&lt;/li&gt; &lt;li&gt;ALU/f, PRED/f&lt;/li&gt; &lt;li&gt;ALU, MUL, MISC&lt;/li&gt; &lt;li&gt;ALU, DIV&lt;/li&gt; &lt;li&gt;ALU, MUL&lt;/li&gt; &lt;li&gt;ALU, MUL&lt;/li&gt; &lt;li&gt;GENERAL, MOVE2GPR, FCMPf, FCSELf, FDIV, MUL, SHA&lt;/li&gt; &lt;li&gt;GENERAL, MOVE2GPR, FCSELf, MUL&lt;/li&gt; &lt;li&gt;GENERAL, MUL&lt;/li&gt; &lt;li&gt;GENERAL, MUL&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;从 M3 开始，P-Core 整数计算单元从 6 个增加到 8 个。浮点部分没有变化。&lt;/p&gt; &lt;p&gt;P-Core 访存：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Burst: 3 load uops, 2 store uops (address part), and 2 store uops (data part)&lt;ul&gt; &lt;li&gt;即 3 load, 2 sta, 2 std&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;Sustained: 4 uops, 2 write into the cache&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;和 M1 E-Core 相同。&lt;/p&gt; &lt;p&gt;M4 Family 的 E-Core 包括如下计算单元：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;ALU/f, MUL, MAC, MISC, PRED/f&lt;/li&gt; &lt;li&gt;ALU/F, BRi, DIV&lt;/li&gt; &lt;li&gt;ALU/f, BRc&lt;/li&gt; &lt;li&gt;ALU/f&lt;/li&gt; &lt;li&gt;GENERAL, MOVE2GPR, FCMPf, FCSELf, FDIV, MUL, SHA&lt;/li&gt; &lt;li&gt;GENERAL, MOVE2GPR, FCMPf, FCSELf, MUL&lt;/li&gt; &lt;li&gt;GENERAL&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;从 M3 开始，E-Core 整数计算单元从 3 个增加到 4 个。从 M3 Max/M4 Family 开始，E-Core 浮点单元从 2 个增加到 3 个。注意 M3/M3 Pro 的 E-Core 依然是 2 个浮点单元。&lt;/p&gt; &lt;p&gt;E-Core 访存：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Burst: 3 load uops, 2 store uops (address part), and 2 store uops (data part)&lt;ul&gt; &lt;li&gt;即 3 load, 2 sta, 2 std&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;Sustained: 4 uops, 2 write into the cache&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;和 M1 E-Core 相同。&lt;/p&gt; &lt;h4 id=&#34;p-core_13&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_13&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;在 M4 P-Core 上测试如下各类指令的延迟和每周期吞吐：&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;Instruction&lt;/th&gt; &lt;th&gt;Latency&lt;/th&gt; &lt;th&gt;Throughput&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;asimd int add&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd aesd/aese&lt;/td&gt; &lt;td&gt;2/3&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd aesimc/aesmc&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fabs&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fadd&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fdiv 64b&lt;/td&gt; &lt;td&gt;10&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fdiv 32b&lt;/td&gt; &lt;td&gt;8&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fmax&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fmin&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fmla&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fmul&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fneg&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd frecpe&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd frsqrte&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fsqrt 64b&lt;/td&gt; &lt;td&gt;13&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fsqrt 32b&lt;/td&gt; &lt;td&gt;10&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp cvtf2i (fcvtzs)&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp cvti2f (scvtf)&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fabs&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fadd&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv 64b&lt;/td&gt; &lt;td&gt;10&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv 32b&lt;/td&gt; &lt;td&gt;8&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fjcvtzs&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fmax&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fmin&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fmov f2i&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fmov i2f&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fmul&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fneg&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp frecpe&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp frecpx&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp frsqrte&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fsqrt 64b&lt;/td&gt; &lt;td&gt;13&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fsqrt 32b&lt;/td&gt; &lt;td&gt;10&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int add&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;7.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int addi&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;8&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int bfm&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int crc&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int csel&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int madd (addend)&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;2.8&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int madd (others)&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;td&gt;2.8&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int mrs nzcv&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int mul&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int nop&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;10&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int sbfm&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;8&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int sdiv&lt;/td&gt; &lt;td&gt;7&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int smull&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int ubfm&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;8&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int udiv&lt;/td&gt; &lt;td&gt;7&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;not taken branch&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;taken branch&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;1-2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;mem asimd load&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;mem asimd store&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;mem int load&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;mem int store&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;从上面的结果可以初步得到的信息：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;标量浮点和 ASIMD 吞吐最大都是 4，意味着有 4 个浮点/ASIMD 执行单元，但并非完全对称，例如 fdiv/frecpe/frecpx/frsqrte/fsqrt/fjcvtzs 由于吞吐不超过 1，大概率只能在一个执行单元内执行。但这些指令是不是都只能在同一个执行单元内执行，还需要进一步的测试；这部分和 M1 P-Core 相同，但浮点乘法 fmla/fmul 的延迟从 4 周期降低到了 3 周期&lt;/li&gt; &lt;li&gt;浮点和整数之间的 move 或 convert 指令，fmov i2f/cvti2f 吞吐是 3，fmov f2i/cvtf2i 吞吐是 2，那么这些指令是在哪个执行单元里实现的，是否需要同时占用整数执行单元和浮点执行单元，需要进一步测试；这部分和 M1 P-Core 相同&lt;/li&gt; &lt;li&gt;整数方面，根据吞吐，推断出如下几类指令对应的执行单元数量：&lt;ol&gt; &lt;li&gt;ALU: 8&lt;/li&gt; &lt;li&gt;CSEL: 4&lt;/li&gt; &lt;li&gt;Mul/MAdd: 3&lt;/li&gt; &lt;li&gt;Br/MRS NZCV: 2&lt;/li&gt; &lt;li&gt;CRC/BFM/Div: 1&lt;/li&gt; &lt;li&gt;ALU/CSEL/Mul/MAdd 的执行单元相比 M1 P-Core 有扩充&lt;/li&gt; &lt;/ol&gt; &lt;/li&gt; &lt;li&gt;访存方面，每周期最多 3 Load 或者 2 Store；这部分和 M1 P-Core 相同&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;首先来看浮点和 ASIMD 单元，根据上面的信息，认为至少有 4 个执行单元，每个执行单元都可以做这些操作：asimd int add/aes/fabs/fadd/fmax/fmin/fmla/fmul/fneg，下面把这些指令称为 basic fp/asimd ops + aes。接下来要判断，fmov f2i/fmov i2f/fdiv/frecpe/frecpx/frsqrte/fsqrt 由哪些执行单元负责执行，方法是把这些指令混合起来测试吞吐（此处的吞吐不代表 CPI，而是每周能够执行多少次指令组合，例如用 2 条指令的组合测试，那么吞吐等于 CPI 除以 2）：&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;指令&lt;/th&gt; &lt;th&gt;吞吐&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + fp frecpe&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + fp frecpx&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + fp frsqrte&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + fp fsqrt&lt;/td&gt; &lt;td&gt;0.33=1/3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + fmov f2i&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + 2x fmov f2i&lt;/td&gt; &lt;td&gt;0.33=1/3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + 3x fmov i2f&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + 4x fmov i2f&lt;/td&gt; &lt;td&gt;0.75=1/1.33&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fmov i2f + 4x fp fadd&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fmov f2i + 4x fp fadd&lt;/td&gt; &lt;td&gt;0.75=1/1.33&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;根据以上测试结果，可以得到如下的推论：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;fp fdiv/frecpe/frecpx/frsqrte 混合的时候，吞吐只有一半，IPC 不变，说明这些指令在同一个执行单元中，混合并不能带来更高的 IPC；这部分和 M1 P-Core 相同&lt;/li&gt; &lt;li&gt;fp fdiv 和 fp fsqrt 混合时，吞吐下降到 0.33 一个不太整的数字，猜测是因为它们属于同一个执行单元内的不同流水线，抢占寄存器堆写口；这部分和 M1 P-Core 相同&lt;/li&gt; &lt;li&gt;fp fdiv + fmov f2i 的时候吞吐是 0.5，而 fdiv + 2x fmov f2i 时吞吐下降到 0.33，IPC 维持在 1，说明有 1 个执行单元执行 fdiv 或 fmov f2i，但奇怪的是单独执行 fmov f2i 可以达到 2 的 IPC；这部分吞吐比 M1 P-Core 要差&lt;/li&gt; &lt;li&gt;fp fdiv + 3x fmov i2f 的时候吞吐是 1，而 fdiv + 4x fmov i2f 时吞吐下降到 0.75，此时每周期还是执行 3 条 fmov i2f 指令，意味着 fdiv 没有抢占 fmov i2f 的执行单元，它们用的执行单元是独立的；这部分和 M1 P-Core 相同&lt;/li&gt; &lt;li&gt;fmov i2f + 4x fp fadd 的时候吞吐是 1，说明 fmov i2f 没有抢占 fp fadd 的执行单元；这部分和 M1 P-Core 相同&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;推断这四个执行单元支持的操作：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;basic fp/asimd ops + aes + fdiv + frecpe + frecpx + frsqrte + fsqrt + fmov f2i + cvtf2i&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes + fmov f2i + cvtf2i&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;当然还有很多指令没有测，不过原理是一样的。这部分和 M1 P-Core 相同。&lt;/p&gt; &lt;p&gt;访存部分，前面已经在测 LSU 的时候测过了，每周期 Load + Store 不超过 4 个，其中 Load 不超过 3 个，Store 不超过 2 个。虽然从 IPC 的角度来看 LSU 的 Load/Store Pipe 未必准确，比如可能它发射和提交的带宽是不同的，但先暂时简化为如下的执行单元：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;load + store&lt;/li&gt; &lt;li&gt;load&lt;/li&gt; &lt;li&gt;load&lt;/li&gt; &lt;li&gt;store&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;这部分和 M1 P-Core 相同。&lt;/p&gt; &lt;p&gt;最后是整数部分。从 addi 的指令来看，有 8 个 ALU，能够执行基本的整数指令。但其他很多指令可能只有一部分执行单元可以执行：bfm/crc/csel/madd/mrs nzcv/mul/div/branch/fmov i2f。为了测试这些指令使用的执行单元是否重合，进行一系列的混合指令测试，吞吐的定义和上面相同：&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;指令&lt;/th&gt; &lt;th&gt;吞吐&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;4x int csel + 3x fmov i2f&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int csel + 2x fmov f2i&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;2x int csel + 2x fmov f2i&lt;/td&gt; &lt;td&gt;0.80=1/1.25&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;3x int csel + int bfm&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;4x int csel + int bfm&lt;/td&gt; &lt;td&gt;0.80=1/1.25&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;4x int csel + int crc&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;3x int csel + int madd&lt;/td&gt; &lt;td&gt;1.33=1/0.75&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;4x int csel + int madd&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;4x int csel + 2x int madd&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;4x int csel + 3x int madd&lt;/td&gt; &lt;td&gt;0.75=1/1.33&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;4x int csel + int mul&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;3x int csel + int sdiv&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;4x int csel + int sdiv&lt;/td&gt; &lt;td&gt;0.45=1/2.23&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;3x int csel + mrs nzcv&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;4x int csel + mrs nzcv&lt;/td&gt; &lt;td&gt;0.80=1/1.25&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;3x int csel + not taken branch&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;4x int csel + not taken branch&lt;/td&gt; &lt;td&gt;0.80=1/1.25&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;mrs nzcv + not taken branch&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;mrs nzcv + 2x not taken branch&lt;/td&gt; &lt;td&gt;0.67=1/1.50&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;2x fmov f2i + 2x not taken branch&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;2x fmov f2i + 2x int mul&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;2x int madd + int crc&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;3x int madd + int crc&lt;/td&gt; &lt;td&gt;0.75=1/1.33&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;2x int madd + int mul&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;3x int madd + int mul&lt;/td&gt; &lt;td&gt;0.75&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;2x int madd + int sdiv&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;3x int madd + int sdiv&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;3x int madd + mrs nzcv&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;根据上述结果分析：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;吞吐与不混合时相同，代表混合的指令对应的执行单元不重合&lt;/li&gt; &lt;li&gt;2x int madd + int mul 的 IPC 是 3，3x int add + int mul 的 IPC 也是 3，说明有三个执行单元可以执行 madd 和 mul：&lt;ol&gt; &lt;li&gt;alu + madd + mul&lt;/li&gt; &lt;li&gt;alu + madd + mul&lt;/li&gt; &lt;li&gt;alu + madd + mul&lt;/li&gt; &lt;/ol&gt; &lt;/li&gt; &lt;li&gt;2x int madd + int crc 的 IPC 是 3，3x int madd + int crc 的 IPC 也是 3，说明其中一个执行单元可以执行 crc：&lt;ol&gt; &lt;li&gt;alu + madd + mul + crc&lt;/li&gt; &lt;li&gt;alu + madd + mul&lt;/li&gt; &lt;li&gt;alu + madd + mul&lt;/li&gt; &lt;/ol&gt; &lt;/li&gt; &lt;li&gt;4x int csel + 2x int madd 的吞吐是 1，4x int csel + 3x int madd 的吞吐是 0.75，说明它们有一个重合的执行单元，并且由于 4x int csel + int crc 的吞吐是 1，所以重合的执行单元不是 crc 的那一个：&lt;ol&gt; &lt;li&gt;alu + madd + mul + crc&lt;/li&gt; &lt;li&gt;alu + madd + mul + csel&lt;/li&gt; &lt;li&gt;alu + madd + mul&lt;/li&gt; &lt;li&gt;alu + csel&lt;/li&gt; &lt;li&gt;alu + csel&lt;/li&gt; &lt;li&gt;alu + csel&lt;/li&gt; &lt;/ol&gt; &lt;/li&gt; &lt;li&gt;4x int csel + mrs nzcv 的 IPC 等于 4，说明 mrs nzcv 的执行单元被包括在能执行 csel 的四个执行单元当中；而 3x int madd + mrs nzcv 的吞吐等于 1，说明 mrs nzcv 的执行单元和 int madd 不重合：&lt;ol&gt; &lt;li&gt;alu + madd + mul + crc&lt;/li&gt; &lt;li&gt;alu + madd + mul + csel&lt;/li&gt; &lt;li&gt;alu + madd + mul&lt;/li&gt; &lt;li&gt;alu + csel + mrs nzcv&lt;/li&gt; &lt;li&gt;alu + csel + mrs nzcv&lt;/li&gt; &lt;li&gt;alu + csel&lt;/li&gt; &lt;/ol&gt; &lt;/li&gt; &lt;li&gt;因为 mrs nzcv + 2x not taken branch 的吞吐是 0.67，此时 IPC 等于 2，说明它们的执行单元重合：&lt;ol&gt; &lt;li&gt;alu + madd + mul + crc&lt;/li&gt; &lt;li&gt;alu + madd + mul + csel&lt;/li&gt; &lt;li&gt;alu + madd + mul&lt;/li&gt; &lt;li&gt;alu + csel + mrs nzcv + branch&lt;/li&gt; &lt;li&gt;alu + csel + mrs nzcv + branch&lt;/li&gt; &lt;li&gt;alu + csel&lt;/li&gt; &lt;/ol&gt; &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;得到初步的结果：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;alu + madd + mul + crc&lt;/li&gt; &lt;li&gt;alu + madd + mul + csel&lt;/li&gt; &lt;li&gt;alu + madd + mul&lt;/li&gt; &lt;li&gt;alu + csel + mrs nzcv + branch&lt;/li&gt; &lt;li&gt;alu + csel + mrs nzcv + branch&lt;/li&gt; &lt;li&gt;alu + csel&lt;/li&gt; &lt;li&gt;alu&lt;/li&gt; &lt;li&gt;alu&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;还有很多其他的指令没有测试，不过方法是类似的。从上面的结果里，可以看到一些值得一提的点：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;fmov f2i 同时占用了浮点执行单元和整数执行单元，这主要是为了复用寄存器堆读写口：fmov f2i 需要读浮点寄存器堆，又需要写整数寄存器堆，那就在浮点侧读寄存器，在整数侧写寄存器。&lt;/li&gt; &lt;li&gt;fmov i2f 既不在浮点，也不在整数，那只能在访存了：而正好访存执行单元需要读整数，写整数或浮点，那就可以复用它的寄存器堆写口来实现 fmov i2f 的功能。&lt;/li&gt; &lt;li&gt;可见整数/浮点/访存执行单元并不是完全隔离的，例如一些微架构，整数和浮点是直接放在一起的。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;小结：M4 P-Core 的执行单元如下：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;alu + madd + mul + crc&lt;/li&gt; &lt;li&gt;alu + madd + mul + csel&lt;/li&gt; &lt;li&gt;alu + madd + mul&lt;/li&gt; &lt;li&gt;alu + csel + mrs nzcv + branch&lt;/li&gt; &lt;li&gt;alu + csel + mrs nzcv + branch&lt;/li&gt; &lt;li&gt;alu + csel&lt;/li&gt; &lt;li&gt;alu&lt;/li&gt; &lt;li&gt;alu&lt;/li&gt; &lt;li&gt;load + store&lt;/li&gt; &lt;li&gt;load&lt;/li&gt; &lt;li&gt;load&lt;/li&gt; &lt;li&gt;store&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes + fdiv + frecpe + frecpx + frsqrte + fsqrt + fmov f2i + cvtf2i&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes + fmov f2i + cvtf2i&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;相比 M1 P-Core，只在整数方面有扩充。和官方的信息，除了 store data/address 部分没有探测出来以外都一致。&lt;/p&gt; &lt;h4 id=&#34;e-core_13&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_13&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;接下来用类似的方法测试 M4 E-Core：&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;Instruction&lt;/th&gt; &lt;th&gt;Latency&lt;/th&gt; &lt;th&gt;Throughput&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;asimd int add&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd aesd/aese&lt;/td&gt; &lt;td&gt;2.5/3&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd aesimc/aesmc&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fabs&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fadd&lt;/td&gt; &lt;td&gt;2.5&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fdiv 64b&lt;/td&gt; &lt;td&gt;11&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fdiv 32b&lt;/td&gt; &lt;td&gt;9&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fmax&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fmin&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fmla&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fmul&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fneg&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd frecpe&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd frsqrte&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fsqrt 64b&lt;/td&gt; &lt;td&gt;15&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;asimd fsqrt 32b&lt;/td&gt; &lt;td&gt;12&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp cvtf2i (fcvtzs)&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp cvti2f (scvtf)&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;1.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fabs&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fadd&lt;/td&gt; &lt;td&gt;2.5&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv 64b&lt;/td&gt; &lt;td&gt;10&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv 32b&lt;/td&gt; &lt;td&gt;8&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fjcvtzs&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fmax&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fmin&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fmov f2i&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fmov i2f&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fmul&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fneg&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp frecpe&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp frecpx&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp frsqrte&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fsqrt 64b&lt;/td&gt; &lt;td&gt;13&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fsqrt 32b&lt;/td&gt; &lt;td&gt;10&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int add&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;4&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int addi&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int bfm&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int crc&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int csel&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int madd (addend)&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int madd (others)&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int mrs nzcv&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int mul&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int nop&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int sbfm&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int sdiv&lt;/td&gt; &lt;td&gt;7&lt;/td&gt; &lt;td&gt;0.125=1/8&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int smull&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int ubfm&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;td&gt;3&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int udiv&lt;/td&gt; &lt;td&gt;7&lt;/td&gt; &lt;td&gt;0.125=1/8&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;not taken branch&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;taken branch&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;mem asimd load&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;mem asimd store&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;mem int load&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;2&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;mem int store&lt;/td&gt; &lt;td&gt;-&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;从上面的结果可以初步得到的信息：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;标量浮点和 ASIMD 吞吐最大都是 3，意味着有 3 个浮点/ASIMD 执行单元，但并非完全对称，例如 fdiv/frecpe/frecpx/frsqrte/fsqrt 由于吞吐不超过 1，大概率只能在一个执行单元内执行；fmla/fmul 的吞吐只有 2，只能在其中两个执行单元内执行。但这些指令是不是都只能在同一个执行单元内执行，还需要进一步的测试；相比 M1 E-Core，添加了一个浮点/ASIMD 执行单元&lt;/li&gt; &lt;li&gt;整数方面，根据吞吐，推断出如下几类指令对应的执行单元数量：&lt;ol&gt; &lt;li&gt;ALU: 4&lt;/li&gt; &lt;li&gt;CSEL/MRS NZCV/SBFM/UBFM: 3&lt;/li&gt; &lt;li&gt;Br: 2&lt;/li&gt; &lt;li&gt;Mul/CRC/BFM/MAdd/Div: 1&lt;/li&gt; &lt;li&gt;相比 M1 E-Core 增加了 ALU 的数量&lt;/li&gt; &lt;/ol&gt; &lt;/li&gt; &lt;li&gt;虽然 Br 的吞吐可以达到 2，但是每周期只能有一个 taken branch，和 M1 E-Core 相同&lt;/li&gt; &lt;li&gt;访存方面，每周期最多 2 Load 或者 1 Store，和 M1 E-Core 相同&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;还是先看浮点，基本指令 add/aes/fabs/fadd/fmax/fmin/fneg 都能做到 3 的吞吐，也就是这三个执行单元都能执行这些基本指令。接下来测其余指令的混合吞吐（吞吐定义见上）：&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;指令&lt;/th&gt; &lt;th&gt;吞吐&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + fp frecpe&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + fp frecpx&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + fp frsqrte&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + fp fsqrt&lt;/td&gt; &lt;td&gt;0.31=1/3.25&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + fmov f2i&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + 2x fmov f2i&lt;/td&gt; &lt;td&gt;0.66=1/1.50&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + 2x fmov i2f&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + 3x fmov i2f&lt;/td&gt; &lt;td&gt;0.67=1/1.50&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + fp fmul&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fdiv + 2x fp fmul&lt;/td&gt; &lt;td&gt;0.6&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp fmul + fmov f2i&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;2x fp fmul + fmov f2i&lt;/td&gt; &lt;td&gt;0.67=1/1.50&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;可见 fdiv/frecpe/frecpx/frsqrte/fsqrt 都在同一个执行单元内：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;basic fp/asimd ops + aes + fdiv + frecpe + frecpx + frsqrte + fsqrt&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;由于 fp fdiv + 2x fmov f2i 的 IPC 是 2，说明它们有重合的执行单元：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;basic fp/asimd ops + aes + fdiv + frecpe + frecpx + frsqrte + fsqrt + fmov f2i&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes + fmov f2i&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;因为 2x fp fmul + fmov f2i 的 IPC 也只有 2，说明 fp fmul 和 fmov f2i 是重合的：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;basic fp/asimd ops + aes + fdiv + frecpe + frecpx + frsqrte + fsqrt + fmov f2i + fmul&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes + fmov f2i + fmul&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;还有很多指令没有测，不过原理是一样的。访存在前面测 LSU 的时候已经测过了：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;load + store&lt;/li&gt; &lt;li&gt;load&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;最后是整数部分。从 add 的指令来看，有 4 个 ALU，能够执行基本的整数指令。但其他很多指令可能只有一部分执行单元可以执行：bfm/crc/csel/madd/mul/div/branch。为了测试这些指令使用的执行单元是否重合，进行一系列的混合指令测试，吞吐的定义和上面相同：&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;指令&lt;/th&gt; &lt;th&gt;吞吐&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;int madd + int mul&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int madd + int crc&lt;/td&gt; &lt;td&gt;0.5&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;int madd + 2x not taken branch&lt;/td&gt; &lt;td&gt;1&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;由此可见，madd/mul/crc 是一个执行单元，和 branch 的两个执行单元不重合，因此整数侧的执行单元有：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;alu + csel + mrs nzcv + branch&lt;/li&gt; &lt;li&gt;alu + csel + mrs nzcv + branch&lt;/li&gt; &lt;li&gt;alu + csel + mrs nzcv + madd + mul + crc&lt;/li&gt; &lt;li&gt;alu&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;小结：M4 E-Core 的执行单元如下：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;alu + csel + mrs nzcv + branch&lt;/li&gt; &lt;li&gt;alu + csel + mrs nzcv + branch&lt;/li&gt; &lt;li&gt;alu + csel + mrs nzcv + madd + mul + crc&lt;/li&gt; &lt;li&gt;alu&lt;/li&gt; &lt;li&gt;load + store&lt;/li&gt; &lt;li&gt;load&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes + fdiv + frecpe + frecpx + frsqrte + fsqrt + fmov f2i + fmul&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes + fmov f2i + fmul&lt;/li&gt; &lt;li&gt;basic fp/asimd ops + aes&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;相比 M1 E-Core，整数和浮点方面都有扩充。和官方的信息，除了 store data/address 部分没有探测出来以外都一致，更具体来说，应该更接近：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;load + sta&lt;/li&gt; &lt;li&gt;load + sta + std&lt;/li&gt; &lt;/ol&gt; &lt;h3 id=&#34;scheduler&#34;&gt;Scheduler&lt;a class=&#34;headerlink&#34; href=&#34;#scheduler&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;h4 id=&#34;p-core_14&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_14&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;在 M4 P-Core 上测试，结果如下：&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;指令&lt;/th&gt; &lt;th&gt;可调度 + 不可调度&lt;/th&gt; &lt;th&gt;可调度&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;ld&lt;/td&gt; &lt;td&gt;66&lt;/td&gt; &lt;td&gt;51&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;st addr&lt;/td&gt; &lt;td&gt;66&lt;/td&gt; &lt;td&gt;51&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;st data&lt;/td&gt; &lt;td&gt;86&lt;/td&gt; &lt;td&gt;70&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;alu&lt;/td&gt; &lt;td&gt;198&lt;/td&gt; &lt;td&gt;175&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fp&lt;/td&gt; &lt;td&gt;266&lt;/td&gt; &lt;td&gt;243&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;crc&lt;/td&gt; &lt;td&gt;36&lt;/td&gt; &lt;td&gt;23&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;idiv&lt;/td&gt; &lt;td&gt;36&lt;/td&gt; &lt;td&gt;23&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;bfm&lt;/td&gt; &lt;td&gt;31&lt;/td&gt; &lt;td&gt;18&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fjcvtzs&lt;/td&gt; &lt;td&gt;72&lt;/td&gt; &lt;td&gt;60&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;fmov f2i&lt;/td&gt; &lt;td&gt;144&lt;/td&gt; &lt;td&gt;121&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;csel&lt;/td&gt; &lt;td&gt;98&lt;/td&gt; &lt;td&gt;85&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;mrs nzcv&lt;/td&gt; &lt;td&gt;60&lt;/td&gt; &lt;td&gt;47&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;首先看浮点：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;可调度部分 fp 是 243，fmov f2i 是 121，fjcvtzs 是 60，有明显的 4:2:1 的关系&lt;/li&gt; &lt;li&gt;fp/fmov f2i/fjcvtzs 吞吐刚好也是 4:2:1 的关系&lt;/li&gt; &lt;li&gt;因此四个执行单元前面各有一个独立的 60 entry 的 Scheduler&lt;/li&gt; &lt;li&gt;不可调度部分，266-243=23，144-121=23，72-60=12，猜测有两个 Non Scheduling Queue，每个 Non Scheduling Queue 12 entry，分别对应两个 Scheduler&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;相比 M1 P-Core 有比较大的扩充：Scheduler 大小从 36 扩大到 60，Non Scheduling Queue 从 6 扩大到了 12。&lt;/p&gt; &lt;p&gt;下面是访存部分，load 和 store addr 一样，但 store data 要更多，可能做了不同的处理。&lt;/p&gt; &lt;p&gt;最后是整数部分，由于有 8 个整数执行单元，情况会比较复杂：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;可调度部分 alu 一共是 175，其中 csel 是 85，crc/idiv 都是 23，bfm 是 18，mrs nzcv 是 47，结合 8 个整数执行单元，可以得到这 8 个执行单元对应的 Scheduler 大小关系：&lt;ol&gt; &lt;li&gt;alu + madd + mul + crc: 23 entries&lt;/li&gt; &lt;li&gt;alu + madd + mul + csel: a entries&lt;/li&gt; &lt;li&gt;alu + madd + mul: b entries&lt;/li&gt; &lt;li&gt;alu + csel + mrs nzcv + branch: c entries&lt;/li&gt; &lt;li&gt;alu + csel + mrs nzcv + branch: 47-c entries&lt;/li&gt; &lt;li&gt;alu + csel: 38-a entries&lt;/li&gt; &lt;li&gt;alu: d entries&lt;/li&gt; &lt;li&gt;alu: 67-b-d entries&lt;/li&gt; &lt;/ol&gt; &lt;/li&gt; &lt;li&gt;alu 不可调度部分是 198-175=23，crc/idiv/bfm/csel/mrs nzcv 不可调度部分都是 13，应该是其中四个执行单元共享一个 12 entry 的 Non Scheduling Queue；另外四个执行单元共享剩下的 12 entry 的 Non Scheduling Queue&lt;/li&gt; &lt;li&gt;最后只差 a 到 d 的取值没有求出来，可以通过进一步测试来更加精确地求出&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;Scheduler 大小相比 M1 P-Core 有比较大的扩充，Non Scheduling Queue 没有变化。&lt;/p&gt; &lt;h4 id=&#34;e-core_14&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_14&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;在 M4 E-Core 上测试，结果很不稳定，需要进一步研究。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/sched_size_gen.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h3 id=&#34;reorder-buffer&#34;&gt;Reorder Buffer&lt;a class=&#34;headerlink&#34; href=&#34;#reorder-buffer&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;h4 id=&#34;p-core_15&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_15&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;首先用不同数量的 fsqrt 依赖链加 NOP 指令测试 M4 P-Core 的 ROB 大小：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-rob.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到当 fsqrt 数量足够多的时候，出现了统一的拐点，在 3184 条指令左右。&lt;/p&gt; &lt;p&gt;为了测 Coalesced ROB 的大小，改成用 load/store 指令，可以测到拐点在 313 左右：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-rob-load.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;3184 除以 313 约等于 10，意味着每个 group 可以保存 10 条指令，一共有 313 左右个 group。相比 M1 P-Core，Group 数量差不多，但是能保存的指令数量有了很大的提升。&lt;/p&gt; &lt;h4 id=&#34;e-core_15&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_15&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;首先用 NOP 指令测试 M4 E-Core 的 ROB 大小：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-e-core-rob.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到拐点是 513 条指令。&lt;/p&gt; &lt;p&gt;为了测 Coalesced ROB 的大小，改成用 load/store 指令，可以测到拐点在 121 左右：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-e-core-rob-load.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;但是 513 除以 121 是 4.24，离 4 或者 5 都有一段距离，比较奇怪，不确定每个 group 可以放多少条指令。容量上比 M1 E-Core 有明显提升。&lt;/p&gt; &lt;h3 id=&#34;l2-cache&#34;&gt;L2 Cache&lt;a class=&#34;headerlink&#34; href=&#34;#l2-cache&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：通过 sysctl 可以看到，4 个 M4 P-Core 核心共享一个 16MB L2 Cache，6 个 M4 E-Core 核心共享一个 4MB L2 Cache：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-3-1&#34;&gt;&lt;a id=&#34;__codelineno-3-1&#34; name=&#34;__codelineno-3-1&#34; href=&#34;#__codelineno-3-1&#34;&gt;&lt;/a&gt;hw.perflevel0.l2cachesize: 16777216 &lt;/span&gt;&lt;span id=&#34;__span-3-2&#34;&gt;&lt;a id=&#34;__codelineno-3-2&#34; name=&#34;__codelineno-3-2&#34; href=&#34;#__codelineno-3-2&#34;&gt;&lt;/a&gt;hw.perflevel0.cpusperl2: 4 &lt;/span&gt;&lt;span id=&#34;__span-3-3&#34;&gt;&lt;a id=&#34;__codelineno-3-3&#34; name=&#34;__codelineno-3-3&#34; href=&#34;#__codelineno-3-3&#34;&gt;&lt;/a&gt;hw.perflevel1.l2cachesize: 4194304 &lt;/span&gt;&lt;span id=&#34;__span-3-4&#34;&gt;&lt;a id=&#34;__codelineno-3-4&#34; name=&#34;__codelineno-3-4&#34; href=&#34;#__codelineno-3-4&#34;&gt;&lt;/a&gt;hw.perflevel1.cpusperl2: 6 &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;根据 Apple Silicon CPU Optimization Guide，L2 Cache 配置如下：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;M1 Family/A14 Bionic: P-Core cluster 12MiB, 12-way, 128B lines; E-Core cluster 4MiB, 16-way, 128B lines&lt;/li&gt; &lt;li&gt;M2/M3/M4 Family/A16 Bionic/A17 Pro/A18 Pro: P-Core cluster 16MiB, 16-way, 128B lines; E-Core cluster 4MiB, 16-way, 128B lines&lt;/li&gt; &lt;li&gt;A14 Bionic/A18: P-Core cluster 8MiB, 16-way, 128B lines; E-Core cluster 4MiB, 16-way, 128B lines&lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;memory-cache&#34;&gt;Memory Cache&lt;a class=&#34;headerlink&#34; href=&#34;#memory-cache&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：根据 Apple Silicon CPU Optimization Guide，Memory Cache（在别的处理器也叫 System Level Cache，就是 Last Level Cache）的配置如下：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;M1/M2/M3/M4: 8MiB, 16-way, 128B lines&lt;/li&gt; &lt;li&gt;M3 Pro/A18: 12MiB, 16-way, 128B lines&lt;/li&gt; &lt;li&gt;A14 Bionic: 16MiB, 16-way, 128B lines&lt;/li&gt; &lt;li&gt;M1 Pro/M2 Pro/M4 Pro/A16 Bionic/A17 Pro/A18 Pro: 24MiB, 12-way, 128B lines&lt;/li&gt; &lt;li&gt;A15 Bionic: 32MiB, 16-way, 128B lines&lt;/li&gt; &lt;li&gt;M1 Max/M2 Max/M3 Max/M4 Max: 48MiB, 12-way, 128B lines&lt;/li&gt; &lt;li&gt;M1 Ultra/M2 Ultra/M3 Ultra: 96MiB, 12-way, 128B lines&lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;l2-tlb&#34;&gt;L2 TLB&lt;a class=&#34;headerlink&#34; href=&#34;#l2-tlb&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：根据 Apple Silicon CPU Optimization Guide，P-Core 的 L2 TLB 容量，从 M1 Family 到 M4 Family，从 A14 Bionic 到 A18 Family，都是 3072 entries；E-Core 的 L2 TLB 容量，M1 Family 和 A14 Bionic 是 1024 entries，M2 Family 到 M4 Family 和 A15 Bionic 到 A18 Family 都是 2048 entries。&lt;/p&gt; &lt;h4 id=&#34;p-core_16&#34;&gt;P-Core&lt;a class=&#34;headerlink&#34; href=&#34;#p-core_16&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;沿用之前测试 L1 DTLB 的方法，把规模扩大到 L2 Unified TLB 的范围，就可以测出来 L2 Unified TLB 的容量，下面是 M4 P-Core 上的测试结果：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-p-core-l2tlb.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到拐点是 3072 个 Page，说明 M4 P-Core 的 L2 TLB 容量是 3072 项，和官方信息一致。这和 M1 P-Core 是一样的。&lt;/p&gt; &lt;h4 id=&#34;e-core_16&#34;&gt;E-Core&lt;a class=&#34;headerlink&#34; href=&#34;#e-core_16&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;在 M4 E-Core 上测试：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../apple-m4-e-core-l2tlb.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到拐点是 1024 个 Page，说明 M4 E-Core 的 L2 TLB 容量是 1024 项，和官方信息不一致，官方信息写的是 2048 项。这和 M1 E-Core 测出来是一样的。&lt;/p&gt; &lt;p&gt;&lt;a href=&#34;https://github.com/jiegec/cpu-micro-benchmarks/blob/master/src/dtlb_size.cpp&#34;&gt;测试过程详见测试代码&lt;/a&gt;。&lt;/p&gt; &lt;h2 id=&#34;总结&#34;&gt;总结&lt;a class=&#34;headerlink&#34; href=&#34;#总结&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;M4 相比 M1，在很多方面做了迭代：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;P-Core 的前端有较大改进，尤其是 BTB 部分&lt;/li&gt; &lt;li&gt;各种结构相比 M1 有了容量的增加&lt;/li&gt; &lt;li&gt;寄存器堆增加了对 32 位整数寄存器的优化&lt;/li&gt; &lt;li&gt;引入了 Load Address/Value Predictor&lt;/li&gt; &lt;li&gt;扩充了执行单元，P-Core 主要扩充了整数，E-Core 则是整数和浮点都做了扩充&lt;/li&gt; &lt;li&gt;添加了 SME 指令集&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;但也有一些遗憾，例如访存方面没有每周期带宽上的增加，P-Core 的浮点也没有增加。&lt;/p&gt;</description> <link>https://jia.je/hardware/2025/05/21/apple-m4/</link> <pubDate>Wed, 21 May 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2025/05/21/apple-m4/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2025/05/21/apple-m4.png" type="image/png" length="45457" /> </item> <item> <title>分析 Rocket Chip 中 Diplomacy 系统</title> <category>chisel</category> <category>diplomacy</category> <category>hardware</category> <category>rocketchip</category> <description>&lt;h1 id=&#34;分析-rocket-chip-中-diplomacy-系统&#34;&gt;分析 Rocket Chip 中 Diplomacy 系统&lt;a class=&#34;headerlink&#34; href=&#34;#分析-rocket-chip-中-diplomacy-系统&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;Rocket Chip 大量使用了 Diplomacy 系统来组织它的总线、中断和时钟网络。因此，如果想要对 Rocket Chip 进行定制，那么必须要对 Rocket Chip 中 Diplomacy 系统的使用有充分的了解，而这方面的文档比较欠缺。本文是对 Rocket Chip 中 Diplomacy 系统的使用的分析。阅读本文前，建议阅读先前的 &lt;a href=&#34;../../../../2022/01/05/diplomacy/&#34;&gt;分析 Diplomacy 系统&lt;/a&gt; 文章，对 Diplomacy 系统的设计和内部实现获得一定的了解。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;rocket-chip-总线结构概要&#34;&gt;Rocket Chip 总线结构概要&lt;a class=&#34;headerlink&#34; href=&#34;#rocket-chip-总线结构概要&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;Rocket Chip 主要有以下几个总线：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;sbus: System Bus&lt;/li&gt; &lt;li&gt;mbus: Memory Bus&lt;/li&gt; &lt;li&gt;cbus: Control Bus&lt;/li&gt; &lt;li&gt;pbus: Periphery Bus&lt;/li&gt; &lt;li&gt;fbus: Frontend Bus&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;图示可以见参考文档中的链接，不过链接中的结构和实际的有一些区别。目前的 Rocket Chip 的总线结构大致是这样：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-0-1&#34;&gt;&lt;a id=&#34;__codelineno-0-1&#34; name=&#34;__codelineno-0-1&#34; href=&#34;#__codelineno-0-1&#34;&gt;&lt;/a&gt;fbus -&amp;gt; sbus -&amp;gt; mbus &lt;/span&gt;&lt;span id=&#34;__span-0-2&#34;&gt;&lt;a id=&#34;__codelineno-0-2&#34; name=&#34;__codelineno-0-2&#34; href=&#34;#__codelineno-0-2&#34;&gt;&lt;/a&gt;tile --/ \-&amp;gt; cbus -&amp;gt; pbus &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;主要是 pbus 的位置从连接 sbus 移动到了连接 cbus。&lt;/p&gt; &lt;p&gt;根据配置不同，总线结构也不同，例如在有 coh(coherence manager) 的时候，是：&lt;/p&gt; &lt;div class=&#34;language-text highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-1-1&#34;&gt;&lt;a id=&#34;__codelineno-1-1&#34; name=&#34;__codelineno-1-1&#34; href=&#34;#__codelineno-1-1&#34;&gt;&lt;/a&gt;fbus -&amp;gt; sbus -&amp;gt; coh -&amp;gt; mbus &lt;/span&gt;&lt;span id=&#34;__span-1-2&#34;&gt;&lt;a id=&#34;__codelineno-1-2&#34; name=&#34;__codelineno-1-2&#34; href=&#34;#__codelineno-1-2&#34;&gt;&lt;/a&gt;tile --/ \-&amp;gt; cbus -&amp;gt; pbus &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;h2 id=&#34;深入分析-rocket-chip-总线结构&#34;&gt;深入分析 Rocket Chip 总线结构&lt;a class=&#34;headerlink&#34; href=&#34;#深入分析-rocket-chip-总线结构&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;下面是一个双核 Rocket Chip 的 GraphML 导出来用 yED 绘制的架构图：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../rocket-chip-diplomacy.svg&#34; /&gt;&lt;/p&gt; &lt;p&gt;接下来深入分析图中的各个连接关系以及对应的代码。&lt;/p&gt; &lt;h3 id=&#34;tilelink-和-axi-总线&#34;&gt;TileLink 和 AXI 总线&lt;a class=&#34;headerlink&#34; href=&#34;#tilelink-和-axi-总线&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;这个图比较复杂，混合了多个 Diplomacy 网络，首先是总线的部分，包括 TileLink 和 AXI：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;两个 Tile，对应一个双核的系统；每个 Tile 内部有一个 dcache 和 icache，连接到一个 tlMasterXbar 上，再通过 coupler_from_rockettile 连接到 fixer 再到 system_bus_xbar&lt;/li&gt; &lt;li&gt;从 system_bus_xbar 分出来三路 Slave：&lt;ol&gt; &lt;li&gt;第一路是 cbus，通过 out_xbar，连接到多个 slave：debug，error device，plic，clint，l2 control，bootrom&lt;/li&gt; &lt;li&gt;第二路是 mmio，通过 tl2axi4，转成 AXI4 连接到外部的 MMIO 外设&lt;/li&gt; &lt;li&gt;第三路是 coh，连接到 InclusiveCache，再连接到 mbus，通过 tl2axi4，转成 AXI4 连接到外部的内存&lt;/li&gt; &lt;/ol&gt; &lt;/li&gt; &lt;li&gt;system_bus_xbar 除了每个 tile 对应一个 master 以外，还有一个 master：fbus，它从外部的 AXI4 进来，通过 axi42tl 转换，接到 fbus，提供一个有缓存一致性的 AXI 访问接口，用于 DMA&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;简化后的结构如图：&lt;/p&gt; &lt;pre class=&#34;mermaid&#34;&gt;&lt;code&gt;flowchart TD subgraph tile0 dcache0[dcache] icache0[icache] tlMasterXbar0[tlMasterXbar] dcache0 --&amp;gt; tlMasterXbar0 icache0 --&amp;gt; tlMasterXbar0 end subgraph tile1 dcache1[dcache] icache1[icache] tlMasterXbar1[tlMasterXbar] dcache1 --&amp;gt; tlMasterXbar1 icache1 --&amp;gt; tlMasterXbar1 end sbus tlMasterXbar0 --&amp;gt; sbus tlMasterXbar1 --&amp;gt; sbus axi_fbus --&amp;gt; axi42tl --&amp;gt; fbus --&amp;gt; sbus sbus --&amp;gt; cbus --&amp;gt; out_xbar out_xbar --&amp;gt; debug out_xbar --&amp;gt; error out_xbar --&amp;gt; plit out_xbar --&amp;gt; clint out_xbar --&amp;gt; l2_ctrl out_xbar --&amp;gt; bootrom cbus --&amp;gt; pbus sbus --&amp;gt; tl2axi4_mmio[tl2axi4] --&amp;gt; axi_mmio sbus --&amp;gt; coh --&amp;gt; mbus --&amp;gt; tl2axi4_mem[tl2axi4] --&amp;gt; axi_mem&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;那么这些连接关系在代码中是怎么搭建的呢：&lt;/p&gt; &lt;ol&gt; &lt;li&gt; &lt;p&gt;首先是 tile 内部，dcache 和 icache 分别通过一个 widget 连到一个 tlMasterXbar 上：&lt;/p&gt; &lt;p&gt;&lt;div class=&#34;language-scala highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-2-1&#34;&gt;&lt;a id=&#34;__codelineno-2-1&#34; name=&#34;__codelineno-2-1&#34; href=&#34;#__codelineno-2-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Frontend&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;icacheParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ICacheParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tileId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;implicit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Parameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;extends&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;LazyModule&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-2&#34;&gt;&lt;a id=&#34;__codelineno-2-2&#34; name=&#34;__codelineno-2-2&#34; href=&#34;#__codelineno-2-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;lazy&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;module&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;FrontendModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-3&#34;&gt;&lt;a id=&#34;__codelineno-2-3&#34; name=&#34;__codelineno-2-3&#34; href=&#34;#__codelineno-2-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// icache resides in frontend&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-4&#34;&gt;&lt;a id=&#34;__codelineno-2-4&#34; name=&#34;__codelineno-2-4&#34; href=&#34;#__codelineno-2-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;icache&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;LazyModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ICache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;icacheParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tileId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-5&#34;&gt;&lt;a id=&#34;__codelineno-2-5&#34; name=&#34;__codelineno-2-5&#34; href=&#34;#__codelineno-2-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;masterNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;icache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;masterNode&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-6&#34;&gt;&lt;a id=&#34;__codelineno-2-6&#34; name=&#34;__codelineno-2-6&#34; href=&#34;#__codelineno-2-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slaveNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;icache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slaveNode&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-7&#34;&gt;&lt;a id=&#34;__codelineno-2-7&#34; name=&#34;__codelineno-2-7&#34; href=&#34;#__codelineno-2-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resetVectorSinkNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BundleBridgeSink&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;UInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;](&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;UInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;masterNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;edges&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bundle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;addressBits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;W&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-8&#34;&gt;&lt;a id=&#34;__codelineno-2-8&#34; name=&#34;__codelineno-2-8&#34; href=&#34;#__codelineno-2-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-9&#34;&gt;&lt;a id=&#34;__codelineno-2-9&#34; name=&#34;__codelineno-2-9&#34; href=&#34;#__codelineno-2-9&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-10&#34;&gt;&lt;a id=&#34;__codelineno-2-10&#34; name=&#34;__codelineno-2-10&#34; href=&#34;#__codelineno-2-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;trait&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HasICacheFrontend&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;extends&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CanHavePTW&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BaseTile&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-11&#34;&gt;&lt;a id=&#34;__codelineno-2-11&#34; name=&#34;__codelineno-2-11&#34; href=&#34;#__codelineno-2-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;frontend&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;LazyModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Frontend&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tileParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;icache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tileId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-12&#34;&gt;&lt;a id=&#34;__codelineno-2-12&#34; name=&#34;__codelineno-2-12&#34; href=&#34;#__codelineno-2-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// tlMasterXbar.node &amp;lt;-- TLWidthWidget &amp;lt;-- frontend.masterNode(i.e. icache.masterNode)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-13&#34;&gt;&lt;a id=&#34;__codelineno-2-13&#34; name=&#34;__codelineno-2-13&#34; href=&#34;#__codelineno-2-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlMasterXbar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLWidthWidget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tileParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;icache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rowBits&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;frontend&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;masterNode&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-14&#34;&gt;&lt;a id=&#34;__codelineno-2-14&#34; name=&#34;__codelineno-2-14&#34; href=&#34;#__codelineno-2-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-15&#34;&gt;&lt;a id=&#34;__codelineno-2-15&#34; name=&#34;__codelineno-2-15&#34; href=&#34;#__codelineno-2-15&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-16&#34;&gt;&lt;a id=&#34;__codelineno-2-16&#34; name=&#34;__codelineno-2-16&#34; href=&#34;#__codelineno-2-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;trait&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HasHellaCache&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BaseTile&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-17&#34;&gt;&lt;a id=&#34;__codelineno-2-17&#34; name=&#34;__codelineno-2-17&#34; href=&#34;#__codelineno-2-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;lazy&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dcache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HellaCache&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;LazyModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BuildHellaCache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-18&#34;&gt;&lt;a id=&#34;__codelineno-2-18&#34; name=&#34;__codelineno-2-18&#34; href=&#34;#__codelineno-2-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlMasterXbar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLWidthWidget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tileParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dcache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rowBits&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dcache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-2-19&#34;&gt;&lt;a id=&#34;__codelineno-2-19&#34; name=&#34;__codelineno-2-19&#34; href=&#34;#__codelineno-2-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; 2. 其次是每个 tile 的 tlMasterXbar 连接到 coupler_from_rockettile，再连到 sbus(system_bus_xbar)&lt;/p&gt; &lt;div class=&#34;language-scala highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-3-1&#34;&gt;&lt;a id=&#34;__codelineno-3-1&#34; name=&#34;__codelineno-3-1&#34; href=&#34;#__codelineno-3-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// in HasTiles.scala&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-2&#34;&gt;&lt;a id=&#34;__codelineno-3-2&#34; name=&#34;__codelineno-3-2&#34; href=&#34;#__codelineno-3-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cm&#34;&gt;/** Connect the port where the tile is the master to a TileLink interconnect. */&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-3&#34;&gt;&lt;a id=&#34;__codelineno-3-3&#34; name=&#34;__codelineno-3-3&#34; href=&#34;#__codelineno-3-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;connectMasterPorts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;domain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TilePRCIDomain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TileType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Attachable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Unit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-4&#34;&gt;&lt;a id=&#34;__codelineno-3-4&#34; name=&#34;__codelineno-3-4&#34; href=&#34;#__codelineno-3-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;implicit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-5&#34;&gt;&lt;a id=&#34;__codelineno-3-5&#34; name=&#34;__codelineno-3-5&#34; href=&#34;#__codelineno-3-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// crossingParams.master.where defaults to SBUS, see below&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-6&#34;&gt;&lt;a id=&#34;__codelineno-3-6&#34; name=&#34;__codelineno-3-6&#34; href=&#34;#__codelineno-3-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// so dataBus is system_bus_xbar&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-7&#34;&gt;&lt;a id=&#34;__codelineno-3-7&#34; name=&#34;__codelineno-3-7&#34; href=&#34;#__codelineno-3-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dataBus&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;locateTLBusWrapper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossingParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;master&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-8&#34;&gt;&lt;a id=&#34;__codelineno-3-8&#34; name=&#34;__codelineno-3-8&#34; href=&#34;#__codelineno-3-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// coupler_from_rockettile (val baseName = &amp;quot;rockettile&amp;quot; in RocketTileParams)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-9&#34;&gt;&lt;a id=&#34;__codelineno-3-9&#34; name=&#34;__codelineno-3-9&#34; href=&#34;#__codelineno-3-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dataBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coupleFrom&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tileParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;baseName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bus&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-10&#34;&gt;&lt;a id=&#34;__codelineno-3-10&#34; name=&#34;__codelineno-3-10&#34; href=&#34;#__codelineno-3-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// crossMasterPort is defined below&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-11&#34;&gt;&lt;a id=&#34;__codelineno-3-11&#34; name=&#34;__codelineno-3-11&#34; href=&#34;#__codelineno-3-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bus&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossingParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;master&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;injectNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;domain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossMasterPort&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossingParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossingType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-12&#34;&gt;&lt;a id=&#34;__codelineno-3-12&#34; name=&#34;__codelineno-3-12&#34; href=&#34;#__codelineno-3-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-13&#34;&gt;&lt;a id=&#34;__codelineno-3-13&#34; name=&#34;__codelineno-3-13&#34; href=&#34;#__codelineno-3-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-14&#34;&gt;&lt;a id=&#34;__codelineno-3-14&#34; name=&#34;__codelineno-3-14&#34; href=&#34;#__codelineno-3-14&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-15&#34;&gt;&lt;a id=&#34;__codelineno-3-15&#34; name=&#34;__codelineno-3-15&#34; href=&#34;#__codelineno-3-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// in HierarchicalElementPRCIDomain.scala&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-16&#34;&gt;&lt;a id=&#34;__codelineno-3-16&#34; name=&#34;__codelineno-3-16&#34; href=&#34;#__codelineno-3-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;crossMasterPort&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossingType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ClockCrossingType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLOutwardNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-17&#34;&gt;&lt;a id=&#34;__codelineno-3-17&#34; name=&#34;__codelineno-3-17&#34; href=&#34;#__codelineno-3-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlMasterResetXing&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;DisableMonitors&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;implicit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-18&#34;&gt;&lt;a id=&#34;__codelineno-3-18&#34; name=&#34;__codelineno-3-18&#34; href=&#34;#__codelineno-3-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;element&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;element&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;makeMasterBoundaryBuffers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossingType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=*&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-19&#34;&gt;&lt;a id=&#34;__codelineno-3-19&#34; name=&#34;__codelineno-3-19&#34; href=&#34;#__codelineno-3-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// masterNode is defined below&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-20&#34;&gt;&lt;a id=&#34;__codelineno-3-20&#34; name=&#34;__codelineno-3-20&#34; href=&#34;#__codelineno-3-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;element_reset_domain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossTLOut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;element&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;masterNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-21&#34;&gt;&lt;a id=&#34;__codelineno-3-21&#34; name=&#34;__codelineno-3-21&#34; href=&#34;#__codelineno-3-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-22&#34;&gt;&lt;a id=&#34;__codelineno-3-22&#34; name=&#34;__codelineno-3-22&#34; href=&#34;#__codelineno-3-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlMasterClockXing&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossOut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlMasterResetXing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-23&#34;&gt;&lt;a id=&#34;__codelineno-3-23&#34; name=&#34;__codelineno-3-23&#34; href=&#34;#__codelineno-3-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlMasterClockXing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossingType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-24&#34;&gt;&lt;a id=&#34;__codelineno-3-24&#34; name=&#34;__codelineno-3-24&#34; href=&#34;#__codelineno-3-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-25&#34;&gt;&lt;a id=&#34;__codelineno-3-25&#34; name=&#34;__codelineno-3-25&#34; href=&#34;#__codelineno-3-25&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-26&#34;&gt;&lt;a id=&#34;__codelineno-3-26&#34; name=&#34;__codelineno-3-26&#34; href=&#34;#__codelineno-3-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// in RocketTile.scala&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-27&#34;&gt;&lt;a id=&#34;__codelineno-3-27&#34; name=&#34;__codelineno-3-27&#34; href=&#34;#__codelineno-3-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;tlOtherMastersNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlMasterXbar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-28&#34;&gt;&lt;a id=&#34;__codelineno-3-28&#34; name=&#34;__codelineno-3-28&#34; href=&#34;#__codelineno-3-28&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;masterNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlOtherMastersNode&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-29&#34;&gt;&lt;a id=&#34;__codelineno-3-29&#34; name=&#34;__codelineno-3-29&#34; href=&#34;#__codelineno-3-29&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-30&#34;&gt;&lt;a id=&#34;__codelineno-3-30&#34; name=&#34;__codelineno-3-30&#34; href=&#34;#__codelineno-3-30&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// crossingParams defaults to RocketCrossingParams()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-31&#34;&gt;&lt;a id=&#34;__codelineno-3-31&#34; name=&#34;__codelineno-3-31&#34; href=&#34;#__codelineno-3-31&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// in RocketSubsystem.scala&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-32&#34;&gt;&lt;a id=&#34;__codelineno-3-32&#34; name=&#34;__codelineno-3-32&#34; href=&#34;#__codelineno-3-32&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;RocketCrossingParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-33&#34;&gt;&lt;a id=&#34;__codelineno-3-33&#34; name=&#34;__codelineno-3-33&#34; href=&#34;#__codelineno-3-33&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossingType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ClockCrossingType&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SynchronousCrossing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-34&#34;&gt;&lt;a id=&#34;__codelineno-3-34&#34; name=&#34;__codelineno-3-34&#34; href=&#34;#__codelineno-3-34&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;master&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HierarchicalElementPortParamsLike&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HierarchicalElementMasterPortParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-35&#34;&gt;&lt;a id=&#34;__codelineno-3-35&#34; name=&#34;__codelineno-3-35&#34; href=&#34;#__codelineno-3-35&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slave&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HierarchicalElementSlavePortParams&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HierarchicalElementSlavePortParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-36&#34;&gt;&lt;a id=&#34;__codelineno-3-36&#34; name=&#34;__codelineno-3-36&#34; href=&#34;#__codelineno-3-36&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mmioBaseAddressPrefixWhere&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperLocation&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-37&#34;&gt;&lt;a id=&#34;__codelineno-3-37&#34; name=&#34;__codelineno-3-37&#34; href=&#34;#__codelineno-3-37&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resetCrossingType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ResetCrossingType&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;NoResetCrossing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-38&#34;&gt;&lt;a id=&#34;__codelineno-3-38&#34; name=&#34;__codelineno-3-38&#34; href=&#34;#__codelineno-3-38&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;forceSeparateClockReset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Boolean&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-39&#34;&gt;&lt;a id=&#34;__codelineno-3-39&#34; name=&#34;__codelineno-3-39&#34; href=&#34;#__codelineno-3-39&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;extends&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HierarchicalElementCrossingParamsLike&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-40&#34;&gt;&lt;a id=&#34;__codelineno-3-40&#34; name=&#34;__codelineno-3-40&#34; href=&#34;#__codelineno-3-40&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-41&#34;&gt;&lt;a id=&#34;__codelineno-3-41&#34; name=&#34;__codelineno-3-41&#34; href=&#34;#__codelineno-3-41&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// default crossingParams.master.where is SBUS(System Bus)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-42&#34;&gt;&lt;a id=&#34;__codelineno-3-42&#34; name=&#34;__codelineno-3-42&#34; href=&#34;#__codelineno-3-42&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HierarchicalElementMasterPortParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-43&#34;&gt;&lt;a id=&#34;__codelineno-3-43&#34; name=&#34;__codelineno-3-43&#34; href=&#34;#__codelineno-3-43&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;buffers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Int&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-44&#34;&gt;&lt;a id=&#34;__codelineno-3-44&#34; name=&#34;__codelineno-3-44&#34; href=&#34;#__codelineno-3-44&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cork&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Option&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Boolean&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-45&#34;&gt;&lt;a id=&#34;__codelineno-3-45&#34; name=&#34;__codelineno-3-45&#34; href=&#34;#__codelineno-3-45&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperLocation&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SBUS&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-46&#34;&gt;&lt;a id=&#34;__codelineno-3-46&#34; name=&#34;__codelineno-3-46&#34; href=&#34;#__codelineno-3-46&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;extends&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HierarchicalElementPortParamsLike&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-47&#34;&gt;&lt;a id=&#34;__codelineno-3-47&#34; name=&#34;__codelineno-3-47&#34; href=&#34;#__codelineno-3-47&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;injectNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Attachable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;implicit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Parameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-48&#34;&gt;&lt;a id=&#34;__codelineno-3-48&#34; name=&#34;__codelineno-3-48&#34; href=&#34;#__codelineno-3-48&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;chainNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;buffers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cork&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLCacheCork&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;unsafe&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getOrElse&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLTempNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-49&#34;&gt;&lt;a id=&#34;__codelineno-3-49&#34; name=&#34;__codelineno-3-49&#34; href=&#34;#__codelineno-3-49&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-3-50&#34;&gt;&lt;a id=&#34;__codelineno-3-50&#34; name=&#34;__codelineno-3-50&#34; href=&#34;#__codelineno-3-50&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;接着是 sbus 连接到 coh，coh 连接到 mbus：&lt;/p&gt; &lt;div class=&#34;language-scala highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-4-1&#34;&gt;&lt;a id=&#34;__codelineno-4-1&#34; name=&#34;__codelineno-4-1&#34; href=&#34;#__codelineno-4-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// in BusTopology.scala&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-2&#34;&gt;&lt;a id=&#34;__codelineno-4-2&#34; name=&#34;__codelineno-4-2&#34; href=&#34;#__codelineno-4-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cm&#34;&gt;/** Parameterization of a topology containing a banked coherence manager and a bus for attaching memory devices. */&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-3&#34;&gt;&lt;a id=&#34;__codelineno-4-3&#34; name=&#34;__codelineno-4-3&#34; href=&#34;#__codelineno-4-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CoherentBusTopologyParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-4&#34;&gt;&lt;a id=&#34;__codelineno-4-4&#34; name=&#34;__codelineno-4-4&#34; href=&#34;#__codelineno-4-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;MemoryBusParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-5&#34;&gt;&lt;a id=&#34;__codelineno-4-5&#34; name=&#34;__codelineno-4-5&#34; href=&#34;#__codelineno-4-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coherence&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BankedCoherenceParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-6&#34;&gt;&lt;a id=&#34;__codelineno-4-6&#34; name=&#34;__codelineno-4-6&#34; href=&#34;#__codelineno-4-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sbusToMbusXType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ClockCrossingType&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;NoCrossing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-7&#34;&gt;&lt;a id=&#34;__codelineno-4-7&#34; name=&#34;__codelineno-4-7&#34; href=&#34;#__codelineno-4-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;driveMBusClockFromSBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Boolean&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-8&#34;&gt;&lt;a id=&#34;__codelineno-4-8&#34; name=&#34;__codelineno-4-8&#34; href=&#34;#__codelineno-4-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;extends&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperTopology&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-9&#34;&gt;&lt;a id=&#34;__codelineno-4-9&#34; name=&#34;__codelineno-4-9&#34; href=&#34;#__codelineno-4-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// instantiate mbus and coherence manager&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-10&#34;&gt;&lt;a id=&#34;__codelineno-4-10&#34; name=&#34;__codelineno-4-10&#34; href=&#34;#__codelineno-4-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;instantiations&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coherence&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nBanks&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-11&#34;&gt;&lt;a id=&#34;__codelineno-4-11&#34; name=&#34;__codelineno-4-11&#34; href=&#34;#__codelineno-4-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;MBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-12&#34;&gt;&lt;a id=&#34;__codelineno-4-12&#34; name=&#34;__codelineno-4-12&#34; href=&#34;#__codelineno-4-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;COH&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CoherenceManagerWrapperParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;blockBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beatBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coherence&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nBanks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;COH&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coherence&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coherenceManager&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-13&#34;&gt;&lt;a id=&#34;__codelineno-4-13&#34; name=&#34;__codelineno-4-13&#34; href=&#34;#__codelineno-4-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;connections&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coherence&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nBanks&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-14&#34;&gt;&lt;a id=&#34;__codelineno-4-14&#34; name=&#34;__codelineno-4-14&#34; href=&#34;#__codelineno-4-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// (master, slave, parameters)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-15&#34;&gt;&lt;a id=&#34;__codelineno-4-15&#34; name=&#34;__codelineno-4-15&#34; href=&#34;#__codelineno-4-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// coh := sbus&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-16&#34;&gt;&lt;a id=&#34;__codelineno-4-16&#34; name=&#34;__codelineno-4-16&#34; href=&#34;#__codelineno-4-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;COH&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperConnection&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;driveClockFromMaster&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nodeBinding&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BIND_STAR&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)()),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-17&#34;&gt;&lt;a id=&#34;__codelineno-4-17&#34; name=&#34;__codelineno-4-17&#34; href=&#34;#__codelineno-4-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// mbus := coh&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-18&#34;&gt;&lt;a id=&#34;__codelineno-4-18&#34; name=&#34;__codelineno-4-18&#34; href=&#34;#__codelineno-4-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;COH&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;MBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperConnection&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossTo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-19&#34;&gt;&lt;a id=&#34;__codelineno-4-19&#34; name=&#34;__codelineno-4-19&#34; href=&#34;#__codelineno-4-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xType&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sbusToMbusXType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-20&#34;&gt;&lt;a id=&#34;__codelineno-4-20&#34; name=&#34;__codelineno-4-20&#34; href=&#34;#__codelineno-4-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;driveClockFromMaster&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;driveMBusClockFromSBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-21&#34;&gt;&lt;a id=&#34;__codelineno-4-21&#34; name=&#34;__codelineno-4-21&#34; href=&#34;#__codelineno-4-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nodeBinding&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BIND_QUERY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-22&#34;&gt;&lt;a id=&#34;__codelineno-4-22&#34; name=&#34;__codelineno-4-22&#34; href=&#34;#__codelineno-4-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-23&#34;&gt;&lt;a id=&#34;__codelineno-4-23&#34; name=&#34;__codelineno-4-23&#34; href=&#34;#__codelineno-4-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-24&#34;&gt;&lt;a id=&#34;__codelineno-4-24&#34; name=&#34;__codelineno-4-24&#34; href=&#34;#__codelineno-4-24&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-25&#34;&gt;&lt;a id=&#34;__codelineno-4-25&#34; name=&#34;__codelineno-4-25&#34; href=&#34;#__codelineno-4-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// in BusWrapper.scala&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-26&#34;&gt;&lt;a id=&#34;__codelineno-4-26&#34; name=&#34;__codelineno-4-26&#34; href=&#34;#__codelineno-4-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperTopology&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-27&#34;&gt;&lt;a id=&#34;__codelineno-4-27&#34; name=&#34;__codelineno-4-27&#34; href=&#34;#__codelineno-4-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;instantiations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Seq&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Location&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperInstantiationLike&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)],&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-28&#34;&gt;&lt;a id=&#34;__codelineno-4-28&#34; name=&#34;__codelineno-4-28&#34; href=&#34;#__codelineno-4-28&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;connections&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Seq&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Location&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Location&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperConnectionLike&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)]&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-29&#34;&gt;&lt;a id=&#34;__codelineno-4-29&#34; name=&#34;__codelineno-4-29&#34; href=&#34;#__codelineno-4-29&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;extends&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CanInstantiateWithinContextThatHasTileLinkLocations&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-30&#34;&gt;&lt;a id=&#34;__codelineno-4-30&#34; name=&#34;__codelineno-4-30&#34; href=&#34;#__codelineno-4-30&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CanConnectWithinContextThatHasTileLinkLocations&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-31&#34;&gt;&lt;a id=&#34;__codelineno-4-31&#34; name=&#34;__codelineno-4-31&#34; href=&#34;#__codelineno-4-31&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-32&#34;&gt;&lt;a id=&#34;__codelineno-4-32&#34; name=&#34;__codelineno-4-32&#34; href=&#34;#__codelineno-4-32&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;instantiate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HasTileLinkLocations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;implicit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Parameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Unit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-33&#34;&gt;&lt;a id=&#34;__codelineno-4-33&#34; name=&#34;__codelineno-4-33&#34; href=&#34;#__codelineno-4-33&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;instantiations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;foreach&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;loc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;instantiate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;loc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-34&#34;&gt;&lt;a id=&#34;__codelineno-4-34&#34; name=&#34;__codelineno-4-34&#34; href=&#34;#__codelineno-4-34&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-35&#34;&gt;&lt;a id=&#34;__codelineno-4-35&#34; name=&#34;__codelineno-4-35&#34; href=&#34;#__codelineno-4-35&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;connect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HasTileLinkLocations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;implicit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Parameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Unit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-36&#34;&gt;&lt;a id=&#34;__codelineno-4-36&#34; name=&#34;__codelineno-4-36&#34; href=&#34;#__codelineno-4-36&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;connections&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;foreach&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;master&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slave&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;connect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;master&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slave&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-37&#34;&gt;&lt;a id=&#34;__codelineno-4-37&#34; name=&#34;__codelineno-4-37&#34; href=&#34;#__codelineno-4-37&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-4-38&#34;&gt;&lt;a id=&#34;__codelineno-4-38&#34; name=&#34;__codelineno-4-38&#34; href=&#34;#__codelineno-4-38&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;为了让 Rocket Chip 可以访问外部的 AXI MMIO 设备，在 sbus 下面添加了 tl 到 axi 的一条路径：&lt;/p&gt; &lt;div class=&#34;language-scala highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-5-1&#34;&gt;&lt;a id=&#34;__codelineno-5-1&#34; name=&#34;__codelineno-5-1&#34; href=&#34;#__codelineno-5-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cm&#34;&gt;/** Adds a AXI4 port to the system intended to master an MMIO device bus */&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-2&#34;&gt;&lt;a id=&#34;__codelineno-5-2&#34; name=&#34;__codelineno-5-2&#34; href=&#34;#__codelineno-5-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;trait&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CanHaveMasterAXI4MMIOPort&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BaseSubsystem&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-3&#34;&gt;&lt;a id=&#34;__codelineno-5-3&#34; name=&#34;__codelineno-5-3&#34; href=&#34;#__codelineno-5-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mmioPortParamsOpt&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ExtBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-4&#34;&gt;&lt;a id=&#34;__codelineno-5-4&#34; name=&#34;__codelineno-5-4&#34; href=&#34;#__codelineno-5-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;portName&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;mmio_port_axi4&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-5&#34;&gt;&lt;a id=&#34;__codelineno-5-5&#34; name=&#34;__codelineno-5-5&#34; href=&#34;#__codelineno-5-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;device&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SimpleBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;portName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kebab&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Nil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-6&#34;&gt;&lt;a id=&#34;__codelineno-5-6&#34; name=&#34;__codelineno-5-6&#34; href=&#34;#__codelineno-5-6&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-7&#34;&gt;&lt;a id=&#34;__codelineno-5-7&#34; name=&#34;__codelineno-5-7&#34; href=&#34;#__codelineno-5-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mmioAXI4Node&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4SlaveNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-8&#34;&gt;&lt;a id=&#34;__codelineno-5-8&#34; name=&#34;__codelineno-5-8&#34; href=&#34;#__codelineno-5-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mmioPortParamsOpt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-9&#34;&gt;&lt;a id=&#34;__codelineno-5-9&#34; name=&#34;__codelineno-5-9&#34; href=&#34;#__codelineno-5-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4SlavePortParameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-10&#34;&gt;&lt;a id=&#34;__codelineno-5-10&#34; name=&#34;__codelineno-5-10&#34; href=&#34;#__codelineno-5-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slaves&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Seq&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4SlaveParameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-11&#34;&gt;&lt;a id=&#34;__codelineno-5-11&#34; name=&#34;__codelineno-5-11&#34; href=&#34;#__codelineno-5-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;address&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AddressSet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;misaligned&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;base&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-12&#34;&gt;&lt;a id=&#34;__codelineno-5-12&#34; name=&#34;__codelineno-5-12&#34; href=&#34;#__codelineno-5-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resources&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;device&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ranges&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-13&#34;&gt;&lt;a id=&#34;__codelineno-5-13&#34; name=&#34;__codelineno-5-13&#34; href=&#34;#__codelineno-5-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;executable&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;executable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-14&#34;&gt;&lt;a id=&#34;__codelineno-5-14&#34; name=&#34;__codelineno-5-14&#34; href=&#34;#__codelineno-5-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;supportsWrite&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TransferSizes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;maxXferBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-15&#34;&gt;&lt;a id=&#34;__codelineno-5-15&#34; name=&#34;__codelineno-5-15&#34; href=&#34;#__codelineno-5-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;supportsRead&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TransferSizes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;maxXferBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-16&#34;&gt;&lt;a id=&#34;__codelineno-5-16&#34; name=&#34;__codelineno-5-16&#34; href=&#34;#__codelineno-5-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beatBytes&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beatBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;toSeq&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-17&#34;&gt;&lt;a id=&#34;__codelineno-5-17&#34; name=&#34;__codelineno-5-17&#34; href=&#34;#__codelineno-5-17&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-18&#34;&gt;&lt;a id=&#34;__codelineno-5-18&#34; name=&#34;__codelineno-5-18&#34; href=&#34;#__codelineno-5-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// in BaseSubsystem.scala:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-19&#34;&gt;&lt;a id=&#34;__codelineno-5-19&#34; name=&#34;__codelineno-5-19&#34; href=&#34;#__codelineno-5-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// def viewpointBus: TLBusWrapper = tlBusWrapperLocationMap(p(TLManagerViewpointLocated(location)))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-20&#34;&gt;&lt;a id=&#34;__codelineno-5-20&#34; name=&#34;__codelineno-5-20&#34; href=&#34;#__codelineno-5-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// case class TLManagerViewpointLocated(where: HierarchicalLocation) extends Field[Location[TLBusWrapper]](SBUS)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-21&#34;&gt;&lt;a id=&#34;__codelineno-5-21&#34; name=&#34;__codelineno-5-21&#34; href=&#34;#__codelineno-5-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// so viewpointBus points to sbus by default&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-22&#34;&gt;&lt;a id=&#34;__codelineno-5-22&#34; name=&#34;__codelineno-5-22&#34; href=&#34;#__codelineno-5-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mmioPortParamsOpt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-23&#34;&gt;&lt;a id=&#34;__codelineno-5-23&#34; name=&#34;__codelineno-5-23&#34; href=&#34;#__codelineno-5-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;viewpointBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coupleTo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;s&amp;quot;port_named_&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;portName&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-24&#34;&gt;&lt;a id=&#34;__codelineno-5-24&#34; name=&#34;__codelineno-5-24&#34; href=&#34;#__codelineno-5-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mmioAXI4Node&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-25&#34;&gt;&lt;a id=&#34;__codelineno-5-25&#34; name=&#34;__codelineno-5-25&#34; href=&#34;#__codelineno-5-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4Buffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-26&#34;&gt;&lt;a id=&#34;__codelineno-5-26&#34; name=&#34;__codelineno-5-26&#34; href=&#34;#__codelineno-5-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4UserYanker&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-27&#34;&gt;&lt;a id=&#34;__codelineno-5-27&#34; name=&#34;__codelineno-5-27&#34; href=&#34;#__codelineno-5-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4Deinterleaver&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;viewpointBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;blockBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-28&#34;&gt;&lt;a id=&#34;__codelineno-5-28&#34; name=&#34;__codelineno-5-28&#34; href=&#34;#__codelineno-5-28&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4IdIndexer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idBits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-29&#34;&gt;&lt;a id=&#34;__codelineno-5-29&#34; name=&#34;__codelineno-5-29&#34; href=&#34;#__codelineno-5-29&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLToAXI4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-30&#34;&gt;&lt;a id=&#34;__codelineno-5-30&#34; name=&#34;__codelineno-5-30&#34; href=&#34;#__codelineno-5-30&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLWidthWidget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;viewpointBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beatBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-31&#34;&gt;&lt;a id=&#34;__codelineno-5-31&#34; name=&#34;__codelineno-5-31&#34; href=&#34;#__codelineno-5-31&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-32&#34;&gt;&lt;a id=&#34;__codelineno-5-32&#34; name=&#34;__codelineno-5-32&#34; href=&#34;#__codelineno-5-32&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-33&#34;&gt;&lt;a id=&#34;__codelineno-5-33&#34; name=&#34;__codelineno-5-33&#34; href=&#34;#__codelineno-5-33&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-34&#34;&gt;&lt;a id=&#34;__codelineno-5-34&#34; name=&#34;__codelineno-5-34&#34; href=&#34;#__codelineno-5-34&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-35&#34;&gt;&lt;a id=&#34;__codelineno-5-35&#34; name=&#34;__codelineno-5-35&#34; href=&#34;#__codelineno-5-35&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mmio_axi4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;InModuleBody&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mmioAXI4Node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;makeIOs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-5-36&#34;&gt;&lt;a id=&#34;__codelineno-5-36&#34; name=&#34;__codelineno-5-36&#34; href=&#34;#__codelineno-5-36&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;类似地，为了让 Rocket Chip 可以访问外部的 AXI Memory，在 mbus 下面添加了 tl 到 axi 的一条路径：&lt;/p&gt; &lt;div class=&#34;language-scala highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-6-1&#34;&gt;&lt;a id=&#34;__codelineno-6-1&#34; name=&#34;__codelineno-6-1&#34; href=&#34;#__codelineno-6-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cm&#34;&gt;/** Adds a port to the system intended to master an AXI4 DRAM controller. */&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-2&#34;&gt;&lt;a id=&#34;__codelineno-6-2&#34; name=&#34;__codelineno-6-2&#34; href=&#34;#__codelineno-6-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;trait&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CanHaveMasterAXI4MemPort&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BaseSubsystem&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-3&#34;&gt;&lt;a id=&#34;__codelineno-6-3&#34; name=&#34;__codelineno-6-3&#34; href=&#34;#__codelineno-6-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memPortParamsOpt&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ExtMem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-4&#34;&gt;&lt;a id=&#34;__codelineno-6-4&#34; name=&#34;__codelineno-6-4&#34; href=&#34;#__codelineno-6-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;portName&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;axi4&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-5&#34;&gt;&lt;a id=&#34;__codelineno-6-5&#34; name=&#34;__codelineno-6-5&#34; href=&#34;#__codelineno-6-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;device&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;MemoryDevice&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-6&#34;&gt;&lt;a id=&#34;__codelineno-6-6&#34; name=&#34;__codelineno-6-6&#34; href=&#34;#__codelineno-6-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idBits&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memPortParamsOpt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;master&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idBits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getOrElse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-7&#34;&gt;&lt;a id=&#34;__codelineno-6-7&#34; name=&#34;__codelineno-6-7&#34; href=&#34;#__codelineno-6-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mbus&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlBusWrapperLocationMap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;MBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getOrElse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;viewpointBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-8&#34;&gt;&lt;a id=&#34;__codelineno-6-8&#34; name=&#34;__codelineno-6-8&#34; href=&#34;#__codelineno-6-8&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-9&#34;&gt;&lt;a id=&#34;__codelineno-6-9&#34; name=&#34;__codelineno-6-9&#34; href=&#34;#__codelineno-6-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memAXI4Node&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4SlaveNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memPortParamsOpt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;MemoryPortParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memPortParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nMemoryChannels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-10&#34;&gt;&lt;a id=&#34;__codelineno-6-10&#34; name=&#34;__codelineno-6-10&#34; href=&#34;#__codelineno-6-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Seq&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tabulate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nMemoryChannels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;channel&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-11&#34;&gt;&lt;a id=&#34;__codelineno-6-11&#34; name=&#34;__codelineno-6-11&#34; href=&#34;#__codelineno-6-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;base&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AddressSet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;misaligned&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memPortParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;base&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memPortParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-12&#34;&gt;&lt;a id=&#34;__codelineno-6-12&#34; name=&#34;__codelineno-6-12&#34; href=&#34;#__codelineno-6-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AddressSet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;channel&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;blockBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;~&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nMemoryChannels&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;blockBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-13&#34;&gt;&lt;a id=&#34;__codelineno-6-13&#34; name=&#34;__codelineno-6-13&#34; href=&#34;#__codelineno-6-13&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-14&#34;&gt;&lt;a id=&#34;__codelineno-6-14&#34; name=&#34;__codelineno-6-14&#34; href=&#34;#__codelineno-6-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4SlavePortParameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-15&#34;&gt;&lt;a id=&#34;__codelineno-6-15&#34; name=&#34;__codelineno-6-15&#34; href=&#34;#__codelineno-6-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slaves&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Seq&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4SlaveParameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-16&#34;&gt;&lt;a id=&#34;__codelineno-6-16&#34; name=&#34;__codelineno-6-16&#34; href=&#34;#__codelineno-6-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;address&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;base&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;flatMap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;intersect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-17&#34;&gt;&lt;a id=&#34;__codelineno-6-17&#34; name=&#34;__codelineno-6-17&#34; href=&#34;#__codelineno-6-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resources&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;device&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-18&#34;&gt;&lt;a id=&#34;__codelineno-6-18&#34; name=&#34;__codelineno-6-18&#34; href=&#34;#__codelineno-6-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;regionType&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;RegionType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;UNCACHED&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// cacheable&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-19&#34;&gt;&lt;a id=&#34;__codelineno-6-19&#34; name=&#34;__codelineno-6-19&#34; href=&#34;#__codelineno-6-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;executable&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-20&#34;&gt;&lt;a id=&#34;__codelineno-6-20&#34; name=&#34;__codelineno-6-20&#34; href=&#34;#__codelineno-6-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;supportsWrite&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TransferSizes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;blockBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-21&#34;&gt;&lt;a id=&#34;__codelineno-6-21&#34; name=&#34;__codelineno-6-21&#34; href=&#34;#__codelineno-6-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;supportsRead&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TransferSizes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;blockBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-22&#34;&gt;&lt;a id=&#34;__codelineno-6-22&#34; name=&#34;__codelineno-6-22&#34; href=&#34;#__codelineno-6-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;interleavedId&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// slave does not interleave read responses&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-23&#34;&gt;&lt;a id=&#34;__codelineno-6-23&#34; name=&#34;__codelineno-6-23&#34; href=&#34;#__codelineno-6-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beatBytes&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memPortParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beatBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-24&#34;&gt;&lt;a id=&#34;__codelineno-6-24&#34; name=&#34;__codelineno-6-24&#34; href=&#34;#__codelineno-6-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-25&#34;&gt;&lt;a id=&#34;__codelineno-6-25&#34; name=&#34;__codelineno-6-25&#34; href=&#34;#__codelineno-6-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;toList&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;flatten&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-26&#34;&gt;&lt;a id=&#34;__codelineno-6-26&#34; name=&#34;__codelineno-6-26&#34; href=&#34;#__codelineno-6-26&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-27&#34;&gt;&lt;a id=&#34;__codelineno-6-27&#34; name=&#34;__codelineno-6-27&#34; href=&#34;#__codelineno-6-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;until&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memAXI4Node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;portParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-28&#34;&gt;&lt;a id=&#34;__codelineno-6-28&#34; name=&#34;__codelineno-6-28&#34; href=&#34;#__codelineno-6-28&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mem_bypass_xbar&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mbus&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLXbar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-29&#34;&gt;&lt;a id=&#34;__codelineno-6-29&#34; name=&#34;__codelineno-6-29&#34; href=&#34;#__codelineno-6-29&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-30&#34;&gt;&lt;a id=&#34;__codelineno-6-30&#34; name=&#34;__codelineno-6-30&#34; href=&#34;#__codelineno-6-30&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Create an incoherent alias for the AXI4 memory&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-31&#34;&gt;&lt;a id=&#34;__codelineno-6-31&#34; name=&#34;__codelineno-6-31&#34; href=&#34;#__codelineno-6-31&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memPortParamsOpt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;foreach&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memPortParams&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-32&#34;&gt;&lt;a id=&#34;__codelineno-6-32&#34; name=&#34;__codelineno-6-32&#34; href=&#34;#__codelineno-6-32&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memPortParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;incohBase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;foreach&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;incohBase&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-33&#34;&gt;&lt;a id=&#34;__codelineno-6-33&#34; name=&#34;__codelineno-6-33&#34; href=&#34;#__codelineno-6-33&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cohRegion&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AddressSet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;incohBase&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-34&#34;&gt;&lt;a id=&#34;__codelineno-6-34&#34; name=&#34;__codelineno-6-34&#34; href=&#34;#__codelineno-6-34&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;incohRegion&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AddressSet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;incohBase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;incohBase&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-35&#34;&gt;&lt;a id=&#34;__codelineno-6-35&#34; name=&#34;__codelineno-6-35&#34; href=&#34;#__codelineno-6-35&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replicator&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlBusWrapperLocationMap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLManagerViewpointLocated&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;location&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-36&#34;&gt;&lt;a id=&#34;__codelineno-6-36&#34; name=&#34;__codelineno-6-36&#34; href=&#34;#__codelineno-6-36&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replicator&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;LazyModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;RegionReplicator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ReplicatedRegion&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cohRegion&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cohRegion&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;widen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;incohBase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-37&#34;&gt;&lt;a id=&#34;__codelineno-6-37&#34; name=&#34;__codelineno-6-37&#34; href=&#34;#__codelineno-6-37&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prefixSource&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BundleBridgeSource&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;UInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;](()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;UInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;W&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-38&#34;&gt;&lt;a id=&#34;__codelineno-6-38&#34; name=&#34;__codelineno-6-38&#34; href=&#34;#__codelineno-6-38&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replicator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prefix&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prefixSource&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-39&#34;&gt;&lt;a id=&#34;__codelineno-6-39&#34; name=&#34;__codelineno-6-39&#34; href=&#34;#__codelineno-6-39&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// prefix is unused for TL uncached, so this is ok&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-40&#34;&gt;&lt;a id=&#34;__codelineno-6-40&#34; name=&#34;__codelineno-6-40&#34; href=&#34;#__codelineno-6-40&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;InModuleBody&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prefixSource&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bundle&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;W&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-41&#34;&gt;&lt;a id=&#34;__codelineno-6-41&#34; name=&#34;__codelineno-6-41&#34; href=&#34;#__codelineno-6-41&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replicator&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-42&#34;&gt;&lt;a id=&#34;__codelineno-6-42&#34; name=&#34;__codelineno-6-42&#34; href=&#34;#__codelineno-6-42&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-43&#34;&gt;&lt;a id=&#34;__codelineno-6-43&#34; name=&#34;__codelineno-6-43&#34; href=&#34;#__codelineno-6-43&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;viewpointBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coupleTo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;s&amp;quot;memory_controller_bypass_port_named_&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;portName&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-44&#34;&gt;&lt;a id=&#34;__codelineno-6-44&#34; name=&#34;__codelineno-6-44&#34; href=&#34;#__codelineno-6-44&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossIn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mem_bypass_xbar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ValName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;bus_xing&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SbusToMbusXTypeKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-45&#34;&gt;&lt;a id=&#34;__codelineno-6-45&#34; name=&#34;__codelineno-6-45&#34; href=&#34;#__codelineno-6-45&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLWidthWidget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;viewpointBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beatBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-46&#34;&gt;&lt;a id=&#34;__codelineno-6-46&#34; name=&#34;__codelineno-6-46&#34; href=&#34;#__codelineno-6-46&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replicator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-47&#34;&gt;&lt;a id=&#34;__codelineno-6-47&#34; name=&#34;__codelineno-6-47&#34; href=&#34;#__codelineno-6-47&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLFilter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLFilter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mSubtract&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cohRegion&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-48&#34;&gt;&lt;a id=&#34;__codelineno-6-48&#34; name=&#34;__codelineno-6-48&#34; href=&#34;#__codelineno-6-48&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLFilter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLFilter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mResourceRemover&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-49&#34;&gt;&lt;a id=&#34;__codelineno-6-49&#34; name=&#34;__codelineno-6-49&#34; href=&#34;#__codelineno-6-49&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-50&#34;&gt;&lt;a id=&#34;__codelineno-6-50&#34; name=&#34;__codelineno-6-50&#34; href=&#34;#__codelineno-6-50&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-51&#34;&gt;&lt;a id=&#34;__codelineno-6-51&#34; name=&#34;__codelineno-6-51&#34; href=&#34;#__codelineno-6-51&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-52&#34;&gt;&lt;a id=&#34;__codelineno-6-52&#34; name=&#34;__codelineno-6-52&#34; href=&#34;#__codelineno-6-52&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-53&#34;&gt;&lt;a id=&#34;__codelineno-6-53&#34; name=&#34;__codelineno-6-53&#34; href=&#34;#__codelineno-6-53&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-54&#34;&gt;&lt;a id=&#34;__codelineno-6-54&#34; name=&#34;__codelineno-6-54&#34; href=&#34;#__codelineno-6-54&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-55&#34;&gt;&lt;a id=&#34;__codelineno-6-55&#34; name=&#34;__codelineno-6-55&#34; href=&#34;#__codelineno-6-55&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coupleTo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;s&amp;quot;memory_controller_port_named_&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;portName&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-56&#34;&gt;&lt;a id=&#34;__codelineno-6-56&#34; name=&#34;__codelineno-6-56&#34; href=&#34;#__codelineno-6-56&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memAXI4Node&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-57&#34;&gt;&lt;a id=&#34;__codelineno-6-57&#34; name=&#34;__codelineno-6-57&#34; href=&#34;#__codelineno-6-57&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4UserYanker&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-58&#34;&gt;&lt;a id=&#34;__codelineno-6-58&#34; name=&#34;__codelineno-6-58&#34; href=&#34;#__codelineno-6-58&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4IdIndexer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idBits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-59&#34;&gt;&lt;a id=&#34;__codelineno-6-59&#34; name=&#34;__codelineno-6-59&#34; href=&#34;#__codelineno-6-59&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLToAXI4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-60&#34;&gt;&lt;a id=&#34;__codelineno-6-60&#34; name=&#34;__codelineno-6-60&#34; href=&#34;#__codelineno-6-60&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLWidthWidget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beatBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-61&#34;&gt;&lt;a id=&#34;__codelineno-6-61&#34; name=&#34;__codelineno-6-61&#34; href=&#34;#__codelineno-6-61&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mem_bypass_xbar&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-62&#34;&gt;&lt;a id=&#34;__codelineno-6-62&#34; name=&#34;__codelineno-6-62&#34; href=&#34;#__codelineno-6-62&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-63&#34;&gt;&lt;a id=&#34;__codelineno-6-63&#34; name=&#34;__codelineno-6-63&#34; href=&#34;#__codelineno-6-63&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-64&#34;&gt;&lt;a id=&#34;__codelineno-6-64&#34; name=&#34;__codelineno-6-64&#34; href=&#34;#__codelineno-6-64&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-65&#34;&gt;&lt;a id=&#34;__codelineno-6-65&#34; name=&#34;__codelineno-6-65&#34; href=&#34;#__codelineno-6-65&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-66&#34;&gt;&lt;a id=&#34;__codelineno-6-66&#34; name=&#34;__codelineno-6-66&#34; href=&#34;#__codelineno-6-66&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-67&#34;&gt;&lt;a id=&#34;__codelineno-6-67&#34; name=&#34;__codelineno-6-67&#34; href=&#34;#__codelineno-6-67&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mem_axi4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;InModuleBody&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memAXI4Node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;makeIOs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-6-68&#34;&gt;&lt;a id=&#34;__codelineno-6-68&#34; name=&#34;__codelineno-6-68&#34; href=&#34;#__codelineno-6-68&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;类似地，为了让外部的 AXI Master 可以访问一致的内存，在 fbus 上面添加了从 axi 到 tl 的一条路径，而 fbus 是连到 sbus 上的：&lt;/p&gt; &lt;div class=&#34;language-scala highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-7-1&#34;&gt;&lt;a id=&#34;__codelineno-7-1&#34; name=&#34;__codelineno-7-1&#34; href=&#34;#__codelineno-7-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;cm&#34;&gt;/** Adds an AXI4 port to the system intended to be a slave on an MMIO device bus */&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-2&#34;&gt;&lt;a id=&#34;__codelineno-7-2&#34; name=&#34;__codelineno-7-2&#34; href=&#34;#__codelineno-7-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;trait&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CanHaveSlaveAXI4Port&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BaseSubsystem&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-3&#34;&gt;&lt;a id=&#34;__codelineno-7-3&#34; name=&#34;__codelineno-7-3&#34; href=&#34;#__codelineno-7-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slavePortParamsOpt&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ExtIn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-4&#34;&gt;&lt;a id=&#34;__codelineno-7-4&#34; name=&#34;__codelineno-7-4&#34; href=&#34;#__codelineno-7-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;portName&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;slave_port_axi4&amp;quot;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-5&#34;&gt;&lt;a id=&#34;__codelineno-7-5&#34; name=&#34;__codelineno-7-5&#34; href=&#34;#__codelineno-7-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fifoBits&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-6&#34;&gt;&lt;a id=&#34;__codelineno-7-6&#34; name=&#34;__codelineno-7-6&#34; href=&#34;#__codelineno-7-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fbus&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlBusWrapperLocationMap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;FBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getOrElse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;viewpointBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-7&#34;&gt;&lt;a id=&#34;__codelineno-7-7&#34; name=&#34;__codelineno-7-7&#34; href=&#34;#__codelineno-7-7&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-8&#34;&gt;&lt;a id=&#34;__codelineno-7-8&#34; name=&#34;__codelineno-7-8&#34; href=&#34;#__codelineno-7-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;l2FrontendAXI4Node&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4MasterNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-9&#34;&gt;&lt;a id=&#34;__codelineno-7-9&#34; name=&#34;__codelineno-7-9&#34; href=&#34;#__codelineno-7-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slavePortParamsOpt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-10&#34;&gt;&lt;a id=&#34;__codelineno-7-10&#34; name=&#34;__codelineno-7-10&#34; href=&#34;#__codelineno-7-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4MasterPortParameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-11&#34;&gt;&lt;a id=&#34;__codelineno-7-11&#34; name=&#34;__codelineno-7-11&#34; href=&#34;#__codelineno-7-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;masters&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Seq&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4MasterParameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-12&#34;&gt;&lt;a id=&#34;__codelineno-7-12&#34; name=&#34;__codelineno-7-12&#34; href=&#34;#__codelineno-7-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;portName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kebab&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-13&#34;&gt;&lt;a id=&#34;__codelineno-7-13&#34; name=&#34;__codelineno-7-13&#34; href=&#34;#__codelineno-7-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;IdRange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;idBits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))))).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;toSeq&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-14&#34;&gt;&lt;a id=&#34;__codelineno-7-14&#34; name=&#34;__codelineno-7-14&#34; href=&#34;#__codelineno-7-14&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-15&#34;&gt;&lt;a id=&#34;__codelineno-7-15&#34; name=&#34;__codelineno-7-15&#34; href=&#34;#__codelineno-7-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slavePortParamsOpt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-16&#34;&gt;&lt;a id=&#34;__codelineno-7-16&#34; name=&#34;__codelineno-7-16&#34; href=&#34;#__codelineno-7-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coupleFrom&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;s&amp;quot;port_named_&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;portName&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-17&#34;&gt;&lt;a id=&#34;__codelineno-7-17&#34; name=&#34;__codelineno-7-17&#34; href=&#34;#__codelineno-7-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-18&#34;&gt;&lt;a id=&#34;__codelineno-7-18&#34; name=&#34;__codelineno-7-18&#34; href=&#34;#__codelineno-7-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BufferParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-19&#34;&gt;&lt;a id=&#34;__codelineno-7-19&#34; name=&#34;__codelineno-7-19&#34; href=&#34;#__codelineno-7-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLFIFOFixer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLFIFOFixer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-20&#34;&gt;&lt;a id=&#34;__codelineno-7-20&#34; name=&#34;__codelineno-7-20&#34; href=&#34;#__codelineno-7-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLWidthWidget&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beatBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-21&#34;&gt;&lt;a id=&#34;__codelineno-7-21&#34; name=&#34;__codelineno-7-21&#34; href=&#34;#__codelineno-7-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4ToTL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-22&#34;&gt;&lt;a id=&#34;__codelineno-7-22&#34; name=&#34;__codelineno-7-22&#34; href=&#34;#__codelineno-7-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4UserYanker&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sourceBits&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fifoBits&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-23&#34;&gt;&lt;a id=&#34;__codelineno-7-23&#34; name=&#34;__codelineno-7-23&#34; href=&#34;#__codelineno-7-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4Fragmenter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-24&#34;&gt;&lt;a id=&#34;__codelineno-7-24&#34; name=&#34;__codelineno-7-24&#34; href=&#34;#__codelineno-7-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;AXI4IdIndexer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fifoBits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-25&#34;&gt;&lt;a id=&#34;__codelineno-7-25&#34; name=&#34;__codelineno-7-25&#34; href=&#34;#__codelineno-7-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;l2FrontendAXI4Node&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-26&#34;&gt;&lt;a id=&#34;__codelineno-7-26&#34; name=&#34;__codelineno-7-26&#34; href=&#34;#__codelineno-7-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-27&#34;&gt;&lt;a id=&#34;__codelineno-7-27&#34; name=&#34;__codelineno-7-27&#34; href=&#34;#__codelineno-7-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-28&#34;&gt;&lt;a id=&#34;__codelineno-7-28&#34; name=&#34;__codelineno-7-28&#34; href=&#34;#__codelineno-7-28&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-29&#34;&gt;&lt;a id=&#34;__codelineno-7-29&#34; name=&#34;__codelineno-7-29&#34; href=&#34;#__codelineno-7-29&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;l2_frontend_bus_axi4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;InModuleBody&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;l2FrontendAXI4Node&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;makeIOs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-30&#34;&gt;&lt;a id=&#34;__codelineno-7-30&#34; name=&#34;__codelineno-7-30&#34; href=&#34;#__codelineno-7-30&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-31&#34;&gt;&lt;a id=&#34;__codelineno-7-31&#34; name=&#34;__codelineno-7-31&#34; href=&#34;#__codelineno-7-31&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-32&#34;&gt;&lt;a id=&#34;__codelineno-7-32&#34; name=&#34;__codelineno-7-32&#34; href=&#34;#__codelineno-7-32&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HierarchicalBusTopologyParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-33&#34;&gt;&lt;a id=&#34;__codelineno-7-33&#34; name=&#34;__codelineno-7-33&#34; href=&#34;#__codelineno-7-33&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;PeripheryBusParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-34&#34;&gt;&lt;a id=&#34;__codelineno-7-34&#34; name=&#34;__codelineno-7-34&#34; href=&#34;#__codelineno-7-34&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;FrontBusParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-35&#34;&gt;&lt;a id=&#34;__codelineno-7-35&#34; name=&#34;__codelineno-7-35&#34; href=&#34;#__codelineno-7-35&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;PeripheryBusParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-36&#34;&gt;&lt;a id=&#34;__codelineno-7-36&#34; name=&#34;__codelineno-7-36&#34; href=&#34;#__codelineno-7-36&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xTypes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SubsystemCrossingParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-37&#34;&gt;&lt;a id=&#34;__codelineno-7-37&#34; name=&#34;__codelineno-7-37&#34; href=&#34;#__codelineno-7-37&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;driveClocksFromSBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Boolean&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-38&#34;&gt;&lt;a id=&#34;__codelineno-7-38&#34; name=&#34;__codelineno-7-38&#34; href=&#34;#__codelineno-7-38&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;extends&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperTopology&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-39&#34;&gt;&lt;a id=&#34;__codelineno-7-39&#34; name=&#34;__codelineno-7-39&#34; href=&#34;#__codelineno-7-39&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;instantiations&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-40&#34;&gt;&lt;a id=&#34;__codelineno-7-40&#34; name=&#34;__codelineno-7-40&#34; href=&#34;#__codelineno-7-40&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;PBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-41&#34;&gt;&lt;a id=&#34;__codelineno-7-41&#34; name=&#34;__codelineno-7-41&#34; href=&#34;#__codelineno-7-41&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;FBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-42&#34;&gt;&lt;a id=&#34;__codelineno-7-42&#34; name=&#34;__codelineno-7-42&#34; href=&#34;#__codelineno-7-42&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-43&#34;&gt;&lt;a id=&#34;__codelineno-7-43&#34; name=&#34;__codelineno-7-43&#34; href=&#34;#__codelineno-7-43&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;connections&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-44&#34;&gt;&lt;a id=&#34;__codelineno-7-44&#34; name=&#34;__codelineno-7-44&#34; href=&#34;#__codelineno-7-44&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// (master, slave, params)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-45&#34;&gt;&lt;a id=&#34;__codelineno-7-45&#34; name=&#34;__codelineno-7-45&#34; href=&#34;#__codelineno-7-45&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// cbus := sbus&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-46&#34;&gt;&lt;a id=&#34;__codelineno-7-46&#34; name=&#34;__codelineno-7-46&#34; href=&#34;#__codelineno-7-46&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperConnection&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossTo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xTypes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sbusToCbusXType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;driveClocksFromSBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-47&#34;&gt;&lt;a id=&#34;__codelineno-7-47&#34; name=&#34;__codelineno-7-47&#34; href=&#34;#__codelineno-7-47&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// pbus := cbus&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-48&#34;&gt;&lt;a id=&#34;__codelineno-7-48&#34; name=&#34;__codelineno-7-48&#34; href=&#34;#__codelineno-7-48&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;PBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperConnection&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossTo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xTypes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cbusToPbusXType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;driveClocksFromSBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-49&#34;&gt;&lt;a id=&#34;__codelineno-7-49&#34; name=&#34;__codelineno-7-49&#34; href=&#34;#__codelineno-7-49&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// sbus := fbus&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-50&#34;&gt;&lt;a id=&#34;__codelineno-7-50&#34; name=&#34;__codelineno-7-50&#34; href=&#34;#__codelineno-7-50&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;FBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperConnection&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossFrom&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xTypes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fbusToSbusXType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;driveClocksFromSBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-7-51&#34;&gt;&lt;a id=&#34;__codelineno-7-51&#34; name=&#34;__codelineno-7-51&#34; href=&#34;#__codelineno-7-51&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;上一段代码中，在 sbus 的下游挂载了 cbus，在 cbus 下游挂载了 pbus；那么 debug/plic/clint 等设备都是挂载在 cbus 下的：&lt;/p&gt; &lt;div class=&#34;language-scala highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-8-1&#34;&gt;&lt;a id=&#34;__codelineno-8-1&#34; name=&#34;__codelineno-8-1&#34; href=&#34;#__codelineno-8-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// in HasPeripheryDebug of Periphery.scala&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-2&#34;&gt;&lt;a id=&#34;__codelineno-8-2&#34; name=&#34;__codelineno-8-2&#34; href=&#34;#__codelineno-8-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// default to cbus&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-3&#34;&gt;&lt;a id=&#34;__codelineno-8-3&#34; name=&#34;__codelineno-8-3&#34; href=&#34;#__codelineno-8-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;lazy&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;locateTLBusWrapper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ExportDebug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slaveWhere&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-4&#34;&gt;&lt;a id=&#34;__codelineno-8-4&#34; name=&#34;__codelineno-8-4&#34; href=&#34;#__codelineno-8-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlDM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;LazyModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLDebugModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beatBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-5&#34;&gt;&lt;a id=&#34;__codelineno-8-5&#34; name=&#34;__codelineno-8-5&#34; href=&#34;#__codelineno-8-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;tlDM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coupleTo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;debug&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;){&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLFragmenter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beatBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;blockBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nameSuffix&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;Debug&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-6&#34;&gt;&lt;a id=&#34;__codelineno-8-6&#34; name=&#34;__codelineno-8-6&#34; href=&#34;#__codelineno-8-6&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-7&#34;&gt;&lt;a id=&#34;__codelineno-8-7&#34; name=&#34;__codelineno-8-7&#34; href=&#34;#__codelineno-8-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// in CanHavePeripheryCLINT of CLINT.scala&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-8&#34;&gt;&lt;a id=&#34;__codelineno-8-8&#34; name=&#34;__codelineno-8-8&#34; href=&#34;#__codelineno-8-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// default to cbus&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-9&#34;&gt;&lt;a id=&#34;__codelineno-8-9&#34; name=&#34;__codelineno-8-9&#34; href=&#34;#__codelineno-8-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;locateTLBusWrapper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CLINTAttachKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slaveWhere&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-10&#34;&gt;&lt;a id=&#34;__codelineno-8-10&#34; name=&#34;__codelineno-8-10&#34; href=&#34;#__codelineno-8-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clintDomainWrapper&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;generateSynchronousDomain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;CLINT&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;suggestName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;clint_domain&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-11&#34;&gt;&lt;a id=&#34;__codelineno-8-11&#34; name=&#34;__codelineno-8-11&#34; href=&#34;#__codelineno-8-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clint&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clintDomainWrapper&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;LazyModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CLINT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beatBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-12&#34;&gt;&lt;a id=&#34;__codelineno-8-12&#34; name=&#34;__codelineno-8-12&#34; href=&#34;#__codelineno-8-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;clintDomainWrapper&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coupleTo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;clint&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLFragmenter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;CLINT&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-13&#34;&gt;&lt;a id=&#34;__codelineno-8-13&#34; name=&#34;__codelineno-8-13&#34; href=&#34;#__codelineno-8-13&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-14&#34;&gt;&lt;a id=&#34;__codelineno-8-14&#34; name=&#34;__codelineno-8-14&#34; href=&#34;#__codelineno-8-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// in CanHavePeripheryPLIC of Plic.scala&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-15&#34;&gt;&lt;a id=&#34;__codelineno-8-15&#34; name=&#34;__codelineno-8-15&#34; href=&#34;#__codelineno-8-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// default to cbus&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-16&#34;&gt;&lt;a id=&#34;__codelineno-8-16&#34; name=&#34;__codelineno-8-16&#34; href=&#34;#__codelineno-8-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;locateTLBusWrapper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;PLICAttachKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;slaveWhere&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-17&#34;&gt;&lt;a id=&#34;__codelineno-8-17&#34; name=&#34;__codelineno-8-17&#34; href=&#34;#__codelineno-8-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plicDomainWrapper&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;generateSynchronousDomain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;PLIC&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;suggestName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;plic_domain&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-18&#34;&gt;&lt;a id=&#34;__codelineno-8-18&#34; name=&#34;__codelineno-8-18&#34; href=&#34;#__codelineno-8-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plic&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plicDomainWrapper&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;LazyModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLPLIC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;beatBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-19&#34;&gt;&lt;a id=&#34;__codelineno-8-19&#34; name=&#34;__codelineno-8-19&#34; href=&#34;#__codelineno-8-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;plicDomainWrapper&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coupleTo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;plic&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLFragmenter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tlbus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;PLIC&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-8-20&#34;&gt;&lt;a id=&#34;__codelineno-8-20&#34; name=&#34;__codelineno-8-20&#34; href=&#34;#__codelineno-8-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;n&#34;&gt;plicDomainWrapper&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;intnode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ibus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;toPLIC&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;至此就把前面提到的 Rocket Chip 的总线结构在源码中的对应关系都找到了。&lt;/p&gt; &lt;p&gt;除了这一组大的总线结构，实际上调试模块内部还有一个小的总线，主要是把 RISC-V Debug 的 DMI 转化为 TileLink，然后访问内部的一些寄存器。&lt;/p&gt; &lt;h3 id=&#34;中断&#34;&gt;中断&lt;a class=&#34;headerlink&#34; href=&#34;#中断&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;除了总线，中断也是通过 Diplomacy 管理的。首先可以看到，每个 Tile 有一个中断的 SinkNode：&lt;/p&gt; &lt;div class=&#34;language-scala highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-9-1&#34;&gt;&lt;a id=&#34;__codelineno-9-1&#34; name=&#34;__codelineno-9-1&#34; href=&#34;#__codelineno-9-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// Use diplomatic interrupts to external interrupts from the subsystem into the tile&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-2&#34;&gt;&lt;a id=&#34;__codelineno-9-2&#34; name=&#34;__codelineno-9-2&#34; href=&#34;#__codelineno-9-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;trait&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SinksExternalInterrupts&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BaseTile&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-3&#34;&gt;&lt;a id=&#34;__codelineno-9-3&#34; name=&#34;__codelineno-9-3&#34; href=&#34;#__codelineno-9-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;intInwardNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;intXbar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;intnode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;IntIdentityNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ValName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;int_local&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-4&#34;&gt;&lt;a id=&#34;__codelineno-9-4&#34; name=&#34;__codelineno-9-4&#34; href=&#34;#__codelineno-9-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;protected&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;intSinkNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;IntSinkNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;IntSinkPortSimple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-5&#34;&gt;&lt;a id=&#34;__codelineno-9-5&#34; name=&#34;__codelineno-9-5&#34; href=&#34;#__codelineno-9-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;intSinkNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;intXbar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;intnode&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-6&#34;&gt;&lt;a id=&#34;__codelineno-9-6&#34; name=&#34;__codelineno-9-6&#34; href=&#34;#__codelineno-9-6&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-7&#34;&gt;&lt;a id=&#34;__codelineno-9-7&#34; name=&#34;__codelineno-9-7&#34; href=&#34;#__codelineno-9-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// go from flat diplomatic Interrupts to bundled TileInterrupts&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-8&#34;&gt;&lt;a id=&#34;__codelineno-9-8&#34; name=&#34;__codelineno-9-8&#34; href=&#34;#__codelineno-9-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;decodeCoreInterrupts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;core&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TileInterrupts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Unit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-9&#34;&gt;&lt;a id=&#34;__codelineno-9-9&#34; name=&#34;__codelineno-9-9&#34; href=&#34;#__codelineno-9-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;async_ips&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Seq&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;core&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;debug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-10&#34;&gt;&lt;a id=&#34;__codelineno-9-10&#34; name=&#34;__codelineno-9-10&#34; href=&#34;#__codelineno-9-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;periph_ips&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Seq&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-11&#34;&gt;&lt;a id=&#34;__codelineno-9-11&#34; name=&#34;__codelineno-9-11&#34; href=&#34;#__codelineno-9-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;core&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;msip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-12&#34;&gt;&lt;a id=&#34;__codelineno-9-12&#34; name=&#34;__codelineno-9-12&#34; href=&#34;#__codelineno-9-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;core&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mtip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-13&#34;&gt;&lt;a id=&#34;__codelineno-9-13&#34; name=&#34;__codelineno-9-13&#34; href=&#34;#__codelineno-9-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;core&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;meip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-14&#34;&gt;&lt;a id=&#34;__codelineno-9-14&#34; name=&#34;__codelineno-9-14&#34; href=&#34;#__codelineno-9-14&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-15&#34;&gt;&lt;a id=&#34;__codelineno-9-15&#34; name=&#34;__codelineno-9-15&#34; href=&#34;#__codelineno-9-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seip&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;core&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;isDefined&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Seq&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;core&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Nil&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-16&#34;&gt;&lt;a id=&#34;__codelineno-9-16&#34; name=&#34;__codelineno-9-16&#34; href=&#34;#__codelineno-9-16&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-17&#34;&gt;&lt;a id=&#34;__codelineno-9-17&#34; name=&#34;__codelineno-9-17&#34; href=&#34;#__codelineno-9-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;core_ips&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;core&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lip&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-18&#34;&gt;&lt;a id=&#34;__codelineno-9-18&#34; name=&#34;__codelineno-9-18&#34; href=&#34;#__codelineno-9-18&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-19&#34;&gt;&lt;a id=&#34;__codelineno-9-19&#34; name=&#34;__codelineno-9-19&#34; href=&#34;#__codelineno-9-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;interrupts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;intSinkNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-20&#34;&gt;&lt;a id=&#34;__codelineno-9-20&#34; name=&#34;__codelineno-9-20&#34; href=&#34;#__codelineno-9-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;async_ips&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;periph_ips&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seip&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;core_ips&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;zip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;interrupts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;foreach&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-21&#34;&gt;&lt;a id=&#34;__codelineno-9-21&#34; name=&#34;__codelineno-9-21&#34; href=&#34;#__codelineno-9-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-22&#34;&gt;&lt;a id=&#34;__codelineno-9-22&#34; name=&#34;__codelineno-9-22&#34; href=&#34;#__codelineno-9-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-23&#34;&gt;&lt;a id=&#34;__codelineno-9-23&#34; name=&#34;__codelineno-9-23&#34; href=&#34;#__codelineno-9-23&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-24&#34;&gt;&lt;a id=&#34;__codelineno-9-24&#34; name=&#34;__codelineno-9-24&#34; href=&#34;#__codelineno-9-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TileInterrupts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;implicit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Parameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;extends&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CoreBundle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-25&#34;&gt;&lt;a id=&#34;__codelineno-9-25&#34; name=&#34;__codelineno-9-25&#34; href=&#34;#__codelineno-9-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;debug&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-26&#34;&gt;&lt;a id=&#34;__codelineno-9-26&#34; name=&#34;__codelineno-9-26&#34; href=&#34;#__codelineno-9-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mtip&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-27&#34;&gt;&lt;a id=&#34;__codelineno-9-27&#34; name=&#34;__codelineno-9-27&#34; href=&#34;#__codelineno-9-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;msip&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-28&#34;&gt;&lt;a id=&#34;__codelineno-9-28&#34; name=&#34;__codelineno-9-28&#34; href=&#34;#__codelineno-9-28&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;meip&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-29&#34;&gt;&lt;a id=&#34;__codelineno-9-29&#34; name=&#34;__codelineno-9-29&#34; href=&#34;#__codelineno-9-29&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seip&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;usingSupervisor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;option&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-30&#34;&gt;&lt;a id=&#34;__codelineno-9-30&#34; name=&#34;__codelineno-9-30&#34; href=&#34;#__codelineno-9-30&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lip&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Vec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;coreParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nLocalInterrupts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-31&#34;&gt;&lt;a id=&#34;__codelineno-9-31&#34; name=&#34;__codelineno-9-31&#34; href=&#34;#__codelineno-9-31&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nmi&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;usingNMI&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;option&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;NMI&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resetVectorLen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-9-32&#34;&gt;&lt;a id=&#34;__codelineno-9-32&#34; name=&#34;__codelineno-9-32&#34; href=&#34;#__codelineno-9-32&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;p&gt;它通过 Diplomacy 的 intXbar 输入多路的中断，然后按照顺序，还原出对应的 debug/mtip/msip/seip 等中断信号。从前面的图中，也可以看到 intXbar 的第一个输入 debug（经过 intsink）来自 dmOuter 也就是调试模块，第二个和第三个输入 msip 和 mtip（经过 intsink_1）来自 clint（负责时钟 mtimer 和软件中断），最后的 meip 和 seip（经过 intsink_2/3）来自 plic（负责外部中断）。为了处理外部中断，从外面接了 6 位的中断信号到 plic。&lt;/p&gt; &lt;h3 id=&#34;时钟&#34;&gt;时钟&lt;a class=&#34;headerlink&#34; href=&#34;#时钟&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;最后，时钟（时钟加上复位）也是由 Diplomacy 管理的：从前面的图中，从 aggregator 进来，首先到 sbus，然后分出来多路的时钟信号：第一路到 cbus，用于 cbus 的各个外设（plic/clint 等），进一步也从 cbus 引到 pbus；第二路到各个 tile；第三路到 coh（coherence wrapper）；第四路到 fbus。默认配置下，这些时钟都是同一个信号，没有额外的处理，但是通过配置，可以把它们区分开，放到不同的时钟域，并在跨时钟域的时候，添加合适的跨时钟域的处理。&lt;/p&gt; &lt;p&gt;那么这些时钟是怎么分出来的呢：&lt;/p&gt; &lt;ol&gt; &lt;li&gt; &lt;p&gt;aggregator 把时钟暴露到 IO 上，然后内部暴露一个 allClockGroupsNode，连接到 sbus 上：&lt;/p&gt; &lt;div class=&#34;language-scala highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-10-1&#34;&gt;&lt;a id=&#34;__codelineno-10-1&#34; name=&#34;__codelineno-10-1&#34; href=&#34;#__codelineno-10-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// in BaseSubsystem.scala&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-2&#34;&gt;&lt;a id=&#34;__codelineno-10-2&#34; name=&#34;__codelineno-10-2&#34; href=&#34;#__codelineno-10-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;trait&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HasConfigurablePRCILocations&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HasPRCILocations&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-3&#34;&gt;&lt;a id=&#34;__codelineno-10-3&#34; name=&#34;__codelineno-10-3&#34; href=&#34;#__codelineno-10-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ibus&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;LazyModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;InterruptBusWrapper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-4&#34;&gt;&lt;a id=&#34;__codelineno-10-4&#34; name=&#34;__codelineno-10-4&#34; href=&#34;#__codelineno-10-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;allClockGroupsNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ClockGroupIdentityNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-5&#34;&gt;&lt;a id=&#34;__codelineno-10-5&#34; name=&#34;__codelineno-10-5&#34; href=&#34;#__codelineno-10-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;io_clocks&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SubsystemDriveClockGroupsFromIO&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-6&#34;&gt;&lt;a id=&#34;__codelineno-10-6&#34; name=&#34;__codelineno-10-6&#34; href=&#34;#__codelineno-10-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;aggregator&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ClockGroupAggregator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-7&#34;&gt;&lt;a id=&#34;__codelineno-10-7&#34; name=&#34;__codelineno-10-7&#34; href=&#34;#__codelineno-10-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ClockGroupSourceNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Seq&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ClockGroupSourceParameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-8&#34;&gt;&lt;a id=&#34;__codelineno-10-8&#34; name=&#34;__codelineno-10-8&#34; href=&#34;#__codelineno-10-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;allClockGroupsNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:*=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;aggregator&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;source&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-9&#34;&gt;&lt;a id=&#34;__codelineno-10-9&#34; name=&#34;__codelineno-10-9&#34; href=&#34;#__codelineno-10-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;InModuleBody&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-10&#34;&gt;&lt;a id=&#34;__codelineno-10-10&#34; name=&#34;__codelineno-10-10&#34; href=&#34;#__codelineno-10-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;elements&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;member&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;elements&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;flatten&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-11&#34;&gt;&lt;a id=&#34;__codelineno-10-11&#34; name=&#34;__codelineno-10-11&#34; href=&#34;#__codelineno-10-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;io&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;IO&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Flipped&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;RecordMap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;elements&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-12&#34;&gt;&lt;a id=&#34;__codelineno-10-12&#34; name=&#34;__codelineno-10-12&#34; href=&#34;#__codelineno-10-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cloneType&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-13&#34;&gt;&lt;a id=&#34;__codelineno-10-13&#34; name=&#34;__codelineno-10-13&#34; href=&#34;#__codelineno-10-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-14&#34;&gt;&lt;a id=&#34;__codelineno-10-14&#34; name=&#34;__codelineno-10-14&#34; href=&#34;#__codelineno-10-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;elements&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;foreach&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;case&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;io&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;foreach&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-15&#34;&gt;&lt;a id=&#34;__codelineno-10-15&#34; name=&#34;__codelineno-10-15&#34; href=&#34;#__codelineno-10-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;io&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-16&#34;&gt;&lt;a id=&#34;__codelineno-10-16&#34; name=&#34;__codelineno-10-16&#34; href=&#34;#__codelineno-10-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-17&#34;&gt;&lt;a id=&#34;__codelineno-10-17&#34; name=&#34;__codelineno-10-17&#34; href=&#34;#__codelineno-10-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-18&#34;&gt;&lt;a id=&#34;__codelineno-10-18&#34; name=&#34;__codelineno-10-18&#34; href=&#34;#__codelineno-10-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;None&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-19&#34;&gt;&lt;a id=&#34;__codelineno-10-19&#34; name=&#34;__codelineno-10-19&#34; href=&#34;#__codelineno-10-19&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-20&#34;&gt;&lt;a id=&#34;__codelineno-10-20&#34; name=&#34;__codelineno-10-20&#34; href=&#34;#__codelineno-10-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-21&#34;&gt;&lt;a id=&#34;__codelineno-10-21&#34; name=&#34;__codelineno-10-21&#34; href=&#34;#__codelineno-10-21&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-22&#34;&gt;&lt;a id=&#34;__codelineno-10-22&#34; name=&#34;__codelineno-10-22&#34; href=&#34;#__codelineno-10-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;abstract&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BaseSubsystem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;location&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HierarchicalLocation&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;InSubsystem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-23&#34;&gt;&lt;a id=&#34;__codelineno-10-23&#34; name=&#34;__codelineno-10-23&#34; href=&#34;#__codelineno-10-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;implicit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Parameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-24&#34;&gt;&lt;a id=&#34;__codelineno-10-24&#34; name=&#34;__codelineno-10-24&#34; href=&#34;#__codelineno-10-24&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;extends&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BareSubsystem&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-25&#34;&gt;&lt;a id=&#34;__codelineno-10-25&#34; name=&#34;__codelineno-10-25&#34; href=&#34;#__codelineno-10-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HasDTS&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-26&#34;&gt;&lt;a id=&#34;__codelineno-10-26&#34; name=&#34;__codelineno-10-26&#34; href=&#34;#__codelineno-10-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Attachable&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-27&#34;&gt;&lt;a id=&#34;__codelineno-10-27&#34; name=&#34;__codelineno-10-27&#34; href=&#34;#__codelineno-10-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HasConfigurablePRCILocations&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-28&#34;&gt;&lt;a id=&#34;__codelineno-10-28&#34; name=&#34;__codelineno-10-28&#34; href=&#34;#__codelineno-10-28&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HasConfigurableTLNetworkTopology&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-29&#34;&gt;&lt;a id=&#34;__codelineno-10-29&#34; name=&#34;__codelineno-10-29&#34; href=&#34;#__codelineno-10-29&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-30&#34;&gt;&lt;a id=&#34;__codelineno-10-30&#34; name=&#34;__codelineno-10-30&#34; href=&#34;#__codelineno-10-30&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-31&#34;&gt;&lt;a id=&#34;__codelineno-10-31&#34; name=&#34;__codelineno-10-31&#34; href=&#34;#__codelineno-10-31&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// viewpointBus points to sbus by default&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-32&#34;&gt;&lt;a id=&#34;__codelineno-10-32&#34; name=&#34;__codelineno-10-32&#34; href=&#34;#__codelineno-10-32&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;viewpointBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockGroupNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;allClockGroupsNode&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-10-33&#34;&gt;&lt;a id=&#34;__codelineno-10-33&#34; name=&#34;__codelineno-10-33&#34; href=&#34;#__codelineno-10-33&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;前面提到，通过 CoherentBusTopologyParams，实现 &lt;code&gt;mbus := coh := sbus&lt;/code&gt; 的连接，通过 HierarchicalBusTopologyParams，实现 &lt;code&gt;pbus := cbus := sbus := fbus&lt;/code&gt; 的连接，与此同时，时钟也被接上了：&lt;/p&gt; &lt;div class=&#34;language-scala highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-11-1&#34;&gt;&lt;a id=&#34;__codelineno-11-1&#34; name=&#34;__codelineno-11-1&#34; href=&#34;#__codelineno-11-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// in BusTopology.scala&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-2&#34;&gt;&lt;a id=&#34;__codelineno-11-2&#34; name=&#34;__codelineno-11-2&#34; href=&#34;#__codelineno-11-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// (master, slave, parameters)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-3&#34;&gt;&lt;a id=&#34;__codelineno-11-3&#34; name=&#34;__codelineno-11-3&#34; href=&#34;#__codelineno-11-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// from CoherentBusTopologyParams&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-4&#34;&gt;&lt;a id=&#34;__codelineno-11-4&#34; name=&#34;__codelineno-11-4&#34; href=&#34;#__codelineno-11-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// coh := sbus, use sbus&amp;#39;s clock for coh&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-5&#34;&gt;&lt;a id=&#34;__codelineno-11-5&#34; name=&#34;__codelineno-11-5&#34; href=&#34;#__codelineno-11-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;COH&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperConnection&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;driveClockFromMaster&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nodeBinding&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BIND_STAR&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)()),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-6&#34;&gt;&lt;a id=&#34;__codelineno-11-6&#34; name=&#34;__codelineno-11-6&#34; href=&#34;#__codelineno-11-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// mbus := coh, use coh&amp;#39;s clock for mbus by default&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-7&#34;&gt;&lt;a id=&#34;__codelineno-11-7&#34; name=&#34;__codelineno-11-7&#34; href=&#34;#__codelineno-11-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;COH&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;MBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperConnection&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossTo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-8&#34;&gt;&lt;a id=&#34;__codelineno-11-8&#34; name=&#34;__codelineno-11-8&#34; href=&#34;#__codelineno-11-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xType&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sbusToMbusXType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-9&#34;&gt;&lt;a id=&#34;__codelineno-11-9&#34; name=&#34;__codelineno-11-9&#34; href=&#34;#__codelineno-11-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;driveClockFromMaster&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;driveMBusClockFromSBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-10&#34;&gt;&lt;a id=&#34;__codelineno-11-10&#34; name=&#34;__codelineno-11-10&#34; href=&#34;#__codelineno-11-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nodeBinding&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;BIND_QUERY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-11&#34;&gt;&lt;a id=&#34;__codelineno-11-11&#34; name=&#34;__codelineno-11-11&#34; href=&#34;#__codelineno-11-11&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-12&#34;&gt;&lt;a id=&#34;__codelineno-11-12&#34; name=&#34;__codelineno-11-12&#34; href=&#34;#__codelineno-11-12&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// from HierarchicalBusTopologyParams&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-13&#34;&gt;&lt;a id=&#34;__codelineno-11-13&#34; name=&#34;__codelineno-11-13&#34; href=&#34;#__codelineno-11-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// cbus := sbus, use sbus&amp;#39;s clock for cbus by default&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-14&#34;&gt;&lt;a id=&#34;__codelineno-11-14&#34; name=&#34;__codelineno-11-14&#34; href=&#34;#__codelineno-11-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperConnection&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossTo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xTypes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sbusToCbusXType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;driveClocksFromSBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-15&#34;&gt;&lt;a id=&#34;__codelineno-11-15&#34; name=&#34;__codelineno-11-15&#34; href=&#34;#__codelineno-11-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// pbus := cbus, use cbus&amp;#39;s clock for pbus by default&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-16&#34;&gt;&lt;a id=&#34;__codelineno-11-16&#34; name=&#34;__codelineno-11-16&#34; href=&#34;#__codelineno-11-16&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;PBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperConnection&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossTo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xTypes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cbusToPbusXType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;driveClocksFromSBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-17&#34;&gt;&lt;a id=&#34;__codelineno-11-17&#34; name=&#34;__codelineno-11-17&#34; href=&#34;#__codelineno-11-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// sbus := fbus, use sbus&amp;#39;s clock for fbus by default&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-11-18&#34;&gt;&lt;a id=&#34;__codelineno-11-18&#34; name=&#34;__codelineno-11-18&#34; href=&#34;#__codelineno-11-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;FBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;SBUS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapperConnection&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crossFrom&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xTypes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fbusToSbusXType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;driveClocksFromSBus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;/li&gt; &lt;li&gt; &lt;p&gt;具体地，每个 bus 有一个自己的 clockGroupNode，bus 之间的 clockGroupNode 按照上面所属的方式连接，然后 bus 下面的设备再挂到 fixedClockNode 下面：&lt;/p&gt; &lt;div class=&#34;language-scala highlight&#34;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span id=&#34;__span-12-1&#34;&gt;&lt;a id=&#34;__codelineno-12-1&#34; name=&#34;__codelineno-12-1&#34; href=&#34;#__codelineno-12-1&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;abstract&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;TLBusWrapper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HasTLBusParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;busName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;String&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;implicit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Parameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-2&#34;&gt;&lt;a id=&#34;__codelineno-12-2&#34; name=&#34;__codelineno-12-2&#34; href=&#34;#__codelineno-12-2&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;extends&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ClockDomain&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-3&#34;&gt;&lt;a id=&#34;__codelineno-12-3&#34; name=&#34;__codelineno-12-3&#34; href=&#34;#__codelineno-12-3&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HasTLBusParams&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-4&#34;&gt;&lt;a id=&#34;__codelineno-12-4&#34; name=&#34;__codelineno-12-4&#34; href=&#34;#__codelineno-12-4&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;CanHaveBuiltInDevices&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-5&#34;&gt;&lt;a id=&#34;__codelineno-12-5&#34; name=&#34;__codelineno-12-5&#34; href=&#34;#__codelineno-12-5&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-6&#34;&gt;&lt;a id=&#34;__codelineno-12-6&#34; name=&#34;__codelineno-12-6&#34; href=&#34;#__codelineno-12-6&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockGroupAggregator&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;LazyModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ClockGroupAggregator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;busName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;){&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;override&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;shouldBeInlined&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;suggestName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;busName&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;_clock_groups&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-7&#34;&gt;&lt;a id=&#34;__codelineno-12-7&#34; name=&#34;__codelineno-12-7&#34; href=&#34;#__codelineno-12-7&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockGroup&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;LazyModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ClockGroup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;busName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;){&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;override&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;shouldBeInlined&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-8&#34;&gt;&lt;a id=&#34;__codelineno-12-8&#34; name=&#34;__codelineno-12-8&#34; href=&#34;#__codelineno-12-8&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockGroupNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockGroupAggregator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// other bus clock groups attach here&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-9&#34;&gt;&lt;a id=&#34;__codelineno-12-9&#34; name=&#34;__codelineno-12-9&#34; href=&#34;#__codelineno-12-9&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockGroup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-10&#34;&gt;&lt;a id=&#34;__codelineno-12-10&#34; name=&#34;__codelineno-12-10&#34; href=&#34;#__codelineno-12-10&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fixedClockNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;FixedClockBroadcast&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fixedClockOpt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// device clocks attach here&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-11&#34;&gt;&lt;a id=&#34;__codelineno-12-11&#34; name=&#34;__codelineno-12-11&#34; href=&#34;#__codelineno-12-11&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockSinkNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ClockSinkNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ClockSinkParameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;take&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fixedClockOpt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-12&#34;&gt;&lt;a id=&#34;__codelineno-12-12&#34; name=&#34;__codelineno-12-12&#34; href=&#34;#__codelineno-12-12&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-13&#34;&gt;&lt;a id=&#34;__codelineno-12-13&#34; name=&#34;__codelineno-12-13&#34; href=&#34;#__codelineno-12-13&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockGroup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockGroupAggregator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-14&#34;&gt;&lt;a id=&#34;__codelineno-12-14&#34; name=&#34;__codelineno-12-14&#34; href=&#34;#__codelineno-12-14&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fixedClockNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockGroup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;node&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// first member of group is always domain&amp;#39;s own clock&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-15&#34;&gt;&lt;a id=&#34;__codelineno-12-15&#34; name=&#34;__codelineno-12-15&#34; href=&#34;#__codelineno-12-15&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockSinkNode&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fixedClockNode&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-16&#34;&gt;&lt;a id=&#34;__codelineno-12-16&#34; name=&#34;__codelineno-12-16&#34; href=&#34;#__codelineno-12-16&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-17&#34;&gt;&lt;a id=&#34;__codelineno-12-17&#34; name=&#34;__codelineno-12-17&#34; href=&#34;#__codelineno-12-17&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;clockBundle&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockSinkNode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_1&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-18&#34;&gt;&lt;a id=&#34;__codelineno-12-18&#34; name=&#34;__codelineno-12-18&#34; href=&#34;#__codelineno-12-18&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-19&#34;&gt;&lt;a id=&#34;__codelineno-12-19&#34; name=&#34;__codelineno-12-19&#34; href=&#34;#__codelineno-12-19&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-20&#34;&gt;&lt;a id=&#34;__codelineno-12-20&#34; name=&#34;__codelineno-12-20&#34; href=&#34;#__codelineno-12-20&#34;&gt;&lt;/a&gt;&lt;span class=&#34;c1&#34;&gt;// in ClockDomain.scala&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-21&#34;&gt;&lt;a id=&#34;__codelineno-12-21&#34; name=&#34;__codelineno-12-21&#34; href=&#34;#__codelineno-12-21&#34;&gt;&lt;/a&gt;&lt;span class=&#34;k&#34;&gt;abstract&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Domain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;implicit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Parameters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;extends&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;LazyModule&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;HasDomainCrossing&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-22&#34;&gt;&lt;a id=&#34;__codelineno-12-22&#34; name=&#34;__codelineno-12-22&#34; href=&#34;#__codelineno-12-22&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-23&#34;&gt;&lt;a id=&#34;__codelineno-12-23&#34; name=&#34;__codelineno-12-23&#34; href=&#34;#__codelineno-12-23&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;clockBundle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;ClockBundle&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-24&#34;&gt;&lt;a id=&#34;__codelineno-12-24&#34; name=&#34;__codelineno-12-24&#34; href=&#34;#__codelineno-12-24&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-25&#34;&gt;&lt;a id=&#34;__codelineno-12-25&#34; name=&#34;__codelineno-12-25&#34; href=&#34;#__codelineno-12-25&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;lazy&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;module&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Impl&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-26&#34;&gt;&lt;a id=&#34;__codelineno-12-26&#34; name=&#34;__codelineno-12-26&#34; href=&#34;#__codelineno-12-26&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Impl&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;extends&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;LazyRawModuleImp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-27&#34;&gt;&lt;a id=&#34;__codelineno-12-27&#34; name=&#34;__codelineno-12-27&#34; href=&#34;#__codelineno-12-27&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;childClock&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockBundle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clock&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-28&#34;&gt;&lt;a id=&#34;__codelineno-12-28&#34; name=&#34;__codelineno-12-28&#34; href=&#34;#__codelineno-12-28&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;childReset&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockBundle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reset&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-29&#34;&gt;&lt;a id=&#34;__codelineno-12-29&#34; name=&#34;__codelineno-12-29&#34; href=&#34;#__codelineno-12-29&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;override&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;provideImplicitClockToLazyChildren&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-30&#34;&gt;&lt;a id=&#34;__codelineno-12-30&#34; name=&#34;__codelineno-12-30&#34; href=&#34;#__codelineno-12-30&#34;&gt;&lt;/a&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-31&#34;&gt;&lt;a id=&#34;__codelineno-12-31&#34; name=&#34;__codelineno-12-31&#34; href=&#34;#__codelineno-12-31&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// these are just for backwards compatibility with external devices&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-32&#34;&gt;&lt;a id=&#34;__codelineno-12-32&#34; name=&#34;__codelineno-12-32&#34; href=&#34;#__codelineno-12-32&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// that were manually wiring themselves to the domain&amp;#39;s clock/reset input:&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-33&#34;&gt;&lt;a id=&#34;__codelineno-12-33&#34; name=&#34;__codelineno-12-33&#34; href=&#34;#__codelineno-12-33&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clock&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;IO&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;chiselTypeOf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockBundle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-34&#34;&gt;&lt;a id=&#34;__codelineno-12-34&#34; name=&#34;__codelineno-12-34&#34; href=&#34;#__codelineno-12-34&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reset&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;IO&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;chiselTypeOf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockBundle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-35&#34;&gt;&lt;a id=&#34;__codelineno-12-35&#34; name=&#34;__codelineno-12-35&#34; href=&#34;#__codelineno-12-35&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clock&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockBundle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clock&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-36&#34;&gt;&lt;a id=&#34;__codelineno-12-36&#34; name=&#34;__codelineno-12-36&#34; href=&#34;#__codelineno-12-36&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reset&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clockBundle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reset&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-37&#34;&gt;&lt;a id=&#34;__codelineno-12-37&#34; name=&#34;__codelineno-12-37&#34; href=&#34;#__codelineno-12-37&#34;&gt;&lt;/a&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;span id=&#34;__span-12-38&#34;&gt;&lt;a id=&#34;__codelineno-12-38&#34; name=&#34;__codelineno-12-38&#34; href=&#34;#__codelineno-12-38&#34;&gt;&lt;/a&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; &lt;/li&gt; &lt;/ol&gt; &lt;h2 id=&#34;tilelink-widgets&#34;&gt;TileLink Widgets&lt;a class=&#34;headerlink&#34; href=&#34;#tilelink-widgets&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;Rocket Chip 中用 Diplomacy 实现 TileLink 总线的连接。涉及到的相关结构如下：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;TLBundle：代表 TileLink 总线的接口，根据 TLBundleParameters 例化&lt;/li&gt; &lt;li&gt;TLMasterPortParameters：信息 TileLink Master 的信息，从 Upstream 向 Downstream 传递&lt;/li&gt; &lt;li&gt;TLSlavePortParameters：信息 TileLink Slave 的信息，从 Downstream 向 Upstream 传递&lt;/li&gt; &lt;li&gt;TLEdgeOut：记录 Outward 边，也就是 Master 侧的 TileLink 的信息&lt;/li&gt; &lt;li&gt;TLEdgeIn：记录 Inward 边，也就是 Slave 侧的 TileLink 的信息&lt;/li&gt; &lt;li&gt;TLImp: &lt;code&gt;extends NodeImp[TLMasterPortParameters, TLSlavePortParameters, TLEdgeOut, TLEdgeIn, TLBundle]&lt;/code&gt;，基于这个类型来导出各种类型的 TileLink Node&lt;/li&gt; &lt;li&gt;TLXBar：TileLink 的 Crossbar，生成一个继承 NexusNode 的 TLNexusNode，它的信息传递方式是，把下游的各个 Slave 信息拼起来传给上游，使得 Master 可以看到所有 Slave 的信息；把上游的各个 Master 信息拼起来传给下游，使得 Slave 可以看到所有 Master 的信息&lt;/li&gt; &lt;li&gt;TLToAXI4：生成一个继承 AdapterNode 的 TLToAXI4Node，把 TileLink Master 转成 AXI4 Master，把上游的 TileLink Master 信息转换为 AXI Master 传递给下游，把下游的 AXI Slave 信息转换为 TileLink Slave 传递给上游&lt;/li&gt; &lt;/ol&gt; &lt;h2 id=&#34;参考文档&#34;&gt;参考文档&lt;a class=&#34;headerlink&#34; href=&#34;#参考文档&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://chipyard.readthedocs.io/en/latest/TileLink-Diplomacy-Reference/index.html&#34;&gt;TileLink and Diplomacy Reference&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://chipyard.readthedocs.io/en/latest/Generators/Rocket-Chip.html#memory-system&#34;&gt;Rocket Chip - Memory System&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://github.com/chipsalliance/diplomacy&#34;&gt;chipsalliance/diplomacy&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;</description> <link>https://jia.je/hardware/2025/05/14/rocket-chip-diplomacy/</link> <pubDate>Wed, 14 May 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2025/05/14/rocket-chip-diplomacy/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2025/05/14/rocket-chip-diplomacy.png" type="image/png" length="56792" /> </item> <item> <title>Intel Redwood Cove 微架构评测</title> <category>cpu</category> <category>graniterapids</category> <category>hardware</category> <category>intel</category> <category>meteorlake</category> <category>performance</category> <category>redwoodcove</category> <category>uarch-review</category> <description>&lt;h1 id=&#34;intel-redwood-cove-微架构评测&#34;&gt;Intel Redwood Cove 微架构评测&lt;a class=&#34;headerlink&#34; href=&#34;#intel-redwood-cove-微架构评测&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;背景&#34;&gt;背景&lt;a class=&#34;headerlink&#34; href=&#34;#背景&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;之前我们测试了 Intel 的微架构 &lt;a href=&#34;../../../01/10/intel-golden-cove/&#34;&gt;Redwood Cove&lt;/a&gt;，这次就来测一下 Redwood Cove，它被用到了 Meteor Lake 以及 Granite Rapids 上。这次就以阿里云 &lt;a href=&#34;https://help.aliyun.com/zh/ecs/user-guide/overview-of-instance-families#g9i&#34;&gt;g9i&lt;/a&gt; 实例的 Granite Rapids 机器来测试一下 Redwood Cove 微架构的各项指标。&lt;/p&gt; &lt;!-- more --&gt; &lt;h2 id=&#34;官方信息&#34;&gt;官方信息&lt;a class=&#34;headerlink&#34; href=&#34;#官方信息&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;Intel 关于 Redwood Cove 微架构有这些官方的信息：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://www.intel.com/content/www/us/en/content-details/814198/intel-64-and-ia-32-architectures-optimization-reference-manual-volume-1.html&#34;&gt;Intel® 64 and IA-32 Architectures Optimization Reference Manual Volume 1&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://www.thefpsreview.com/wp-content/uploads/2023/10/Meteor-Lake-Architecture-Overview.pdf&#34;&gt;Meteor Lake Architecture Overview&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h2 id=&#34;现有评测&#34;&gt;现有评测&lt;a class=&#34;headerlink&#34; href=&#34;#现有评测&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;网上已经有较多针对 Redwood Cove 微架构的评测和分析，建议阅读：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&#34;https://chipsandcheese.com/p/intels-redwood-cove-baby-steps-are-still-steps&#34;&gt;Intel’s Redwood Cove: Baby Steps are Still Steps&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href=&#34;https://www.anandtech.com/show/20046/intel-unveils-meteor-lake-architecture-intel-4-heralds-the-disaggregated-future-of-mobile-cpus/2&#34;&gt;Intel Unveils Meteor Lake Architecture: Intel 4 Heralds the Disaggregated Future of Mobile CPUs&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;下面分各个模块分别记录官方提供的信息，以及实测的结果。读者可以对照已有的第三方评测理解。官方信息与实测结果一致的数据会加粗。&lt;/p&gt; &lt;h2 id=&#34;benchmark&#34;&gt;Benchmark&lt;a class=&#34;headerlink&#34; href=&#34;#benchmark&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;Intel Redwood Cove 的性能测试结果见 &lt;a href=&#34;../../../../../benchmark/&#34;&gt;SPEC&lt;/a&gt;。&lt;/p&gt; &lt;h2 id=&#34;前端&#34;&gt;前端&lt;a class=&#34;headerlink&#34; href=&#34;#前端&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;l1-icache&#34;&gt;L1 ICache&lt;a class=&#34;headerlink&#34; href=&#34;#l1-icache&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Larger instruction cache: 32K→&lt;strong&gt;64K&lt;/strong&gt;.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;为了测试 L1 ICache 容量，构造一个具有巨大指令 footprint 的循环，由大量的 4 字节 nop 和最后的分支指令组成。观察在不同 footprint 大小下的 IPC：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../intel-redwood-cove-fetch-bandwidth.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到 footprint 在 64 KB 之前时可以达到 6 IPC，之后则降到 3.2 IPC，这里的 64 KB 就对应了 L1 ICache 的容量。容量相比 &lt;a href=&#34;../../../01/10/intel-golden-cove/&#34;&gt;Golden Cove&lt;/a&gt; 翻倍，终于和 ARM 看齐。&lt;/p&gt; &lt;h3 id=&#34;l1-itlb&#34;&gt;L1 ITLB&lt;a class=&#34;headerlink&#34; href=&#34;#l1-itlb&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;构造一系列的 jmp 指令，使得 jmp 指令分布在不同的 page 上，使得 ITLB 成为瓶颈：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../intel-redwood-cove-itlb-size.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到 256 个 Page 出现了明显的拐点，对应的就是 256 的 L1 ITLB 容量。注意要避免 ICache 和 BTB 的容量成为瓶颈，把 jmp 指令分布在不同的 Cache Line 和 BTB entry 上。&lt;/p&gt; &lt;p&gt;超过 256 个 Page 以后，如图有周期数突然下降后缓慢上升的情况（例如横坐标 288-&amp;gt;289、320-&amp;gt;321、352-&amp;gt;353、384-&amp;gt;385 等，以 32 为周期），背后的原理需要进一步分析，猜测和 Linux 的 Huge Page 机制相关。&lt;/p&gt; &lt;p&gt;Redwood Cove 的 L1 ITLB 容量和 &lt;a href=&#34;../../../01/10/intel-golden-cove/&#34;&gt;Golden Cove&lt;/a&gt; 是一样的。&lt;/p&gt; &lt;h3 id=&#34;instruction-decode-queue-idq--loop-stream-detector-lsd&#34;&gt;Instruction Decode Queue (IDQ) + Loop Stream Detector (LSD)&lt;a class=&#34;headerlink&#34; href=&#34;#instruction-decode-queue-idq--loop-stream-detector-lsd&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Improved LSD coverage: the IDQ can hold &lt;strong&gt;192&lt;/strong&gt; μops per logical processor in single-thread mode or 96 μops per thread when SMT is active.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;为了测试 Instruction Decode Queue 的大小，构造不同大小的循环，循环体是复制若干份的 &lt;code&gt;inc %rsi&lt;/code&gt; 指令，最后是 &lt;code&gt;dec + jnz&lt;/code&gt; 作为循环结尾，通过 &lt;a href=&#34;https://perfmon-events.intel.com/index.html?pltfrm=ahybrid.html&amp;amp;evnt=LSD.UOPS&#34;&gt;LSD.UOPS&lt;/a&gt; 性能计数器统计每次循环有多少个 UOP 来自于 Loop Stream Detector 机制，发现其最大值为 191，说明 Redwood Cove 的 Loop Stream Detector 可以识别最多 191 个 uop 的循环。此时每个循环要执行 192 条指令，最后的 &lt;code&gt;dec + jnz&lt;/code&gt; 被融合成了一个 uop。相比 &lt;a href=&#34;../../../01/10/intel-golden-cove/&#34;&gt;Golden Cove&lt;/a&gt; 的 144 uops IDQ 容量有所增加。&lt;/p&gt; &lt;p&gt;循环体中，如果用 &lt;code&gt;nop&lt;/code&gt; 指令来填充，会得到 39 左右的比 192 小得多的容量，猜测是进入了低功耗模式。&lt;/p&gt; &lt;h3 id=&#34;instruction-prefetch-instruction&#34;&gt;Instruction Prefetch Instruction&lt;a class=&#34;headerlink&#34; href=&#34;#instruction-prefetch-instruction&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Code Software Prefetch x86 architecture extension (Granite Rapids only).&lt;/li&gt; &lt;li&gt;PREFETCHIT0: (temporal code)—prefetch code into all levels of the cache hierarchy.&lt;/li&gt; &lt;li&gt;PREFETCHIT1: (temporal code with respect to first level cache misses)—prefetch code into all but the first-level of the cache hierarchy.&lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;conditional-branch-predictor&#34;&gt;Conditional Branch Predictor&lt;a class=&#34;headerlink&#34; href=&#34;#conditional-branch-predictor&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;参考 &lt;a href=&#34;https://cseweb.ucsd.edu/~dstefan/pubs/yavarzadeh:2023:half.pdf&#34;&gt;Half&amp;amp;Half: Demystifying Intel’s Directional Branch Predictors for Fast, Secure Partitioned Execution&lt;/a&gt; 论文的方法，可以测出 Redwood Cove 的分支预测器采用的历史更新方式为：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;使用 388 位的 Path History Register，每次执行 taken branch 时更新&lt;/li&gt; &lt;li&gt;更新方式为：&lt;code&gt;PHRnew = (PHRold &amp;lt;&amp;lt; 2) xor footprint&lt;/code&gt;&lt;/li&gt; &lt;li&gt;footprint 共有 16 位，其中 B 代表分支指令的地址，T 代表分支跳转的目的地址：&lt;ul&gt; &lt;li&gt;footprint[0] = B[3] xor T[0]&lt;/li&gt; &lt;li&gt;footprint[1] = B[4] xor T[1]&lt;/li&gt; &lt;li&gt;footprint[2] = B[5]&lt;/li&gt; &lt;li&gt;footprint[3] = B[6]&lt;/li&gt; &lt;li&gt;footprint[4] = B[7]&lt;/li&gt; &lt;li&gt;footprint[5] = B[8]&lt;/li&gt; &lt;li&gt;footprint[6] = B[9]&lt;/li&gt; &lt;li&gt;footprint[7] = B[10]&lt;/li&gt; &lt;li&gt;footprint[8] = B[0] xor T[2]&lt;/li&gt; &lt;li&gt;footprint[9] = B[1] xor T[3]&lt;/li&gt; &lt;li&gt;footprint[10] = B[2] xor T[4]&lt;/li&gt; &lt;li&gt;footprint[11] = B[11] xor T[5]&lt;/li&gt; &lt;li&gt;footprint[12] = B[12]&lt;/li&gt; &lt;li&gt;footprint[13] = B[13]&lt;/li&gt; &lt;li&gt;footprint[14] = B[14]&lt;/li&gt; &lt;li&gt;footprint[15] = B[15]&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;和 &lt;a href=&#34;../../../01/10/intel-golden-cove/&#34;&gt;Golden Cove&lt;/a&gt; 是一样的。各厂商处理器的 PHR 更新规则见 &lt;a href=&#34;https://jia.je/cpu/cbp.html&#34;&gt;jiegec/cpu&lt;/a&gt;。&lt;/p&gt; &lt;h2 id=&#34;后端&#34;&gt;后端&lt;a class=&#34;headerlink&#34; href=&#34;#后端&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;h3 id=&#34;l1-dcache&#34;&gt;L1 DCache&lt;a class=&#34;headerlink&#34; href=&#34;#l1-dcache&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;构造不同大小 footprint 的 pointer chasing 链，测试不同 footprint 下每条 load 指令耗费的时间：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;0KB-48KB: 5 cycle，对应 L1 DCache&lt;/li&gt; &lt;li&gt;48KB-384KB: 16 cycle，对应 L2 Cache，且命中了 L1 DTLB；说明 L1 miss L2 hit 带来了 11 cycle 的损失&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;L1 DCache 大小和 &lt;a href=&#34;../../../01/10/intel-golden-cove/&#34;&gt;Golden Cove&lt;/a&gt; 相同。&lt;/p&gt; &lt;h3 id=&#34;l1-dtlb&#34;&gt;L1 DTLB&lt;a class=&#34;headerlink&#34; href=&#34;#l1-dtlb&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;用类似测 L1 DCache 的方法测试 L1 DTLB 容量，只不过这次 pointer chasing 链的指针分布在不同的 page 上，使得 DTLB 成为瓶颈：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../intel-redwood-cove-dtlb-size.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;可以看到 96 Page 出现了明显的拐点，对应的就是 96 的 L1 DTLB 容量。没有超出 L1 DTLB 容量前，Load to use latency 是 5 cycle；超出 L1 DTLB 容量后，Load to use latency 是 12 cycle，说明 L1 DTLB miss 带来了 7 cycle 的损失。&lt;/p&gt; &lt;p&gt;L1 DTLB 大小和 &lt;a href=&#34;../../../01/10/intel-golden-cove/&#34;&gt;Golden Cove&lt;/a&gt; 相同。&lt;/p&gt; &lt;h3 id=&#34;执行单元&#34;&gt;执行单元&lt;a class=&#34;headerlink&#34; href=&#34;#执行单元&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;EXE: 3-cycle Floating Point multiplication.&lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;lsu&#34;&gt;LSU&lt;a class=&#34;headerlink&#34; href=&#34;#lsu&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;h4 id=&#34;load-store-带宽&#34;&gt;Load Store 带宽&lt;a class=&#34;headerlink&#34; href=&#34;#load-store-带宽&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;针对 Load Store 带宽，实测每个周期可以完成：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;3x 256b Load&lt;/li&gt; &lt;li&gt;2x 256b Load + 2x 256b Store&lt;/li&gt; &lt;li&gt;1x 256b Load + 2x 256b Store&lt;/li&gt; &lt;li&gt;2x 256b Store&lt;/li&gt; &lt;li&gt;2x 512b Load&lt;/li&gt; &lt;li&gt;1x 512b Load + 1x 512b Store&lt;/li&gt; &lt;li&gt;1x 512b Store&lt;/li&gt; &lt;/ul&gt; &lt;h4 id=&#34;store-to-load-forwarding&#34;&gt;Store to Load Forwarding&lt;a class=&#34;headerlink&#34; href=&#34;#store-to-load-forwarding&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h4&gt; &lt;p&gt;经过实际测试，Redwood Cove 上如下的情况可以成功转发，对地址 x 的 Store 转发到对地址 y 的 Load 成功时 y-x 的取值范围：&lt;/p&gt; &lt;table&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;Store\Load&lt;/th&gt; &lt;th&gt;8b Load&lt;/th&gt; &lt;th&gt;16b Load&lt;/th&gt; &lt;th&gt;32b Load&lt;/th&gt; &lt;th&gt;64b Load&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;8b Store&lt;/td&gt; &lt;td&gt;{0}&lt;/td&gt; &lt;td&gt;{}&lt;/td&gt; &lt;td&gt;{}&lt;/td&gt; &lt;td&gt;{}&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;16b Store&lt;/td&gt; &lt;td&gt;[0,1]&lt;/td&gt; &lt;td&gt;{0}&lt;/td&gt; &lt;td&gt;{}&lt;/td&gt; &lt;td&gt;{}&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;32b Store&lt;/td&gt; &lt;td&gt;[0,3]&lt;/td&gt; &lt;td&gt;[0,2]&lt;/td&gt; &lt;td&gt;{0}&lt;/td&gt; &lt;td&gt;{}&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;64b Store&lt;/td&gt; &lt;td&gt;[0,7]&lt;/td&gt; &lt;td&gt;[0,6]&lt;/td&gt; &lt;td&gt;[0,4]&lt;/td&gt; &lt;td&gt;{0}&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;p&gt;可以看到，Redwood Cove 在 Store 完全包含 Load 的情况下都可以转发，没有额外的对齐要求。但当 Load 和 Store 只有部分重合时，就无法转发。两个连续的 32 位的 Store 和一个 64 位的 Load 重合也不能转发。&lt;/p&gt; &lt;p&gt;特别地，在 y=x 且不跨越缓存行边界且满足下列要求的情况下，Store Forwarding 不会或只带来很小的性能损失：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;8b Store -&amp;gt; 8b Load&lt;/li&gt; &lt;li&gt;32b Store -&amp;gt; 8b Load&lt;/li&gt; &lt;li&gt;64b Store -&amp;gt; 8b Load&lt;/li&gt; &lt;li&gt;32b Store -&amp;gt; 32b Load&lt;/li&gt; &lt;li&gt;64b Store -&amp;gt; 32b Load&lt;/li&gt; &lt;li&gt;64b Store -&amp;gt; 64b Load&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;考虑到 y 必须等于 x，也就是地址要一样，猜测 Redwood Cove 使用了类似 Memory Renaming 的技术来实现这个效果。如果是连续两个对同一个地址的 Store 对一个 Load 的转发，效果和只有一个 Store 是一样的。&lt;/p&gt; &lt;p&gt;除了上述情况以外，Store Forwarding 成功时的延迟在 5 个周期，失败则要 19 个周期。&lt;/p&gt; &lt;p&gt;和 &lt;a href=&#34;../../../01/10/intel-golden-cove/&#34;&gt;Golden Cove&lt;/a&gt; 是一样的。&lt;/p&gt; &lt;p&gt;小结：Redwood Cove 的 Store to Load Forwarding：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;1 ld + 1 st: 要求 st 包含 ld，特别地，地址相同时，性能最好&lt;/li&gt; &lt;li&gt;1 ld + 2+ st: 不支持&lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;prefetcher&#34;&gt;Prefetcher&lt;a class=&#34;headerlink&#34; href=&#34;#prefetcher&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;官方信息：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;New HW data prefetcher to recognize and prefetch the “Array of Pointers” pattern.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Intel Redwood Cove 的处理器通过 MSR 1A4H 可以配置各个预取器（来源：Software Developers Manual，Additional MSRs Supported by the Intel® Core™ Ultra 7 Processors Supporting Performance Hybrid Architecture）：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;MSR_1A4H[0]: the L2 hardware prefetcher, which fetches additional lines of code or data into the L2 cache.&lt;/li&gt; &lt;li&gt;MSR_1A4H[1]: the L2 adjacent cache line prefetcher, which fetches the cache line that comprises a cache line pair (128 bytes). 这和 AMD 的 Up/Down Prefetcher 应该是一个意思&lt;/li&gt; &lt;li&gt;MSR_1A4H[2]: the L1 data cache prefetcher, which fetches the next cache line into L1 data cache. 这个应该属于 Next Line Prefetcher&lt;/li&gt; &lt;li&gt;MSR_1A4H[3]: the L1 data cache IP prefetcher, which uses sequential load history (based on instruction pointer of previous loads) to determine whether to prefetch additional lines.&lt;/li&gt; &lt;li&gt;MSR_1A4H[4]: Next page prefetcher，当访问快走到一个页的结尾的时候，从下一个页的开头开始 prefetch，提前进行可能的 TLB refill&lt;/li&gt; &lt;li&gt;MSR_1A4H[5]: the L2 Adaptive Multipath Probability (AMP) prefetcher. 这个应该属于 Spatial Prefetcher&lt;/li&gt; &lt;li&gt;MSR_1A4H[6]: LLC page prefetcher，类似 Next page prefetcher 的思路，但是把虚拟地址上连续的两个 4KB 的页，一共 8KB 的数据预取到 LLC 缓存上&lt;/li&gt; &lt;li&gt;MSR_1A4H[7]: Array of pointers prefetcher，针对指针数组 &lt;code&gt;T *arr[]&lt;/code&gt; 的场景进行预取&lt;/li&gt; &lt;li&gt;MSR_1A4H[8]: Stream prefetch code fetch&lt;/li&gt; &lt;/ul&gt; &lt;h3 id=&#34;reorder-buffer&#34;&gt;ReOrder Buffer&lt;a class=&#34;headerlink&#34; href=&#34;#reorder-buffer&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;为了测试 ROB 的大小，设计了一个循环，循环开始和结束是长延迟的 long latency load。中间是若干条 NOP 指令，当 NOP 指令比较少时，循环的时候取决于 load 指令的时间；当 NOP 指令数量过多，填满了 ROB 以后，就会导致 ROB 无法保存循环末尾的 load 指令，性能出现下降。测试结果如下：&lt;/p&gt; &lt;p&gt;&lt;img alt=&#34;&#34; src=&#34;../../../../intel-redwood-cove-rob-size.png&#34; /&gt;&lt;/p&gt; &lt;p&gt;当 NOP 数量达到 512 时，性能开始急剧下滑，说明 Redwood Cove 的 ROB 大小是 512。这和 &lt;a href=&#34;../../../01/10/intel-golden-cove/&#34;&gt;Golden Cove&lt;/a&gt; 是一样的。&lt;/p&gt; &lt;h2 id=&#34;总结&#34;&gt;总结&lt;a class=&#34;headerlink&#34; href=&#34;#总结&#34; title=&#34;Permanent link&#34;&gt;&amp;para;&lt;/a&gt;&lt;/h2&gt; &lt;p&gt;Redwood Cove 相比 Golden Cove 是比较小的一个迭代，更新的部分主要有：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;扩大了 L1 ICache 容量&lt;/li&gt; &lt;li&gt;扩大了分支预测器的容量（通过 MPKI 看出）&lt;/li&gt; &lt;li&gt;增加了更多预取器&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;因此性能提升也比较小，希望 Intel 可以更加给力一些，给 AMD 一些竞争压力。&lt;/p&gt;</description> <link>https://jia.je/hardware/2025/04/23/intel-redwood-cove/</link> <pubDate>Wed, 23 Apr 2025 00:00:00 +0000</pubDate> <source url="https://jia.je/feed_rss_updated.xml">杰哥的{运维，编程，调板子}小笔记</source><guid isPermaLink="true">https://jia.je/hardware/2025/04/23/intel-redwood-cove/</guid> <enclosure url="https://jia.je/assets/images/social/hardware/2025/04/23/intel-redwood-cove.png" type="image/png" length="52398" /> </item> </channel> </rss>