【UVM学习笔记】更加灵活的UVM—通信
系列文章目录
【UVM学习笔记】UVM基础—一文告诉你UVM的组成部分
【UVM学习笔记】UVM中的“类”
文章目录
- 系列文章目录
- 前言
- 一、TLM是什么?
- 二、put操作
- 2.1、建立PORT和EXPORT的连接
- 2.2 IMP组件
- 三、get操作
- 四、transport端口
- 五、nonblocking端口
- 六、analysis端口
- 七、monitor与scoreboard之间的通信
- 八、使用FIFO通信
- 总结
前言
该专题用于记录学习UVM芯片验证的过程,主要学习书籍为经典的《UVM实战》,同时也会去进行一些UVM的项目联系。
一、TLM是什么?
TLM是Transaction Level Modeling(事务级建模)的缩写。所谓transaction level是相对DUT中各个模块之间信号线级别的通信来说的。
TLM通常有三种模式:
- put操作,通信的发起者A把一个transaction发送给B。在这个过程中,A称为“发起者”,而B称为“目标”。A具有的端口(用方框表示)称为PORT,而B的端口(用圆圈表示)称为EXPORT。这个过程中,数据流是从A流向B的。
- get操作。在这个过程中,A依然是“发起者”,B依然是“目标”,A上的端口依然是PORT,而B上的端口依然是EXPORT。这个过程中,数据流是从B流向A的。PORT和EXPORT体现的是控制流而不是数据流。

- transport操作,transport操作相当于一次put操作加一次get操作,这两次操作的“发起者”都是A,目标都是B。在这个过程中,数据流先从A流向B,再从B流向A。在现实世界中, 相当于是A向B提交了一个请求(request),而B返回给A一个应答(response)。

二、put操作
2.1、建立PORT和EXPORT的连接
UVM中使用connect函数来建立连接关系。如A要和B通信(A是发起者),那么可以这么写:A.port.connect(B.export)。下面是A的代码部分:
class A extends uvm_component;`uvm_component_utils(A)uvm_blocking_put_port#(my_transaction) A_port;function new(string name, uvm_component parent);super.new(name, parent);endfunctionextern function void build_phase(uvm_phase phase);extern virtual task main_phase(uvm_phase phase);
endclassfunction void A::build_phase(uvm_phase phase);super.build_phase(phase);A_port = new("A_port", this);
endfunctiontask A::main_phase(uvm_phase phase);
endtask
然后得到B的代码:
class B extends uvm_component;`uvm_component_utils(B)uvm_blocking_put_export#(my_transaction) B_export;function new(string name, uvm_component parent);super.new(name, parent);endfunctionextern function void build_phase(uvm_phase phase);extern virtual task main_phase(uvm_phase phase);
endclassfunction void B::build_phase(uvm_phase phase);super.build_phase(phase);B_export = new("B_export", this);
endfunctiontask B::main_phase(uvm_phase phase);
endtask
然后在env将两者进行链接
class my_env extends uvm_env;A A_inst;B B_inst;function new(string name = "my_env", uvm_component parent);super.new(name, parent);endfunctionvirtual function void build_phase(uvm_phase phase);super.build_phase(phase);A_inst = A::type_id::create("A_inst", this);B_inst = B::type_id::create("B_inst", this);endfunctionextern virtual function void connect_phase(uvm_phase phase);`uvm_component_utils(my_env)
endclassfunction void my_env::connect_phase(uvm_phase phase);super.connect_phase(phase);A_inst.A_port.connect(B_inst.B_export);
endfunction
2.2 IMP组件
除了TLM中定义的PORT与EXPORT外,UVM中加入了第三种端口:IMP,起作用相当于在EXPORT后进行接受操作。
添加IMP后,A的代码变为:
task A::main_phase(uvm_phase phase);my_transaction tr;repeat(10) begin#10;tr = new("tr");assert(tr.randomize());A_port.put(tr);end
endtask
在B中需要改动的要多一点:
class B extends uvm_component;`uvm_component_utils(B)uvm_blocking_put_export#(my_transaction) B_export;uvm_blocking_put_imp#(my_transaction, B) B_imp;function new(string name, uvm_component parent);super.new(name, parent);endfunctionextern function void build_phase(uvm_phase phase);extern function void connect_phase(uvm_phase phase);extern function void put(my_transaction tr);extern virtual task main_phase(uvm_phase phase);
endclassfunction void B::build_phase(uvm_phase phase);super.build_phase(phase);B_export = new("B_export", this);B_imp = new("B_imp", this);
endfunctionfunction void B::connect_phase(uvm_phase phase);super.connect_phase(phase);B_export.connect(B_imp);
endfunctionfunction void B::put(my_transaction tr);`uvm_info("B", "receive a transaction", UVM_LOW) tr.print();
endfunction
在上述连接关系中,IMP是作为连接的终点。在UVM中,只有IMP才能作为连接关系的终点。如果是PORT或者EXPORT作为终点,则会报错。
三、get操作
get系列端口与put系列端口在某些方面完全相反。在这种连接关系中,数据流依然是从A到B,但是A由动作发起者变成了动作接收者,而B由动作接收者变成了动作发起者。

B_port的类型为uvm_blocking_get_port,A_export的类型为uvm_blocking_get_export,A_imp的类型为uvm_blocking_get_imp。A的代码为:
class A extends uvm_component;`uvm_component_utils(A)uvm_blocking_get_export#(my_transaction) A_export;uvm_blocking_get_imp#(my_transaction, A) A_imp;my_transaction tr_q[$];function new(string name, uvm_component parent);super.new(name, parent);endfunctionextern function void build_phase(uvm_phase phase);extern function void connect_phase(uvm_phase phase);extern virtual task get(output my_transaction tr);extern virtual task main_phase(uvm_phase phase);
endclassfunction void A::build_phase(uvm_phase phase);super.build_phase(phase);A_export = new("A_export", this);A_imp = new("A_imp", this);
endfunctionfunction void A::connect_phase(uvm_phase phase);super.connect_phase(phase);A_export.connect(A_imp);
endfunctiontask A::get(output my_transaction tr);while(tr_q.size() == 0) #2;tr = tr_q.pop_front();
endtasktask A::main_phase(uvm_phase phase);my_transaction tr;repeat(10) begin#10;tr = new("tr");tr_q.push_back(tr); end
endtask
在A的get任务中,每隔2个时间单位检查tr_q中是否有数据,如果有则发送出去。当B在其main_phase调用get任务时,会最终执行A的get任务。在A的connect_phase,需要把A_export和A_imp连接起来。下面是B的部分:
class B extends uvm_component;`uvm_component_utils(B)uvm_blocking_get_port#(my_transaction) B_port;function new(string name, uvm_component parent);super.new(name, parent);endfunctionextern function void build_phase(uvm_phase phase);extern virtual task main_phase(uvm_phase phase);
endclassfunction void B::build_phase(uvm_phase phase);super.build_phase(phase);B_port = new("B_port", this);
endfunctiontask B::main_phase(uvm_phase phase);my_transaction tr;while(1) beginB_port.get(tr);`uvm_info("B", "get a transaction", UVM_LOW) tr.print();end
endtask
在这些连接关系中,需要谨记的是连接的终点必须是一个IMP。
四、transport端口

A代码如下所示:
task A::main_phase(uvm_phase phase);my_transaction tr;my_transaction rsp;repeat(10) begin#10;tr = new("tr");assert(tr.randomize());A_transport.transport(tr, rsp);`uvm_info("A", "received rsp", UVM_MEDIUM)rsp.print();end
endtask
B中需要定义一个类型为uvm_blocking_transport_imp的IMP:
class B extends uvm_component;`uvm_component_utils(B)uvm_blocking_transport_imp#(my_transaction, my_transaction, B) B_imp;function new(string name, uvm_component parent);super.new(name, parent);endfunctionextern function void build_phase(uvm_phase phase);extern task transport(my_transaction req, output my_transaction rsp);
endclassfunction void B::build_phase(uvm_phase phase);super.build_phase(phase);B_imp = new("B_imp", this);
endfunctiontask B::transport(my_transaction req, output my_transaction rsp);`uvm_info("B", "receive a transaction", UVM_LOW) req.print();//do something according to req#5;rsp = new("rsp");
endtask
env中的代码是:
function void my_env::connect_phase(uvm_phase phase);super.connect_phase(phase);A_inst.A_transport.connect(B_inst.B_imp);
endfunction
在A中调用transport任务,并把生成的transaction作为第一个参数。B中的transaport任务接收到这笔transaction,根据这笔transaction做某些操作,并把操作的结果作为transport的第二个参数发送出去。A根据接收到的rsp来决定后面的行为。
五、nonblocking端口
task A::main_phase(uvm_phase phase);my_transaction tr;repeat(10) begintr = new("tr");assert(tr.randomize());while(!A_port.can_put()) #10;void'(A_port.try_put(tr));end
endtask
由于端口变为了非阻塞的,所以在送出transaction之前需要调用can_put函数来确认是否能够执行put操作。can_put最终会调用B中的can_put:
六、analysis端口
UVM中还有两种特殊的端口:analysis_port和analysis_export。该端口有两点需要注意的地方:
- 一个analysis_port(analysis_export)可以连接多个IMP,analysis_port(analysis_export)与IMP 之间的通信是一对多的通信。analysis_port(analysis_export)更像是一个广播。
- put与get系列端口都有阻塞和非阻塞的区分。但是对于analysis_port和analysis_export来说,没有阻塞和非阻塞的概念。
一个analysis_port可以和多个IMP相连接进行通信,但是IMP的类型必须是uvm_analysis_imp,否则会报错。

下面是A的代码:
class A extends uvm_component;`uvm_component_utils(A)uvm_analysis_port#(my_transaction) A_ap;function new(string name, uvm_component parent);super.new(name, parent);endfunctionextern function void build_phase(uvm_phase phase);extern virtual task main_phase(uvm_phase phase);
endclassfunction void A::build_phase(uvm_phase phase);super.build_phase(phase);A_ap = new("A_ap", this);
endfunctiontask A::main_phase(uvm_phase phase);my_transaction tr;repeat(10) begin#10;tr = new("tr");assert(tr.randomize());A_ap.write(tr);end
endtask
A的代码很简单,只是简单地定义一个analysis_port,并在main_phase中每隔10个时间单位写入一个transaction。
B的代码为:
function void B::write(my_transaction tr);`uvm_info("B", "receive a transaction", UVM_LOW) tr.print();
endfunction
在env中通过下面方式进行连接:
function void my_env::connect_phase(uvm_phase phase);super.connect_phase(phase);A_inst.A_ap.connect(B_inst.B_imp);A_inst.A_ap.connect(C_inst.C_imp);
endfunction
上面只是一个analysis_port与IMP相连的例子。analysis_export和IMP也可以这样相连接,只需将上面例子中的uvm_analysis_port改为uvm_analysis_export就可以。
七、monitor与scoreboard之间的通信
和上一个一样,在两段分别进行定义,monitor的代码为:
task my_monitor::main_phase(uvm_phase phase);my_transaction tr;while(1) begintr = new("tr");collect_one_pkt(tr);ap.write(tr);end
endtask
scoreboard的代码为:
function void my_scoreboard::write_monitor(my_transaction tr);my_transaction tmp_tran;bit result;if(expect_queue.size() > 0) begintmp_tran = expect_queue.pop_front();result = tr.compare(tmp_tran);if(result) begin `uvm_info("my_scoreboard", "Compare SUCCESSFULLY", UVM_LOW);endelse begin`uvm_error("my_scoreboard", "Compare FAILED");$display("the expect pkt is");tmp_tran.print();$display("the actual pkt is");tr.print();endendelse begin`uvm_error("my_scoreboard", "Received from DUT, while Expect Queue is empty");$display("the unexpected pkt is");tr.print();end
endfunction
之后在env中可以使用connect连接。
由于monitor与scoreboard在UVM树中并不是平等的兄妹关系,这里选择下面的连接方式:
在agent中声明一个ap,但是不实例化它,让其指向monitor中的ap。在env中可以直接连接agent的ap到scoreboard的imp:
agent:
class my_agent extends uvm_agent ; uvm_analysis_port #(my_transaction) ap; ... function void my_agent::connect_phase(uvm_phase phase); ap = mon.ap; ... endfunction
endclass
env:
function void my_env::connect_phase(uvm_phase phase); o_agt.ap.connect(scb.scb_imp); ...
endfunction
在上面的例子中,scoreboard只接收一路数据。但在现实情况中,scoreboard除了接收monitor的数据之外,还要接收reference model的数据。相应的scoreboard就要再添加一个 uvm_analysis_imp的IMP。此时问题就出现了,由于接收到的两路数据应该做不同的处理,所以这个新的IMP也要有一个write任务与其对应。但是write只有一个,怎么办?
可以使用宏定义的方法:
`uvm_analysis_imp_decl(_monitor)
`uvm_analysis_imp_decl(_model)
class my_scoreboard extends uvm_scoreboard;my_transaction expect_queue[$];uvm_analysis_imp_monitor#(my_transaction, my_scoreboard) monitor_imp; uvm_analysis_imp_model#(my_transaction, my_scoreboard) model_imp;`uvm_component_utils(my_scoreboard)extern function new(string name, uvm_component parent = null);extern virtual function void build_phase(uvm_phase phase);extern virtual task main_phase(uvm_phase phase);
endclass
上述代码通过宏uvm_analysis_imp_decl声明了两个后缀_monitor和_model。
当与monitor_imp相连接的analysis_port执行write函数时,会自动调用write_monitor函数,而与model_imp相连接的analysis_port执行write 函数时,会自动调用write_model函数。
八、使用FIFO通信
使用fifo的方法能够让两个端口都能实现主动的接收,因此下面的例子便是利用FIFO来实现monitor和scoreboard的通信。
FIFO的本质是一块缓存加两个IMP。在monitor与FIFO的连接关系中,monitor中依然是analysis_port,FIFO中是uvm_analysis_imp,数据流和控制流的方向相同。在scoreboard与FIFO的连接关系中,scoreboard中使用blocking_get_port端口:
class my_scoreboard extends uvm_scoreboard;my_transaction expect_queue[$];uvm_blocking_get_port #(my_transaction) exp_port[16];uvm_blocking_get_port #(my_transaction) act_port;`uvm_component_utils(my_scoreboard)extern function new(string name, uvm_component parent = null);extern virtual function void build_phase(uvm_phase phase);extern virtual task main_phase(uvm_phase phase);
endclass
而FIFO中使用的是一个get端口的IMP。在这种连接关系中,控制流是从scoreboard到FIFO,而数据流是从FIFO到scoreboard。

在env中连接方式如下:
function void my_env::connect_phase(uvm_phase phase);super.connect_phase(phase);i_agt.ap.connect(agt_mdl_fifo.analysis_export);mdl.port.connect(agt_mdl_fifo.blocking_get_export);for(int i = 0; i < 16; i++) beginmdl.ap[i].connect(mdl_scb_fifo[i].analysis_export);scb.exp_port[i].connect(mdl_scb_fifo[i].blocking_get_export);endo_agt.ap.connect(agt_scb_fifo.analysis_export);scb.act_port.connect(agt_scb_fifo.blocking_get_export);
endfunction
FIFO中有两个IMP,但是在上面的连接关系中,FIFO中却是EXPORT,这是为什么呢?实际上,FIFO中的analysis_export和blocking_get_export虽然名字中有关键字export,但是其类型却是IMP。UVM为了掩饰IMP的存在,在它们的命名中加入了export关键字。
但事实上,FIFO上的端口并不局限于上述两个,一个FIFO中有众多的端口。端口列表如下:

总结
总结来说,这一章主要讲了数据在UVM中的传递方式,学习这一章可以更好的编写灵活性更高的UVM代码。
相关文章:
【UVM学习笔记】更加灵活的UVM—通信
系列文章目录 【UVM学习笔记】UVM基础—一文告诉你UVM的组成部分 【UVM学习笔记】UVM中的“类” 文章目录 系列文章目录前言一、TLM是什么?二、put操作2.1、建立PORT和EXPORT的连接2.2 IMP组件 三、get操作四、transport端口五、nonblocking端口六、analysis端口七…...
NSSCTF [HGAME 2023 week1]simple_shellcode
3488.[HGAME 2023 week1]simple_shellcode 手写read函数shellcode和orw [HGAME 2023 week1]simple_shellcode (1) motalymotaly-VMware-Virtual-Platform:~/桌面$ file vuln vuln: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpret…...
前端面试题之CSS中的box属性
前几天在面试中遇到面试官问了一个关于box的属性面试题,平时都是直接AI没有仔细去看过。来说说CSS中的常用box属性: 1. box-sizing box-sizing 属性定义了元素的宽度和高度是否包括内边距(padding)和边框(border&…...
数据集(Dataset)和数据加载器(DataLoader)-pytroch学习3
pytorch网站学习 处理数据样本的代码往往会变得很乱、难以维护;理想情况下,我们希望把数据部分的代码和模型训练部分分开写,这样更容易阅读、也更好维护。 简单说:数据和模型最好“分工明确”,不要写在一起。 PyTor…...
数据结构|排序算法(一)快速排序
一、排序概念 排序是数据结构中的一个重要概念,它是指将一组数据元素按照特定的顺序进行排列的过程,默认是从小到大排序。 常见的八大排序算法: 插入排序、希尔排序、冒泡排序、快速排序、选择排序、堆排序、归并排序、基数排序 二、快速…...
文件或目录损坏且无法读取:数据恢复的实战指南
在数字化时代,数据的重要性不言而喻。然而,在日常使用电脑、移动硬盘、U盘等存储设备时,我们难免会遇到“文件或目录损坏且无法读取”的提示。这一提示如同晴天霹雳,让无数用户心急如焚,尤其是当这些文件中存储着重要的…...
leetcode数组-螺旋矩阵Ⅱ
题目 题目链接:https://leetcode.cn/problems/spiral-matrix-ii/ 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 输入:n 3 输出:[[1,2,3],[8,9,4],[7…...
小刚说C语言刷题——第14讲 逻辑运算符
当我们需要将一个表达式取反,或者要判断两个表达式组成的大的表达式的结果时,要用到逻辑运算符。 1.逻辑运算符的分类 (1)逻辑非(!) !a,当a为真时,!a为假。当a为假时,!a为真。 例…...
WPS宏开发手册——Excel实战
目录 系列文章5、Excel实战使用for循环给10*10的表格填充行列之和使用for循环将10*10表格中的偶数值提取到另一个sheet页使用for循环给写一个99乘法表按市场成员名称分类(即市场成员A、B、C...),统计月内不同时间段表1和表2的乘积之和&#x…...
Buildroot与Yocto介绍比对
Buildroot 和 Yocto 是嵌入式 Linux 领域最常用的两大系统构建工具,它们在功能定位、使用方法和适用场景上有显著差异。以下从专业角度对两者进行对比分析: 一、Buildroot 核心功能与特点 1. 功能定位 轻量级系统构建工具:专注于快速生成精…...
前端加密方式 AES对称加密 RSA非对称加密 以及 MD5哈希算法详解
在前端开发中,MD5 并不是用于加密解密的算法,而是一个不可逆的哈希算法(即生成固定长度的摘要,但无法逆向解密)。如果你需要实现加密解密功能,应该使用对称加密算法(如 AES)或非对称…...
32--当网络接口变成“夜店门口“:802.1X协议深度解码(理论纯享版本)
当网络接口变成"夜店门口":802.1X协议深度解码 引言:网口的"保安队长"上岗记 如果把企业网络比作高端会所,那么802.1X协议就是门口那个拿着金属探测器的黑超保安。它会对着每个想进场的设备说:“请出示您的会…...
MAUI开发第一个app的需求解析:登录+版本更新,用于喂给AI
vscode中MAUI框架已经搭好,用MAUI+c#webapi+orcl数据库开发一个app, 功能是两个界面一个登录界面,登录注册常用功能,另一个主窗体,功能先空着,显示“主要功能窗体”。 这是一个全新的功能,需要重零开始涉及所有数据表 登录后检查是否有新版本程序,自动更新功能。 1.用户…...
Linux系统进程
Linux系统进程 程序开始 编译链接的引导代码 操作系统下的应用程序在main执行前也需要先执行段引导代码才能去执行main,但写应用程序时不用考虑引导代码的问题,编译连接时(准确说是链接时)由链接器将编译器中事先准备好的引导代码…...
【Cursor】切换主题
右键顶部,把菜单栏勾上 首选项-主题-颜色主题 选择和喜欢的颜色主题即可,一般是“现代深色”...
spring druid项目中监控sql执行情况
场景 在 Spring Boot 结合 MyBatis 的服务中,实现 SQL 执行覆盖情况的监控,可以基于Druid提供的内置的 SQL 监控统计功能。 开启监控 在 application.yml 中启用 Druid 的 stat 和 wall 过滤器,并配置监控页面的访问权限 …...
Obsidian按下三个横线不能出现文档属性
解决方案: 需要在标题下方的一行, 按下 键盘数字0后面那个横线(英文横线), 然后回车就可以了 然后点击横线即可...
pyqt SQL Server 数据库查询-优化2
1、增加导出数据功能 2、增加删除表里数据功能 import sys import pyodbc from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QListWidget, QLineEdit, QPushButton, \QTableWidget, QTableWidgetItem, QLabel, QMessageBox from PyQt6.QtGui i…...
Hyperlane:高性能 Rust HTTP 服务器框架评测
Hyperlane:高性能 Rust HTTP 服务器框架评测 在当今快速发展的互联网时代,选择一个高效、可靠的 HTTP 服务器框架对于开发者来说至关重要。最近,我在评估各种服务器框架性能时,发现了一个名为 Hyperlane 的 Rust HTTP 服务器库&a…...
Laravel 中使用 JWT 作用户登录,身份认证
什么是JWT: JWT 全名 JSON Web Token,是一种开放标准 (RFC 7519)。 用于在网络应用环境间安全地传输信息作为 JSON 对象。 它是一种轻量级的认证和授权机制,特别适合分布式系统的身份验证。 核心特点 紧凑格式:体积小&#x…...
JavaScript BOM核心对象、本地存储
目录 BOM 核心对象详解 一、location 对象 1. 常用属性 2. 常用方法 3. 应用场景 二、navigator 对象 1. 核心属性 2. 常用方法 3. 应用场景 三、history 对象 1. 核心属性和方法 2. 应用场景 四、兼容性与注意事项 五、总结 本地存储与复杂数据类型处理 一、本…...
VBA中类的解读及应用第二十二讲:利用类判断任意单元格的类型-5
《VBA中类的解读及应用》教程【10165646】是我推出的第五套教程,目前已经是第一版修订了。这套教程定位于最高级,是学完初级,中级后的教程。 类,是非常抽象的,更具研究的价值。随着我们学习、应用VBA的深入࿰…...
ffmpeg常见命令3
文章目录 1. **文字水印(Text Watermark)**示例命令:更多选项:2. **图片水印(Image Watermark)**示例命令:更多选项:3. **画中画(Picture-in-Picture, PIP)**示例命令:更多选项:4. **多宫格效果(Grid Effect)**示例命令(2x2 网格):更多选项:综合示例:文字水…...
Spring Boot 可扩展脱敏框架设计全解析 | 注解+策略模式+模板方法模式实战
一、需求场景:为什么需要脱敏框架? 在数据安全合规要求下,敏感信息处理成为系统必备能力。典型场景: 用户隐私保护(手机号、身份证、邮箱等)日志敏感信息过滤接口返回数据自动脱敏 传统方案痛点…...
STM32F103_LL库+寄存器学习笔记13 - 梳理外设CAN与如何发送CAN报文(串行发送)
导言 CAN总线因其高速稳定的数据传输与卓越抗干扰性能,在汽车、机器人及工业自动化中被广泛应用。它采用分布式网络结构,实现多节点间实时通信,确保各控制模块精准协同。在汽车领域,CAN总线连接发动机、制动、车身系统,…...
JavaScript学习19-事件类型之鼠标事件
1. 2. 3....
Linux系统调用编程
文章目录 一、进程和线程二、Linux的虚拟内存管理和stm32的真实物理内存**Linux虚拟内存管理**STM32物理内存映射2. 主要区别 三、Linux系统调用函数 fork()、wait()、exec()1. fork():创建子进程2. wait():等待子进程状态改变3. exec():替换…...
游戏引擎学习第203天
回顾当前情况 在这里我将直播完成整个游戏的制作。我们现在面临一些技术上的困难,确实如此。我的笔记本电脑的电源接口坏了,所以我不得不准备了这台备用笔记本,希望它能够正常工作。我所以希望一切都还好,尽管我不完全确定是否一…...
408 计算机网络 知识点记忆(4)
前言 本文基于王道考研课程与湖科大计算机网络课程教学内容,系统梳理核心知识记忆点和框架,既为个人复习沉淀思考,亦希望能与同行者互助共进。(PS:后续将持续迭代优化细节) 往期内容 408 计算机网络 知识…...
线性代数:分块矩阵,秩,齐次线性,非齐次线性的解相关经典例题
所以C错误,选D 排除A,B选项...
