Bluespec SytemVerilog 握手协议接口转换

news2024/11/29 1:53:24

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();
endinterface

interface 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);
    endrule

    rule passReady if (readyW);
        pipe.deq;
    endrule

    method 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);
    endrule

    method Action validData(Bool valid, dType data);
        validW <= valid;
        dataW <= data;
    endmethod
    method 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;
endinterface

module 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;
        endmethod
    endinterface

    interface PipeIn pipe;
        method Bool notFull = readyW;
        method Action enq(dType data) if (readyW);
            validData.wset(data);
        endmethod
    endinterface
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);
endinterface

module 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);
        endmethod
    endinterface
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.coloradmin.cn/o/1052314.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

综合应用QGIS软件,实现商场选址分析

一、实验要求 ①离城市主要交通道路50米内&#xff0c;保证商场交通的便利性。 ②在居民区100米内&#xff0c;便于居民步行到商场。 ③距离停车场100米内&#xff0c;便于顾客停车。 ④距离其他商场500米范围之外&#xff0c;减少竞争压力。 二、实验数据 ①城市地区主要…

机器学习算法基础--层次聚类法

文章目录 1.层次聚类法原理简介2.层次聚类法基础算法演示2.1.Single-linkage的计算方法演示2.2.Complete-linkage的计算方法演示2.3.Group-average的计算方法演示 3.层次聚类法拓展算法介绍3.1.质心法原理介绍3.2.基于中点的质心法3.3.Ward方法 4.层次聚类法应用实战4.1.层次聚…

Java21 新特性

文章目录 1. 概述2. JDK21 安装与配置3. 新特性3.1 switch模式匹配3.2 字符串模板3.3 顺序集合3.4 记录模式&#xff08;Record Patterns&#xff09;3.5 未命名类和实例的main方法&#xff08;预览版&#xff09;3.6 虚拟线程 1. 概述 2023年9月19日 &#xff0c;Oracle 发布了…

【Linux】完美解决ubuntu18.04下vi不能使用方向键和退格键

今天在刚安装完ubuntu18.04&#xff0c;发现在使用vi命令配置文件时使用方向键并不能移动光标&#xff0c;而是出现一堆奇怪的英文字母&#xff0c;使用退格键也不能正常地删除内容&#xff0c;用惯了CentOS的我已经感觉到ubuntu没有centos用着丝滑&#xff0c;但是没办法&…

C++ -- 学习系列 std::deque 的原理与使用

一 deque 是什么? std::deque 是 c 一种序列式容器&#xff0c;其与 vector 类似&#xff0c;其底层内存都是连续的&#xff0c;不同的地方在于&#xff0c; vector 是一端开口&#xff0c;在一端放入数据与扩充空间&#xff0c;而 deque 是双端均开口&#xff0c;都可以放…

lv5 嵌入式开发-10 信号机制(下)

目录 1 信号集、信号的阻塞 2 信号集操作函数 2.1 自定义信号集 2.2 清空信号集 2.3 全部置1 2.4 将一个信号添加到集合中 2.5 将一个信号从集合中移除 2.6 判断一个信号是否在集合中 2.7 设定对信号集内的信号的处理方式(阻塞或不阻塞) 2.8 使进程挂起&#xff08;…

NLP 01(介绍)

一、NLP 自然语言处理 (Natural Language rrocessing,简称NLP) 是计算机科学与语言学中关注于计算机与人类语言间转换的领域。 1.1 发展 规则&#xff1a;基于语法 自然语言处理的应用场景: 语音助手 机器翻译 搜索引擎 智能问答

Windows下安装MySQL8详细教程

Windows下安装MySQL8详细教程 因为需要在Windows下安装MySQL8的数据库&#xff0c;做一个临时数据库环境。 1.准备软件 使用社区版本&#xff0c;下载地址如下&#xff1a; https://dev.mysql.com/downloads/mysql/ 使用8.0.16版本&#xff0c;需要在归档中查找 选择版本&a…

pysimpleGui 使用之sg.SaveAs使用

SaveAs与FileBrowse使用一样需要给指定target参数&#xff0c;保存路径 layout [ [ sg.FileBrowse( button_text“请选择单个文件”, # 按钮文本 target“single_path”, # 把选择后的路径保存到key为input_path的对象 # file_types((“All Files”, “.”),), # 默认筛选全部…

Python+Yolov8路面桥梁墙体裂缝识别

程序示例精选 PythonYolov8路面桥梁墙体裂缝识别 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《PythonYolov8路面桥梁墙体裂缝识别》编写代码&#xff0c;代码整洁&#xff0c;规则&#…

如何应用MBTI职业性格测试来做职业规划

想要有一个不错的职业发展&#xff0c;需要做好职业规划。通常来说&#xff0c;职业规划可以分为三个组成&#xff0c;即定位、目标和路径。应用MBTI职业性格测试&#xff0c;可以对上述三个组成有更清晰的认识&#xff0c;帮助人们完成适合自己的职业规划。 职业性格和职业定…

Pytorch之ResNet图像分类

&#x1f482; 个人主页:风间琉璃&#x1f91f; 版权: 本文由【风间琉璃】原创、在CSDN首发、需要转载请联系博主&#x1f4ac; 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)和订阅专栏哦 目录 前言 一、ResNet网络结构 1.residual结构 2.BN(Batch Normalization)层…

反射知识点学习

文章目录 1. Java 反射机制原理示意图1.1 反射相关的主要类1.2 反射的优点和缺点1.3 反射调用优化-关闭访问检查 2. Class 类2.1 基本介绍2.2 Class类的常用方法2.3 获取 Class 类对象 3. 哪些类型有 Class 对象4. 类加载4.1 基本说明4.2 类加载时机4.3 类加载过程图4.4 类加载…

国庆作业1

使用消息队列实现进程之间的通信 代码 write.c #include <myhead.h> //消息结构体 typedef struct {long msgtype; //消息类型char data[1024]; //消息正文 }Msg_ds;#define SIZE sizeof(Msg_ds)-sizeof(long) //正文大小 int main(int argc, cons…

算法-位运算-只出现一次的数字 II

算法-位运算-只出现一次的数字 II 1 题目概述 1.1 题目出处 https://leetcode.cn/problems/bitwise-and-of-numbers-range/description/?envTypestudy-plan-v2&envIdtop-interview-150 1.2 题目描述 2 逐个按位与运算 2.1 思路 最简单的就是直接挨个做与运算&#x…

transformers简介

目录 1、前言 2、网络结构 &#xff08;1&#xff09;、Transformers的总体架构可以分为四部分 &#xff08;2&#xff09;、输入文本包含 &#xff08;3&#xff09;、输出部分包含 &#xff08;4&#xff09;、编码器部分 &#xff08;5&#xff09;、解码器部分 1、前…

dbeaver连接国产数据库

dbeaver是常用的数据库连接工具。但是在连接一些国产的数据库时&#xff0c;因为没有可选的驱动&#xff0c;所以需要我们先设置驱动&#xff0c;在连接。以下是一个连接highgo例子。 首先先新增一个驱动&#xff1a; 在页面的菜单栏&#xff0c;选择 数据库 ->驱动管理器…

SpringBoot整合阿里云OSS文件存储解决方案

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;啥技术都喜欢捣鼓捣鼓&#xff0c;喜欢分享技术、经验、生活。 &#x1f60e;人生感悟&#xff1a;尝尽人生百味&#xff0c;方知世间冷暖。 &#x1f4d6;所属专栏&#xff1a;Sp…

【AI视野·今日Sound 声学论文速览 第十五期】Fri, 29 Sep 2023

AI视野今日CS.Sound 声学论文速览 Fri, 29 Sep 2023 Totally 1 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers Audio-Visual Speaker Verification via Joint Cross-Attention Authors R. Gnana Praveen, Jahangir Alam使用语音信号进行了说话人验证的…

Web开发-新建Spring Boot项目

目录 Spring Boot 与 Web开发Spring Boot 与 MavenJava 环境搭建下载JDK下载xmapp下载navicat for mysql下载Eclipse配置tomcat配置maven 新建Spring Boot项目 Spring Boot 与 Web开发 Spring Boot 是一种用于简化 Spring 应用程序开发、部署和运行的框架&#xff0c;而 Web 开…