Bluespec SytemVerilog 握手协议接口转换

01、引言

由于接口控制信号上的差异,要实现Bluespec SystemVerilog(BSV)生成的代码和外部Verilog代码之间的正确交互是一件比较麻烦同时容易出错的事情。在BSV中, 模块之间的交互都是基于Action或ActionValue这两类method完成。下图展示了使用BSV设计的某一模块的接口定义及其实际生成的硬件端口。由图可见,除了被显式地定义为函数输入参数或返回类型的数据信号外,每个method都隐含着一对控制信号,即en和rdy。

其中,rdy信号指示该方法已经准备好被调用,而当外部模块调用该方法时会拉高对应的en信号。en-rdy控制信号和AXI总线中valid-ready信号的作用类似,这两对信号都保证了当通信双方都准备好时才能完成一拍数据的传输。虽然完成的功能相同,但这两对信号在具体的实现机制上仍存在一定差异:

首先,en-rdy和valid-ready并不是一一对应的关系。对于某个模块,en永远是输入信号,而rdy永远是输出信号。而在valid-ready握手协议中,master端输出valid接收ready,而slave端输出ready接收valid。因此,这两对信号有如下表所示的对应关系:

masterslave
validrdyen
readyenrdy

其次,是控制信号之间依赖关系的差异。在BSV中,method的en信号依赖于rdy信号,具体来说一个method只有在其准备好(rdy为高)时才能被调用。下图展示了这一依赖关系在硬件上的具体实现,即输入的en信号需要和输出的rdy信号相与后传递给下一级。而在AXI协议中,为了避免产生死锁(通信双方都等待对方准备好后再响应),其明确规定:master输出的valid信号不能依赖于ready信号,即不能等待slave侧准备好后再发起请求;相反,slave端输出的ready信号可以依赖于输入的valid,即可以等待master发起请求后再作响应。

在大部分使用Verilog实现的电路中,我们都会基于valid-ready握手协议实现模块之间的交互。如果在一个项目中,我们需要将BSV生成的代码和基于Verilog的设计进行交互,通常还需要实现一个转换模块,来处理valid-ready和en-rdy控制信号之间的交互。

除了控制信号的差异外,BSV生成的Verilog代码还存在如下问题:如果在BSV中将多个相关的输入/输出信号封装在一个结构体,那么在生成的Verilog接口中所有封装在一起的字段都会合并成单个信号。例如,在BSV中使用AXI-Stream总线时,为了方便信号传递,通常会将总线上的信号封装成一个结构体后在方法之间传递:

typedef struct {Bit#(TMul#(keepWidth, 8)) tData;Bit#(keepWidth) tKeep;Bit#(usrWidth) tUser;Bool tLast;
} AxiStream#(numeric type keepWidth, numeric type usrWidth) deriving(Bits);interface AxiStreamExample;interface Put#(AxiStream#(8, 1)) axiStreamSlave;interface Get#(AxiStream#(8, 1)) axiStreamMaster;
endinterface

而在生成的Verilog代码中,结构体里定义的所有字段都合并到了axiStreamSlave_put/axiStreamMaster_get信号里:

module mkAxiStreamExample(CLK,RST_N,axiStreamSlave_put,EN_axiStreamSlave_put,RDY_axiStreamSlave_put,EN_axiStreamMaster_get,axiStreamMaster_get,RDY_axiStreamMaster_get
);

如果我们要将上述代码与其他Verilog模块交互,需要添加一个额外的模块对生成的mkAxiStreamExample进行封装。该模块需要完成两件事:

1)将合并的信号解析成每个独立的信号,

2)将en-rdy转换为valid-ready握手协议。

以Master端信号的封装为例,具体的实现代码如下:

module mkAxiStreamExampleWrapper(input clk,input reset_n,output m_axis_tvalid,input  m_axis_tready,output m_axis_tlast,output m_axis_tuser,output [63:0] m_axis_tdata,output [ 7:0] m_axis_tkeep,
);mkAxiStreamExample axiStreamExampleInst (.CLK   (    clk),.RST_N (reset_n),.RDY_axiStreamMaster_get (m_axis_tvalid),.EN_axiStreamMaster_get  (m_axis_tvalid & m_axis_tready),.axiStreamMaster_get ({m_axis_tdata, m_axis_tkeep, m_axis_tuser, m_axis_tlast}));
endmodule

虽然上面展示的Verilog封装模块可以保证模块间正确的交互,但仍存在一些缺陷。首先,解析打包信号的方式与BSV中结构体的定义相关,如果结构的内容发生更改,封装模块解析出的结果就可能出错。其次,手动地处理en-rdy和valid-ready信号对之间的转换也容易出错。这些问题都降低了BSV项目的可维护性。

为了方便BSV和Verilog之间的交互,我们实现了blue-wrapper项目并提供了等同于上述Verilog封装的BSV实现,使得经过封装的BSV模块所生成的代码能够直接和其他Verilog模块进行交互。下文将介绍blue-wrapper的具体实现及其使用方式,主要包括三部分内容:

  • PipeOut/PipeIn接口的定义,对应代码实现见 src/SemiFifo.bsv
  • 基于PipeOut/PipeInGet/Put接口实现握手控制信号转换, 详细代码实现可见 src/BusConversion.bsv;
  • 控制信号转换的基础上,还需要对完成对数据信号的解析,blue-wrapper中分别提供了对AXI-Stream,AXI4-Lite和AXI4-Full等协议的支持;

下文将结合实际代码分别介绍这三部分的具体实现。

02、PipeOut/PipeIn接口

在基于valid-ready控制信号对的数据交互场景下,交互双方可分为Master和Slave。其中,Master端发起数据传输,可对应BSV中常用的Get接口,而Slave负责接收数据,因此可以对应BSV中的Put接口。除了Get/Put外,为了方便实现握手控制信号的转换,blue-wrapper中还额外定义了PipeOut/PipeIn接口,这两个接口分别封装了FIFOF接口出队侧(deq)和入队(enq)侧的方法,具体定义如下:

interface PipeIn#(type dType);method Action enq(dType data);method Bool   notFull();
endinterfaceinterface PipeOut#(type dType);method dType  first();method Action deq();method Bool   notEmpty();
endinterface

从实现功能的角度上看,PipeOut/PipeInGet/Put接口类似,都可分别实现数据的输出/输入。但对于Get/Put接口,其get/put方法所隐含的en-rdy控制信号在BSV中是无法访问的。而对于PipeOut/PipeIn接口,其将deq/enq方法对应的rdy信号分别通过notEmpty/notFull方法暴露出来,使得我们可以直接在BSV中对其进行访问,而这一点将极大地方便握手控制信号的转换。

03、握手控制信号转换

显式定义valid-ready信号

实现接口转换的第一步需要在interface中定义valid和ready信号对应的method,一方面使得生成的Verilog代码直接包含valid-ready信号对,另一方面方便我们在BSV中操纵这两个信号实现握手协议转换。在BSV中,一个方法的返回值对应Verilog的输出端口,而方法的输入参数对应输入端口,基于该原则,valid-ready协议的Master/Slave侧接口的BSV定义如下:

(* always_ready, always_enabled )
interface RawBusMaster#(type dType);( result = "data" ) method dType  data;( result = "valid"*) method Bool   valid;(* prefix = "" ) method Action ready(( port = "ready" ) Bool rdy);
endinterface( always_ready, always_enabled )
interface RawBusSlave#(type dType);( prefix = "" ) method Action validData(( port = "valid"   ) Bool valid,( port = "data"    ) dType data);( result = "ready" *) method Bool ready;
endinterface

上述代码中,编译属性“always_ready”和“always_enabled”消除了每个method隐含的en-rdy控制信号对。同时,我们可以通过设置输出method的“result”属性和每个输入参数的“port”属性来指定生成的Verilog中每个端口的具体名称。

en-rdy和valid-ready之间的转换

在定义好包含valid-ready控制信号的interface后,下一步需要完成en-rdy到valid-ready握手控制信号的转换。blue-wrapper项目分别提供了两种不同的转换思路:

1. 将需要封装的PipeOut/PipeIn接口作为参数传入转换模块供valid/ready信号对应的method调用;

2. 将RawBusMaster/Slave接口分别封装成PipeIn/PipeOut接口供其他BSV模块调用;

基于第一种思路实现的转换模块包括: mkPipeOutToRawBusMaster/mkPipeInToRawBusSlave,以及mkGetToRawBusMaster和mkPutToRawBusSlave。以mkPipeOutToRawBusMaster为例,该模块接收PipeOut接口作为输入参数,并返回RawBusMaster接口,其中各个method的实现思路和具体代码如下:

  • valid: 对于Master端,其valid信号对应BSV中的rdy信号,而PipeOut接口通过notEmpty方法暴露出了deq方法对应的rdy,因此valid方法直接返回notEmpty的值;
  • data: 对应PipeOut接口的first方法;
  • ready: 作为方法输入参数传递的ready信号对应BSV中的en控制信号,该值为真时需要调用PipeOut接口的deq方法。由于在BSV中调用任意method,编译器都会自动保证上文提到的en-rdy的依赖关系,因此在调用deq方法时不需要额外检查其rdy信号来保证握手成功。
module mkPipeOutToRawBusMaster#(PipeOut#(dType) pipe
)(RawBusMaster#(dType));RWire#(dType) dataW <- mkRWire;Wire#(Bool) readyW <- mkBypassWire;rule passWire if (pipe.notEmpty);dataW.wset(pipe.first);endrulerule passReady if (readyW);pipe.deq;endrulemethod Bool valid = pipe.notEmpty;method dType data = fromMaybe(?, dataW.wget);method Action ready(Bool rdy);readyW <= rdy;endmethod
endmodule

对于PipeIn到RawBusSlave的转换,其实现的原理和Master端类似,具体代码如下:

module mkPipeInToRawBusSlave#(PipeIn#(dType) pipe
)(RawBusSlave#(dType));Wire#(Bool)  validW <- mkBypassWire;Wire#(dType) dataW <- mkBypassWire;rule passData if (validW);pipe.enq(dataW);endrulemethod Action validData(Bool valid, dType data);validW <= valid;dataW <= data;endmethodmethod Bool ready = pipe.notFull;
endmodule

对于Get/Put接口,由于在BSV中无法直接访问get/put方法的rdy信号,直接进行转换无法提取出master输出的valid信号以及slave输出的ready信号。因此,在blue-wrapper的实现中我们通过添加一个额外的FIFOF模块作为媒介,将Get/Put接口转换成PipeOut/PipeIn接口后,调用上面展示的两个模块实现控制信号的转换,以Get接口为例,具体的代码实现如下:

module mkGetToRawBusMaster#(Get#(dType) get
)(RawBusMaster#(dType));FIFOF#(dType) fifo <- mkFIFOF;mkConnection(get, toPut(fifo));let rawBus <- mkPipeOutToRawBusMaster(convertFifoToPipeOut(fifo));return rawBus;
endmodule

第二种实现思路对应代码中的:mkRawBusMasterToPut/mkRawBusMasterToGet,以及mkRawBusMasterToPipeIn/mkRawBusMasterToPipeOut四个模块。这种转换方式分别用PipeIn/PipeOutPut/Get接口封装RawBusMaster/RawBusSlave接口对于其他BSV模块,可以通过PipeIn/Put接口将数据传入转换模块然后从RawBusMaster发送出去,同时可以通过PipeOut/Get接口获取从RawBusSlave上接收到的数据。这种实现方式和BSV提供的BVI接口类似。以master侧为例,具体的转换实现如下:

首先,我们需要定义RawBusMasterToPipeIn接口,其由两个子接口RawBusMasterPipeIn组成,其中PipeIn用于封装RawBusMaster使其可供其他BSV模块调用。

对于RawBusMaster接口,其实现代码主要是在进行信号的传递, 从validData中取出valid和data方法的返回值,并将ready方法的输入参数传递给readyW

对于PipeIn接口, notFull方法返回readyW的值,enq方法将传入的参数写入validData。同时为了保证握手成功,enq方法需要被readyW所守卫(guarded), 即当输入的ready信号为高时,才可调用enq方法传入数据。

interface RawBusMasterToPipeIn#(type dType);interface RawBusMaster#(dType) rawBus;interface PipeIn#(dType) pipe;
endinterfacemodule mkRawBusMasterToPipeIn(RawBusMasterToPipeIn#(dType));RWire#(dType) validData <- mkRWire;Wire#(Bool) readyW <- mkBypassWire;interface RawBusMaster rawBus;method Bool valid = isValid(validData.wget);method dType data = fromMaybe(?, validData.wget);method Action ready(Bool rdy);readyW <= rdy;endmethodendinterfaceinterface PipeIn pipe;method Bool notFull = readyW;method Action enq(dType data) if (readyW);validData.wset(data);endmethodendinterface
endmodule

对于Get/Put接口,也可以使用上述方法对RawBusSlave/RawBusMaster接口进行封装,其实现的关键点都是要为get和put方法设置正确的守卫信号以保证握手成功.

死锁问题

为了避免master和slave之间互相等待而产生死锁,AXI文档中规定master不能等待slave侧拉高ready后再输出有效的valid和data,但允许slave侧在master拉高valid之后再置ready为高。在BSV中对于每个method,en只有在rdy信号拉高后才能拉高。由于en-rdy和valid-ready不同的依赖关系,在交互的过程中就有可能导致双方产生死锁。下文将主要针对上面提到的两种封装方法,分析其是否会引入死锁问题。

  • 第一种封装方式相当于是在转换模块中调用传入的PipeOut/PipeIn接口的方法。在BSV中调用任何方法,编译器都会自动地为en添加对于rdy的依赖,具体的en-rdy和valid-ready间的交互可以由下图所示。其中,en-rdy之间的依赖关系如红色虚线所示。当Slave侧为Verilog实现时,valid和ready之间可能存在如黑色虚线所示的依赖关系。由图可知,这两种依赖关系同向因此不会产生死锁。

  • 第二种封装方式类似于BSV提供的BVI接口,其将Verilog信号封装成BSV中的method供其他模块调用。同样的,对于这些method,BSV会给en信号添加对rdy的依赖,如下图红色虚线所示。而基于Verilog实现的Slave端口,其valid-ready之间可能存在如黑色虚线所示的依赖关系。由图可见,en-rdy和valid-ready之间正好形成了一个死锁环路,即master端等待ready拉高后输出有效的valid,而slave等待master输出有效valid后再拉高ready。因此,在使用mkRawBusMasterToPipeOut转换模块时需要保证所对接的slave侧Verilog实现中不存在ready对valid的依赖。

04、信号解析

完成控制信号的转换后,我们已经实现了可生成valid-ready控制信号的RawBusMaster#(dType)RawBusSlave#(dType)接口但是,如果dType是用户定义的struct结构体,则生成的Verilog会将struct中的所有字段打包到一个信号中。因此,我们仍然需要在BSV中将结构体的每个字段解析为单独的信号,以生成直接可用的Verilog代码。blue-wrapper分别提供了针对AXI-Stream, AXI4-Lite以及AXI4-Full三种总线协议的信号解析实现。以Master端的AXI-Stream接口为例,其信号解析代码如下:

(*always_ready, always_enabled*)
interface RawAxiStreamMaster#(numeric type dataWidth, numeric type usrWidth);(* result = "tvalid" *) method Bool tValid;(* result = "tdata"  *) method Bit#(dataWidth) tData;(* result = "tkeep"  *) method Bit#(keepWidth) tKeep;(* result = "tlast"  *) method Bool tLast;(* result = "tuser"  *) method Bit#(usrWidth) tUser;(* always_enabled, prefix = "" *) method Action tReady((* port="tready" *) Bool ready);
endinterfacemodule mkPipeOutToRawAxiStreamMaster#(PipeOut#(AxiStream#(dataWidth, usrWidth)) pipe
)(RawAxiStreamMaster#(dataWidth, usrWidth));let rawBus <- mkPipeOutToRawBusMaster(pipe);return convertRawBusToRawAxiStreamMaster(rawBus);interface RawAxiStreamMaster;method Bool tValid = rawBus.valid;method Bit#(dataWidth) tData = rawBus.data.tData;method Bit#(keepWidth) tKeep = rawBus.data.tKeep;method Bool tLast = rawBus.data.tLast;method Bit#(usrWidth) tUser = rawBus.data.tUser;method Action tReady(Bool rdy);rawBus.ready(rdy);endmethodendinterface
endmodule

除了使用blue-wrapper中提供的三种常用总线接口的转换模块外,用户也可以仿照上述代码为自定义的接口实现对应的转换模块,具体的实现步骤如下:

  • 首先,需要实现自定义Verilog接口对应的BSV接口。其中,每个输出信号都需要独立定义成一个method,每个输入信号都需定义成Action方法的一个输入参数;
  • 使用使用上文的介绍的握手控制信号转换模块将Get/PutPipeOut/PipeIn转换成RawBusMaster/RawBusSlave;
  • 在得到RawBusMaster/RawBusSlave后将结构体中的字段和对应的method相连。

05、总结

对于BSV生成的硬件代码,其接口通常是基于en-rdy控制信号进行交互,而使用Verilog设计时,我们通常采用valid-ready信号对实现模块之间的交互。由于控制信号上的差异,将BSV生成的代码和Verilog设计进行交互通常需要额外的转换模块。针对该问题,blue-wrapper项目为BSV代码实现了相应的封装模块,使得封装后生成的Verilog代码能够直接和外部的Verilog代码进行交互。本文主要介绍了blue-wrapper背后的实现原理,具体包括: 定义PipeOut/PipeIn接口以提取出rdy信号;两种不同的握手控制信号转换的思路;以及解析struct结构体为每个字段生成独立的信号等三部分内容。

06、相关链接

Flute:

https://github.com/bluespec/Flute/tree/master/src_Testbench/Fabrics/AXI4_Lite

Blue-AXI:

https://github.com/esa-tu-darmstadt/BlueAXI

bsc-contrib: 

https://github.com/B-Lang-org/bsc-contrib/tree/main

欢迎大家关注和支持blue-crc项目,GitHub仓库地址:

https://github.com/datenlord/blue-crc

07、往期推荐

基于BSV的高性能并行CRC硬件电路生成器

达坦科技(DatenLord)专注下一代云计算——“天空计算”的基础设施技术,致力于拓宽云计算的边界。达坦科技打造的新一代开源跨云存储平台DatenLord,通过软硬件深度融合的方式打通云间壁垒,实现数据高效跨云访问,建立海量异地、异构数据的统一存储访问机制,为云上应用提供高性能安全存储支持。以满足不同行业客户对海量数据跨云、跨数据中心高性能访问的需求。

公众号:达坦科技DatenLord

DatenLord官网

https://datenlord.github.io/zh-cn/

知乎账号:

达坦科技DatenLord - 知乎

B站

https://space.bilibili.com/2017027518

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/144993.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

8.2 Jmeter if控制器使用

前提&#xff1a;jmeter脚本需要用到if控制器&#xff0c;if判断如果查询不到&#xff0c;则去新增。 1、添加if控制器 线程组-->逻辑控制器-->如果(if)控制器 1&#xff09;、Expression (must evaluate to true or false) &#xff1a;表达式&#xff08;值必须是tru…

数据结构算法--6 希尔排序和计数排序

希尔排序 希尔排序与插入排序原理相同&#xff0c;希尔排序是一种分组插入排序算法 > 首先取一个整数d1n/2&#xff0c;将元素分为d1个组&#xff0c;每组相邻两元素之间距离为d1&#xff0c;在各组内之间插入排序。 > 取第二个整数d2n/2&#xff0c;重复上述分组排序…

HTML——列表,表格,表单内容的讲解

文章目录 一、列表1.1无序&#xff08;unorder&#xff09;列表1.2 有序&#xff08;order&#xff09;列表1.3 定义列表 二、表格**2.1 基本的表格标签2.2 演示 三、表单3.1 form元素3.2 input元素3.2.1 单选按钮 3.3 selcet元素 基础部分点击&#xff1a; web基础 一、列表 …

华为云云耀云服务器L实例评测|华为云云耀云服务器L实例CentOS的存储和备份策略

1 华为云云耀云服务器L实例介绍 华为云云耀云服务器L实例是华为云计算服务中的一种虚拟云服务器&#xff0c;它提供了强大的计算资源&#xff0c;可以在云端运行各种应用程序和服务。 华为云服务器提供了多种实例类型&#xff0c;包括通用型、计算优化型、内存优化型等&#…

时序预测 | MATLAB实现POA-CNN-GRU鹈鹕算法优化卷积门控循环单元时间序列预测

时序预测 | MATLAB实现POA-CNN-GRU鹈鹕算法优化卷积门控循环单元时间序列预测 目录 时序预测 | MATLAB实现POA-CNN-GRU鹈鹕算法优化卷积门控循环单元时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现POA-CNN-GRU鹈鹕算法优化卷积门控循环单元时间序…

Flutter笔记:手写一个简单的画板工具

Flutter笔记 手写一个简单的画板工具 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/133418742 目 录 1…

华为智能企业上网行为管理安全解决方案(2)

本文承接&#xff1a; https://blog.csdn.net/qq_37633855/article/details/133339254?spm1001.2014.3001.5501 重点讲解华为智能企业上网行为管理安全解决方案的部署流程。 华为智能企业上网行为管理安全解决方案&#xff08;2&#xff09; 课程地址方案部署整体流程组网规划…

R语言进行孟德尔随机化+meta分析(2)----基于R和stata

目前不少文章用到了孟德尔随机化meta分析&#xff0c;在上一章咱们简单介绍了一下meta分析的基础知识。咱们今天来介绍一篇11分文章&#xff0c;由文章看看孟德尔随机化meta分析如何进行&#xff0c;文章的题目是&#xff1a;Appraising the causal role of smoking in multipl…

No165.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

AIGC(生成式AI)试用 7 -- 桌面小程序

生成式AI&#xff0c;别人用来写作&#xff0c;我先用来写个桌面小程序。 桌面小程序&#xff1a;计算器 需求 Python开发图形界面&#xff0c;标题&#xff1a;计算器 - * / 基本运算计算范围&#xff1a;-999999999 ~ 999999999** 乘方计算&#xff08;例&#xff0c;2*…

NX 1988 如何将组件转为部件

打开组件 文件-导出-部件 指定部件名为1206&#xff0c;类选择&#xff1a;所有要导出的部件 选择完全加载 完成

【从入门到起飞】JavaSE—Stream流

&#x1f38a;专栏【JavaSE】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 &#x1f970;欢迎并且感谢大家指出我的问题 文章目录 &#x1f354;Stream流的作用&#x1f354;Stream流的使用步骤&#x1f384;获取Strea…

Go-Ldap-Admin | openLDAP 同步钉钉、企业微信、飞书组织架构实践和部分小坑

目录 一、Docker-compose快速拉起demo测试环境 二、原生部署流程 安装MySQL&#xff1a;5.7数据库 安装openLDAP 修改域名&#xff0c;新增con.ldif 创建一个组织 安装OpenResty 下载后端 下载前端 部署后端 部署前端 三、管理动态字段 钉钉 企业微信 飞书 四、…

内存函数(memcpy、memmove、memset、memcmp)你真的懂了吗?

&#x1f493;博客主页&#xff1a;江池俊的博客⏩收录专栏&#xff1a;C语言进阶之路&#x1f449;专栏推荐&#xff1a;✅C语言初阶之路 ✅数据结构探索&#x1f4bb;代码仓库&#xff1a;江池俊的代码仓库&#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐ 文…

26663-2011 大型液压安全联轴器 课堂随笔

声明 本文是学习GB-T 26663-2011 大型液压安全联轴器. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了大型液压安全联轴器的分类、技术要求、试验方法及检验规则等。 本标准适用于联接两同轴线的传动轴系&#xff0c;可起到限制…

分布式事务-TCC案例分析流程图

防止cancel方法在最后执行出现问题&#xff0c;用户收到提示已经退款成功但是由于cancel过慢或者出现问题&#xff08;虽然最后会重试成功但是用户体验很差&#xff09;&#xff0c;可以做以下的业务sql模型优化(增加一个冻结金额)。

消息队列实现进程间通信

write.c #include<myhead.h>typedef struct {long msgtype; //消息类型char data[1024]; //消息正文 }Msg_s;#define SIZE sizeof(Msg_s)-sizeof(long) //消息正文的大小int main(int argc, const char *argv[]) {key_t key; //定义一个键值if((key ftok("./&q…

基于springboot的洗衣店订单管理系统

目录 前言 一、技术栈 二、系统功能介绍 顾客信息管理 店家信息管理 店铺信息管理 洗衣信息管理 预约功能 洗衣信息 交流区 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息互联网信息的飞速发展&#xff0c;无纸化作业变成了一种趋势&#x…

红队打靶:THE PLANETS: MERCURY打靶思路详解(vulnhub)

目录 写在开头 第一步&#xff1a;主机发现和端口扫描 第二步&#xff1a;Web渗透 第三步&#xff1a;获取初步立足点并搜集信息 第四步&#xff1a;软连接劫持sudo提权 总结与思考 写在开头 本篇博客在自己的理解之上根据大佬红队笔记的视频进行打靶&#xff0c;详述了…

【HTML】表格行和列的合并

概述 当我们需要在 HTML 表格中展示复杂的数据时&#xff0c;行和列的合并可以帮助我们实现更灵活的布局和结构。通过合并行和列&#xff0c;我们可以创建具有更多层次和结构的表格&#xff0c;使数据更易于理解和分析。 在 HTML 表格中&#xff0c;我们可以使用 rowspan 和 …