当前位置: 首页 > news >正文

Gemmini测试test文件chisel源码详解(一)

DMACommandTrackerTest.scala

源码如下:

package gemminiimport scala.collection.mutable.ArrayBufferimport chisel3._
import chisel3.iotesters.{ChiselFlatSpec, PeekPokeTester}class DMACommandTrackerTester(c: DMAReadCommandTracker[UInt]) extends PeekPokeTester(c) {case class AllocatedCmd(id: Int, tag: Int, requestsSent: Int)var max_cycles = 100000000var cmdsToAllocate = 100val cmdIdsAllocated: ArrayBuffer[AllocatedCmd] = ArrayBuffer() // TODO use a map insteadwhile ((cmdsToAllocate > 0 || cmdIdsAllocated.size > 0) && max_cycles > 0) {val can_allocate = cmdsToAllocate > 0 && rnd.nextBoolean()poke(c.io.alloc.valid, can_allocate)val tag = rnd.nextInt(100)poke(c.io.alloc.bits.tag, tag)val can_read_cmd = rnd.nextBoolean()poke(c.io.cmd_completed.ready, can_read_cmd)if (rnd.nextBoolean() || cmdIdsAllocated.size == 0) {poke(c.io.request_returned.valid, false)} else {val cmd_buf_id = rnd.nextInt(cmdIdsAllocated.size)val id = cmdIdsAllocated(cmd_buf_id).idval requestsSent = cmdIdsAllocated(cmd_buf_id).requestsSentif (requestsSent < c.nRequests) {poke(c.io.request_returned.valid, true)poke(c.io.request_returned.bits.cmd_id, id)cmdIdsAllocated(cmd_buf_id) = cmdIdsAllocated(cmd_buf_id).copy(requestsSent=requestsSent+1)} else {poke(c.io.request_returned.valid, false)}}val alloc_fire = can_allocate && peek(c.io.alloc.ready) != 0if (alloc_fire) {cmdsToAllocate -= 1val cmd_id = peek(c.io.alloc.bits.cmd_id).toIntassert(!cmdIdsAllocated.exists(_.id == cmd_id), s"$cmd_id already allocated")cmdIdsAllocated += AllocatedCmd(cmd_id, tag, 0)}val cmd_completed_fire = can_read_cmd && peek(c.io.cmd_completed.valid) != 0if (cmd_completed_fire) {val cmd_id = peek(c.io.cmd_completed.bits.cmd_id).toIntval cmd_buf_id = cmdIdsAllocated.zipWithIndex.collectFirst { case (AllocatedCmd(id, _, _), i) if id == cmd_id => i }.getval tag = peek(c.io.cmd_completed.bits.tag).toIntif (cmdIdsAllocated(cmd_buf_id).tag != tag) {println(s"wrong tag, $tag, ${cmdIdsAllocated(cmd_buf_id).tag}")max_cycles = 0}assert(cmdIdsAllocated(cmd_buf_id).tag == tag, "tag is incorrect")assert(cmdIdsAllocated(cmd_buf_id).requestsSent == c.nRequests, "returned after wrong number of requests returned")cmdIdsAllocated.remove(cmd_buf_id)}step(1)max_cycles -= 1}assert(max_cycles > 0, "reached max_cycles")
}class DMACommandTrackerUnitTest extends ChiselFlatSpec {val testerArgs = Array("--backend-name", "treadle",// "--generate-vcd-output", "on","--target-dir", "test_run_dir/dmacommandtracker")behavior of "DMACommandTracker"it should "work" in {chisel3.iotesters.Driver.execute(testerArgs, () => new DMAReadCommandTracker(2, 16, UInt(29.W))) {c => new DMACommandTrackerTester(c)} should be (true)}
}

这段代码是用于测试 DMAReadCommandTracker 模块的功能和正确性。DMAReadCommandTracker 模块是一个用于跟踪 DMA 读取命令的状态的硬件模块,它可以分配和回收命令 id 和 tag,并在所有请求都返回后输出完成信号。

这段代码包含两个类,DMACommandTrackerTester 和 DMACommandTrackerUnitTest。DMACommandTrackerTester 类是一个用于对 DMAReadCommandTracker 模块进行输入输出操作和断言检查的测试类。

DMACommandTrackerUnitTest 类是一个用于运行 DMACommandTrackerTester 的测试类,它继承自 ChiselFlatSpec 类,并指定了一些测试参数,如后端名称,目标目录等。

这段代码的目的是验证 DMAReadCommandTracker 模块是否能正确地分配和回收命令 id 和 tag,并在所有请求都返回后输出完成信号。

  • DMACommandTrackerTester 类是一个继承自 PeekPokeTester 的测试器类,它接受一个 DMAReadCommandTracker 类型的参数 c。

    • AllocatedCmd 是一个 case class,它用于存储已分配命令的 id、tag 和 requestsSent,id是命令编号、tag是标签(记录版本类型等)、requestsSent记录命令的进度。
    • max_cycles 是一个整数变量,它表示最大的执行周期数,用于限制测试的时间。
    • cmdsToAllocate 是一个整数变量,它表示要分配的命令数量,初始值为 100。
    • cmdIdsAllocated 是一个 ArrayBuffer 类型的变量,它用于存储已分配命令的 AllocatedCmd 对象。
    • while 循环是测试的主要逻辑,它在 cmdsToAllocate 大于 0 或 cmdIdsAllocated 不为空,并且 max_cycles 大于 0 的条件下执行。循环中包含以下步骤:
      • 随机决定是否可以分配新的命令,并将结果赋值给 can_allocate 变量,然后将其 poke 给 c.io.alloc.valid 输入端口。
      • 随机生成一个 0 到 99 之间的整数作为 tag,并将其 poke 给 c.io.alloc.bits.tag 输入端口。
      • 随机决定是否可以读取已完成的命令,并将结果赋值给 can_read_cmd 变量,然后将其 poke 给 c.io.cmd_completed.ready 输入端口。
      • 如果随机决定不返回请求或 cmdIdsAllocated 为空,则将 false poke 给 c.io.request_returned.valid 输入端口;否则,从 cmdIdsAllocated 中随机选择一个已分配命令,获取其 id 和 requestsSent,如果 requestsSent 小于 c.nRequests,则将 true poke 给 c.io.request_returned.valid 输入端口,并将 id poke 给 c.io.request_returned.bits.cmd_id 输入端口,同时将 cmdIdsAllocated 中对应的 AllocatedCmd 对象的 requestsSent 增加 1;否则,将 false poke 给 c.io.request_returned.valid 输入端口。
      • 判断是否发生了 alloc_fire 事件,即 can_allocate 为 true 并且 c.io.alloc.ready 输出端口为 true。如果是,则将 cmdsToAllocate 减 1,并从 c.io.alloc.bits.cmd_id 输出端口读取分配的 cmd_id,断言 cmdIdsAllocated 中不存在相同的 id,并将新建的 AllocatedCmd 对象添加到 cmdIdsAllocated 中。
      • 判断是否发生了 cmd_completed_fire 事件,即 can_read_cmd 为 true 并且 c.io.cmd_completed.valid 输出端口为 true。如果是,则从 c.io.cmd_completed.bits.cmd_id 和 c.io.cmd_completed.bits.tag 输出端口读取完成的 cmd_id 和 tag,并在 cmdIdsAllocated 中找到对应的 AllocatedCmd 对象和索引。如果对象中的 tag 不等于输出端口中的 tag,则打印错误信息并将 max_cycles 设为 0;否则,断言对象中的 tag 等于输出端口中的 tag,并断言对象中的 requestsSent 等于 c.nRequests,然后从 cmdIdsAllocated 中移除该对象。
      • 调用 step(1) 方法执行一个时钟周期,并将 max_cycles 减 1。
    • 在 while 循环结束后,断言 max_cycles 大于 0,表示测试没有超时。
  • DMACommandTrackerUnitTest 类是一个继承自 ChiselFlatSpec 的单元测试类,它定义了一些变量和方法。

    • testerArgs 是一个字符串数组,它存储了一些测试参数,如后端名称、目标目录等。
    • behavior of “DMACommandTracker” 是一个字符串字面量,它表示要测试的类名。
    • it should “work” 是一个方法,它表示要测试的功能。方法中包含以下步骤:
      • 调用 chisel3.iotesters.Driver.execute 方法,传入 testerArgs 和一个匿名函数,该函数返回一个新建的 DMAReadCommandTracker 对象,其参数为 2、16 和 UInt(29.W)。
      • 在 execute 方法的第二个参数中,传入一个匿名函数,该函数接受一个 DMAReadCommandTracker 类型的参数 c,并返回一个新建的 DMACommandTrackerTester 对象,其参数为 c。
      • 在 execute 方法的返回值上调用 should be (true) 方法,断言测试结果为 true。

注释版:

package gemminiimport scala.collection.mutable.ArrayBufferimport chisel3._
import chisel3.iotesters.{ChiselFlatSpec, PeekPokeTester}//测试 DMAReadCommandTracker 模块的功能和正确性。
//DMAReadCommandTracker 模块是一个用于跟踪 DMA 读取命令的状态的硬件模块,它可以分配和回收命令 id 和 tag,并在所有请求都返回后输出完成信号。
//包含两个类,DMACommandTrackerTester 和 DMACommandTrackerUnitTest。
//DMACommandTrackerTester 类是一个用于对 DMAReadCommandTracker 模块进行输入输出和断言检查的测试类。
//DMACommandTrackerUnitTest 类是一个用于运行 DMACommandTrackerTester 的测试类
//这段代码的目的是验证 DMAReadCommandTracker 模块是否能正确地分配和回收命令 id 和 tag,并在所有请求都返回后输出完成信号。class DMACommandTrackerTester(c: DMAReadCommandTracker[UInt]) extends PeekPokeTester(c) {
//用于存储已分配命令的 id、tag 和 requestsSent,id是命令编号、tag是标签(记录版本类型等)、requestsSent记录命令的进度。case class AllocatedCmd(id: Int, tag: Int, requestsSent: Int)
//最大的执行周期数var max_cycles = 100000000
//要分配的命令数量,初始值为 100;cmdIdsAllocated存储已分配命令的 AllocatedCmd 对象var cmdsToAllocate = 100val cmdIdsAllocated: ArrayBuffer[AllocatedCmd] = ArrayBuffer() // TODO use a map instead
//循环条件:1.还有剩余的周期数可执行 2.待分配命令数不是0或者已分配命令不为空while ((cmdsToAllocate > 0 || cmdIdsAllocated.size > 0) && max_cycles > 0) {
//当还有命令可以分配的时候,随机决定是否可以分配新的命令,并将结果赋值给 can_allocate 变量,然后将其 poke 给 c.io.alloc.valid 输入端口。val can_allocate = cmdsToAllocate > 0 && rnd.nextBoolean()poke(c.io.alloc.valid, can_allocate)
//随机生成一个 0 到 99 之间的整数作为 tag,并将其 poke 给 c.io.alloc.bits.tag 输入端口。val tag = rnd.nextInt(100)poke(c.io.alloc.bits.tag, tag)
//随机决定是否可以读取已完成的命令,并将结果赋值给 can_read_cmd 变量,然后将其 poke 给 c.io.cmd_completed.ready 输入端口。
//当 can_read_cmd 为 true 时,表示允许读取已完成的命令,即表明模块已准备好接收命令完成的信号。当 can_read_cmd 为 false 时,表示不允许读取已完成的命令,即表明模块不准备接收命令完成的信号。val can_read_cmd = rnd.nextBoolean()poke(c.io.cmd_completed.ready, can_read_cmd)
//如果随机决定不返回请求或 cmdIdsAllocated 为空,则将 false poke 给 c.io.request_returned.valid 输入端口if (rnd.nextBoolean() || cmdIdsAllocated.size == 0) {poke(c.io.request_returned.valid, false)} else {
//从 cmdIdsAllocated 中随机选择一个已分配命令,获取其 id 和 requestsSentval cmd_buf_id = rnd.nextInt(cmdIdsAllocated.size)val id = cmdIdsAllocated(cmd_buf_id).idval requestsSent = cmdIdsAllocated(cmd_buf_id).requestsSent//nRequests 用于表示每个已分配的命令所需的请求次数。在这个上下文中,当已分配的命令的请求次数达到 nRequests 时,该命令将被认为是完成的。
//如果 requestsSent 小于 c.nRequests,则将 true poke 给 c.io.request_returned.valid 输入端口
//将 id poke 给 c.io.request_returned.bits.cmd_id 输入端口,同时将 cmdIdsAllocated 中对应的 AllocatedCmd 对象的 requestsSent 增加 1;否则,将 false poke 给 c.io.request_returned.valid 输入端口。//说白了就是判断这个命令是否完成了,然后作相应操作if (requestsSent < c.nRequests) {poke(c.io.request_returned.valid, true)poke(c.io.request_returned.bits.cmd_id, id)cmdIdsAllocated(cmd_buf_id) = cmdIdsAllocated(cmd_buf_id).copy(requestsSent=requestsSent+1)} else {poke(c.io.request_returned.valid, false)}}
//检查是否可以分配命令,(即 can_allocate 为 true 并且 c.io.alloc.ready 输出端口为 true)
//如果是,则将 cmdsToAllocate 减 1,并从 c.io.alloc.bits.cmd_id 输出端口读取分配的 cmd_id,断言 cmdIdsAllocated 中不存在相同的 id,并将新建的 AllocatedCmd 对象添加到 cmdIdsAllocated 中。val alloc_fire = can_allocate && peek(c.io.alloc.ready) != 0if (alloc_fire) {cmdsToAllocate -= 1val cmd_id = peek(c.io.alloc.bits.cmd_id).toIntassert(!cmdIdsAllocated.exists(_.id == cmd_id), s"$cmd_id already allocated")cmdIdsAllocated += AllocatedCmd(cmd_id, tag, 0)}
//检查是否可以读取完成的命令,(即 can_read_cmd 为 true 且 c.io.cmd_completed.valid 输出端口的值不为 0)
//如果是,则读取id和tag,并在 cmdIdsAllocated 中找到对应的 AllocatedCmd 对象和索引。
//如果原tag与输出端口的tag不同就报错,相同就删除这个命令val cmd_completed_fire = can_read_cmd && peek(c.io.cmd_completed.valid) != 0if (cmd_completed_fire) {val cmd_id = peek(c.io.cmd_completed.bits.cmd_id).toIntval cmd_buf_id = cmdIdsAllocated.zipWithIndex.collectFirst { case (AllocatedCmd(id, _, _), i) if id == cmd_id => i }.getval tag = peek(c.io.cmd_completed.bits.tag).toIntif (cmdIdsAllocated(cmd_buf_id).tag != tag) {println(s"wrong tag, $tag, ${cmdIdsAllocated(cmd_buf_id).tag}")max_cycles = 0}assert(cmdIdsAllocated(cmd_buf_id).tag == tag, "tag is incorrect")assert(cmdIdsAllocated(cmd_buf_id).requestsSent == c.nRequests, "returned after wrong number of requests returned")cmdIdsAllocated.remove(cmd_buf_id)}
//每次循环周期减少step(1)max_cycles -= 1}
//判断有没有超市assert(max_cycles > 0, "reached max_cycles")
}class DMACommandTrackerUnitTest extends ChiselFlatSpec {
//存取测试参数val testerArgs = Array("--backend-name", "treadle",// "--generate-vcd-output", "on","--target-dir", "test_run_dir/dmacommandtracker")
//表示要测试的是 DMACommandTracker 模块behavior of "DMACommandTracker"it should "work" in {chisel3.iotesters.Driver.execute(testerArgs, () => new DMAReadCommandTracker(2, 16, UInt(29.W))) {c => new DMACommandTrackerTester(c)} should be (true)//测试参数与断言测试结果}
}

相关文章:

Gemmini测试test文件chisel源码详解(一)

DMACommandTrackerTest.scala 源码如下&#xff1a; package gemminiimport scala.collection.mutable.ArrayBufferimport chisel3._ import chisel3.iotesters.{ChiselFlatSpec, PeekPokeTester}class DMACommandTrackerTester(c: DMAReadCommandTracker[UInt]) extends Pee…...

RabbitMQ中的手动应答和自动应答

当使用RabbitMQ来处理消息时&#xff0c;消息确认是一个重要的概念。RabbitMQ提供了两种不同的消息确认方式&#xff1a;自动应答&#xff08;Automatic Acknowledgment&#xff09;和手动应答&#xff08;Manual Acknowledgment&#xff09;。这两种方式适用于不同的应用场景&…...

【C语言】文件的操作与文件函数的使用(详细讲解)

前言&#xff1a;我们在学习C语言的时候会发现在编写一个程序的时候&#xff0c;数据是存在内存当中的&#xff0c;而当我们退出这个程序的时候会发现这个数据不复存在了&#xff0c;因此我们可以通过文件把数据记录下来&#xff0c;使用文件我们可以将数据直接存放在电脑的硬盘…...

ROS-PX4仿真笔记_1

offbord模式测试 rosrun offboard_pkg position stablelize模式 lqr控制器实验 roslaunch px4 fast_test.launch 无人机起飞1.5-2m sh mybot_gazebo.sh#roslaunch px4 fast_racing.launch & sleep 20; roslaunch ego_planner single_run_in_gazebo.launch & sleep 1…...

使用 Python 中的小波变换信号驾驭股票价格的波动

一、简介 股票上涨和下跌,创造出像海浪一样难以预测的模式和走势。然而,就像科学家通过了解下面的水流来预测波浪的运动一样,我们也可以使用类似的工具破译股票市场的一些模式。 通过利用小波变换的力量,我们深入表面,试图揭示驱动股价的深层原因。这段旅程不仅仅涉及数字…...

AndroidStudio模拟器,没有Google Play的就有ROOT权限

正确选择版本 测试 D:\>adb shell emulator64_x86_64:/ $ su emulator64_x86_64:/ #...

复选框 前端代码

表单中复选框选项 <el-form-item label="是否公开:" hidden="true"><input type="checkbox...

每日一练 | 网络工程师软考真题Day41

1、包过滤防火墙对通过防火墙的数据包进行检查&#xff0c;只有满足条件的数据包才能通过&#xff0c;对数据包的检查内容一般不包括 。 A&#xff0e;源地址 B&#xff0e;目的地址 C&#xff0e;协议 D&#xff0e;有效载荷 2、下面关于ARP木马的描述中&#xff0c;错误的…...

vue使用pinia存储数据并保持数据持久化

在Vue中使用Pinia存储数据并保持数据持久化&#xff0c;你可以遵循以下步骤&#xff1a; 安装Pinia&#xff1a;首先&#xff0c;你需要安装Pinia。可以通过npm或yarn来安装它。在终端中运行以下命令&#xff1a; npm install pinia# 或者使用yarn yarn add pinia创建Pinia St…...

k8s - Flannel

1.Flannel概念剖析 Flannel是 CoreOS 团队针对 Kubernetes 设计的一个覆盖网络&#xff08;Overlay Network&#xff09;工具&#xff0c;其目的在于帮助每一个使用 Kuberentes 的 CoreOS 主机拥有一个完整的子网。这次的分享内容将从Flannel的介绍、工作原理及安装和配置三方…...

服务器中了balckhoues勒索病毒怎么办?勒索病毒解密,数据恢复

近日&#xff0c;云天数据恢复中心发现&#xff0c;有多位用户的服务器中了一种名为balckhoues的勒索病毒&#xff0c;因为绝大多数用户是第一次遇到这种情况&#xff0c;所以对这种类型的勒索病毒并不是很了解。那接下来我们将对balckhoues勒索病毒做一个分析。 中毒特征 服务…...

react-pdf | Warning: TextLayer styles not found.

问题描述&#xff1a; 使用react-pdf展示pdf&#xff0c;但是报警告&#xff0c;Warning: TextLayer styles not found. 解决方法&#xff1a; <Pageloading{"加载中..."}renderAnnotationLayer{false}renderTextLayer{false}/> 添加属性如上&#xff0c;设…...

vue上传文件MD5加密

1.下载MD5依赖 npm install crypto-js 2.在utils文件夹中新增文件md5方法文件&#xff0c;文件名自定义&#xff08;fileMd5Sum.js&#xff09; import CryptoJs from crypto-js export default {// md5值计算fileMd5Sum(file) {let CryptoJS require("crypto-js"…...

vue2 .sync 修饰符

vue2 .sync 修饰符 **创建 工程&#xff1a; H:\java_work\java_springboot\vue_study ctrl按住不放 右键 悬着 powershell H:\java_work\java_springboot\js_study\Vue2_3入门到实战-配套资料\01-随堂代码素材\day04\准备代码\13-sync修饰符 vue --version vue create v-sy…...

使用Tensorrt的一般步骤

使用Tensorrt的一般步骤 TensorRT的使用包括两个阶段&#xff1a;build and deployment。 build&#xff1a;该阶段主要完成模型转换&#xff08;从caffe或TensorFlow到TensorRT&#xff09;&#xff0c;如下图所示&#xff0c;在模型转换时会完成前述优化过程中的层间融合&am…...

uniapp apple 苹果登录 离线本地打包

官方文档 uni-app官网 文档写的不全&#xff0c;没有写离线打包流程 加lib 签名里带 sign in with apple hbuilder开关 代码 测试代码&#xff0c;获取app里所有的provider uni.getProvider({service: oauth,success: function (res) {console.log(res.provider)uni.showT…...

【数据库】Sql Server数据迁移,处理自增字段赋值

给自己一个目标&#xff0c;然后坚持一段时间&#xff0c;总会有收获和感悟&#xff01; 在实际项目开发中&#xff0c;如果遇到高版本导入到低版本&#xff0c;或者低版本转高版本&#xff0c;那么就会出现版本不兼容无法导入&#xff0c;此时通过程序遍历创建表和添加数据方式…...

JOSEF约瑟 矿用一般型选择性漏电继电器 LXY2-660 Φ45 JKY1-660

系列型号&#xff1a; JY82A检漏继电器 JY82B检漏继电器 JY82-380/660检漏继电器 JY82-IV检漏继电器 JY82-2P检漏继电器 JY82-2/3检漏继电器 JJKY检漏继电器 JD型检漏继电器 JY82-IV;JY82J JY82-II;JY82-III JY82-1P;JY82-2PA;JY82-2PB JJB-380;JJB-380/660 JD-12…...

DHCP自动分配IP原理

DHCP自动分配IP原理 1.采用UDP通信方式 2.服务器IP&#xff1a;255.255.255.255&#xff1b; 服务器端口&#xff1a;67, 设备接收端口&#xff1a;68 3.设备向服务器发送DISCOVER信息 4.设备收到服务器回应&#xff0c;且解析正确 5.设备向服务器发送REQUEST请求消息 6.设备接…...

读书笔记-《ON JAVA 中文版》-摘要26[第二十三章 注解]

文章目录 第二十三章 注解1. 基本语法1.1 基本语法1.2 定义注解1.3 元注解 2. 编写注解处理器2.1 编写注解处理器2.2 注解元素2.3 默认值限制 3. 使用javac处理注解4. 基于注解的单元测试5. 本章小结 第二十三章 注解 注解&#xff08;也被称为元数据&#xff09;为我们在代码…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

spring Security对RBAC及其ABAC的支持使用

RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型&#xff0c;它将权限分配给角色&#xff0c;再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...