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

深入浅出CRC校验:从数学原理到单周期硬件实现 (4)硬件实现代码

终极性能:深度揭秘单周期CRC32的硬件实现

告别逐位计算的缓慢时代,迎接单周期完成的性能飞跃。本文将彻底揭示如何用纯组合逻辑实现每个时钟周期处理32位数据的CRC计算,并分享经过实战验证的Verilog代码。

前言:突破串行计算的性能壁垒

在上一篇文章中,我们看到了串行CRC实现的局限性——每个时钟周期只能处理1位数据,这根本无法满足现代高速接口的需求。现在,我们将解决这个核心问题:如何将多个时钟周期的迭代计算压缩到单个时钟周期内完成?

并行化原理:展开循环的数学艺术

从串行到并行的思维转变

串行LFSR的状态转移方程可以表示为:

S_{n+1} = f(S_n, d_n)

其中S是状态寄存器,d是输入数据位。

对于8位并行处理,我们需要的是:

text

S_{n+8} = f⁸(S_n, d_n, d_{n+1}, ..., d_{n+7})

我们需要找到一个函数F,能够直接计算8个时钟周期后的状态。

核心数学原理:线性系统的 superposition 特性

CRC计算是一个 线性系统 ,这意味着:

  1. 可加性 :f(A + B) = f(A) + f(B)
  2. 齐次性 :f(k × A) = k × f(A)

这种线性特性让我们能够将输入数据的影响分解开来单独处理,然后再组合起来。

推导步骤详解

步骤1:分析单个输入位的影响

首先考虑只有一个输入位为1,其他都为0的情况。对于8位输入,我们需要分析256种情况(2⁸),但由于线性特性,实际上只需要分析每个位单独为1的情况。

对于输入字节的第i位为1,计算经过8个时钟周期后对状态寄存器的影响,得到一个32位的掩码M_i。

步骤2:构建影响矩阵

将每个输入位的影响组织成一个32×8的矩阵A,其中每一列A[:,i]对应第i位输入为1时对32位状态寄存器的影响。

步骤3:组合所有输入影响

由于线性特性,任意输入字节的影响可以表示为:

text

ΔS = A × d

其中d是输入字节的各位,乘法是模2乘(即与操作),加法是模2加(即异或操作)。

步骤4:计算最终状态

8个周期后的状态为:

S_{n+8} = B × S_n + A × d

其中B是状态转移矩阵,描述初始状态经过8个空移位后的影响。

实战推导:CRC32单周期实现的完整过程

生成多项式选择

我们使用标准的CRC32生成多项式:

g(x) = x³² + x²⁶ + x²³ + x²² + x¹⁶ + x¹² + x¹¹ + x¹⁰ + x⁸ + x⁷ + x⁵ + x⁴ + x² + x + 1

二进制表示为:1 00000100 11000001 00011101 10110111
十六进制表示为:0x04C11DB7

Python推导工具原理

利用LFSR实现CRC32的基本原理,逐个按每bit计算CRC32的值,直到完成一个字节。

	$crc_31 = $crc_31_shft;$crc_30 = $crc_30_shft;$crc_29 = $crc_29_shft;$crc_28 = $crc_28_shft;$crc_27 = $crc_27_shft;$crc_26 = $crc_26_shft."^"."$p";$crc_25 = $crc_25_shft;$crc_24 = $crc_24_shft;$crc_23 = $crc_23_shft."^"."$p";$crc_22 = $crc_22_shft."^"."$p";$crc_21 = $crc_21_shft;$crc_20 = $crc_20_shft;$crc_19 = $crc_19_shft;$crc_18 = $crc_18_shft;$crc_17 = $crc_17_shft;$crc_16 = $crc_16_shft."^"."$p";$crc_15 =	$crc_15_shft; 	 	 $crc_14 = $crc_14_shft;$crc_13 = $crc_13_shft;$crc_12 = $crc_12_shft."^"."$p";$crc_11 = $crc_11_shft."^"."$p";$crc_10 = $crc_10_shft."^"."$p";$crc_9 =  $crc_9_shft ;$crc_8 =  $crc_8_shft."^"."$p" ;$crc_7 =  $crc_7_shft."^"."$p" ;$crc_6 =  $crc_6_shft ;$crc_5 =  $crc_5_shft."^"."$p" ;$crc_4 =  $crc_4_shft."^"."$p" ;$crc_3 =  $crc_3_shft ;$crc_2 =  $crc_2_shft."^"."$p" ;$crc_1 =  $crc_1_shft."^"."$p" ;$crc_0 =  $crc_0_shft."^"."$p" ;

最终推导结果

经过数学推导,我们得到并行计算的逻辑表达式。以CRC32输出位的其中几位为例:

一个时钟周期计算一个字节时

c[0] = c[24]^c[30]^d[0]^d[6];
c[1] = c[24]^c[25]^c[30]^c[31]^d[0]^d[1]^d[6]^d[7];
c[2] = c[24]^c[25]^c[26]^c[30]^c[31]^d[0]^d[1]^d[2]^d[6]^d[7];
c[3] = c[25]^c[26]^c[27]^c[31]^d[1]^d[2]^d[3]^d[7];
c[4] = c[24]^c[26]^c[27]^c[28]^c[30]^d[0]^d[2]^d[3]^d[4]^d[6];
c[5] = c[24]^c[25]^c[27]^c[28]^c[29]^c[30]^c[31]^d[0]^d[1]^d[3]^d[4]^d[5]^d[6]^d[7];
c[6] = c[25]^c[26]^c[28]^c[29]^c[30]^c[31]^d[1]^d[2]^d[4]^d[5]^d[6]^d[7];
c[7] = c[24]^c[26]^c[27]^c[29]^c[31]^d[0]^d[2]^d[3]^d[5]^d[7];
c[8] = c[0]^c[24]^c[25]^c[27]^c[28]^d[0]^d[1]^d[3]^d[4];
c[9] = c[1]^c[25]^c[26]^c[28]^c[29]^d[1]^d[2]^d[4]^d[5];
c[10] = c[2]^c[24]^c[26]^c[27]^c[29]^d[0]^d[2]^d[3]^d[5];
c[11] = c[3]^c[24]^c[25]^c[27]^c[28]^d[0]^d[1]^d[3]^d[4];
c[12] = c[4]^c[24]^c[25]^c[26]^c[28]^c[29]^c[30]^d[0]^d[1]^d[2]^d[4]^d[5]^d[6];
c[13] = c[5]^c[25]^c[26]^c[27]^c[29]^c[30]^c[31]^d[1]^d[2]^d[3]^d[5]^d[6]^d[7];
c[14] = c[6]^c[26]^c[27]^c[28]^c[30]^c[31]^d[2]^d[3]^d[4]^d[6]^d[7];
c[15] = c[7]^c[27]^c[28]^c[29]^c[31]^d[3]^d[4]^d[5]^d[7];
c[16] = c[8]^c[24]^c[28]^c[29]^d[0]^d[4]^d[5];
c[17] = c[9]^c[25]^c[29]^c[30]^d[1]^d[5]^d[6];
c[18] = c[10]^c[26]^c[30]^c[31]^d[2]^d[6]^d[7];
c[19] = c[11]^c[27]^c[31]^d[3]^d[7];
c[20] = c[12]^c[28]^d[4];
c[21] = c[13]^c[29]^d[5];
c[22] = c[14]^c[24]^d[0];
c[23] = c[15]^c[24]^c[25]^c[30]^d[0]^d[1]^d[6];
c[24] = c[16]^c[25]^c[26]^c[31]^d[1]^d[2]^d[7];
c[25] = c[17]^c[26]^c[27]^d[2]^d[3];
c[26] = c[18]^c[24]^c[27]^c[28]^c[30]^d[0]^d[3]^d[4]^d[6];
c[27] = c[19]^c[25]^c[28]^c[29]^c[31]^d[1]^d[4]^d[5]^d[7];
c[28] = c[20]^c[26]^c[29]^c[30]^d[2]^d[5]^d[6];
c[29] = c[21]^c[27]^c[30]^c[31]^d[3]^d[6]^d[7];
c[30] = c[22]^c[28]^c[31]^d[4]^d[7];
c[31] = c[23]^c[29]^d[5];

一个时钟周期计算两个字节时

c[0] = c[16]^c[22]^c[25]^c[26]^c[28]^d[0]^d[6]^d[9]^d[10]^d[12];
c[1] = c[16]^c[17]^c[22]^c[23]^c[25]^c[27]^c[28]^c[29]^d[0]^d[1]^d[6]^d[7]^d[9]^d[11]^d[12]^d[13];
c[2] = c[16]^c[17]^c[18]^c[22]^c[23]^c[24]^c[25]^c[29]^c[30]^d[0]^d[1]^d[2]^d[6]^d[7]^d[8]^d[9]^d[13]^d[14];
c[3] = c[17]^c[18]^c[19]^c[23]^c[24]^c[25]^c[26]^c[30]^c[31]^d[1]^d[2]^d[3]^d[7]^d[8]^d[9]^d[10]^d[14]^d[15];
c[4] = c[16]^c[18]^c[19]^c[20]^c[22]^c[24]^c[27]^c[28]^c[31]^d[0]^d[2]^d[3]^d[4]^d[6]^d[8]^d[11]^d[12]^d[15];
c[5] = c[16]^c[17]^c[19]^c[20]^c[21]^c[22]^c[23]^c[26]^c[29]^d[0]^d[1]^d[3]^d[4]^d[5]^d[6]^d[7]^d[10]^d[13];
c[6] = c[17]^c[18]^c[20]^c[21]^c[22]^c[23]^c[24]^c[27]^c[30]^d[1]^d[2]^d[4]^d[5]^d[6]^d[7]^d[8]^d[11]^d[14];
c[7] = c[16]^c[18]^c[19]^c[21]^c[23]^c[24]^c[26]^c[31]^d[0]^d[2]^d[3]^d[5]^d[7]^d[8]^d[10]^d[15];
c[8] = c[16]^c[17]^c[19]^c[20]^c[24]^c[26]^c[27]^c[28]^d[0]^d[1]^d[3]^d[4]^d[8]^d[10]^d[11]^d[12];
c[9] = c[17]^c[18]^c[20]^c[21]^c[25]^c[27]^c[28]^c[29]^d[1]^d[2]^d[4]^d[5]^d[9]^d[11]^d[12]^d[13];
c[10] = c[16]^c[18]^c[19]^c[21]^c[25]^c[29]^c[30]^d[0]^d[2]^d[3]^d[5]^d[9]^d[13]^d[14];
c[11] = c[16]^c[17]^c[19]^c[20]^c[25]^c[28]^c[30]^c[31]^d[0]^d[1]^d[3]^d[4]^d[9]^d[12]^d[14]^d[15];
c[12] = c[16]^c[17]^c[18]^c[20]^c[21]^c[22]^c[25]^c[28]^c[29]^c[31]^d[0]^d[1]^d[2]^d[4]^d[5]^d[6]^d[9]^d[12]^d[13]^d[15];
c[13] = c[17]^c[18]^c[19]^c[21]^c[22]^c[23]^c[26]^c[29]^c[30]^d[1]^d[2]^d[3]^d[5]^d[6]^d[7]^d[10]^d[13]^d[14];
c[14] = c[18]^c[19]^c[20]^c[22]^c[23]^c[24]^c[27]^c[30]^c[31]^d[2]^d[3]^d[4]^d[6]^d[7]^d[8]^d[11]^d[14]^d[15];
c[15] = c[19]^c[20]^c[21]^c[23]^c[24]^c[25]^c[28]^c[31]^d[3]^d[4]^d[5]^d[7]^d[8]^d[9]^d[12]^d[15];
c[16] = c[0]^c[16]^c[20]^c[21]^c[24]^c[28]^c[29]^d[0]^d[4]^d[5]^d[8]^d[12]^d[13];
c[17] = c[1]^c[17]^c[21]^c[22]^c[25]^c[29]^c[30]^d[1]^d[5]^d[6]^d[9]^d[13]^d[14];
c[18] = c[2]^c[18]^c[22]^c[23]^c[26]^c[30]^c[31]^d[2]^d[6]^d[7]^d[10]^d[14]^d[15];
c[19] = c[3]^c[19]^c[23]^c[24]^c[27]^c[31]^d[3]^d[7]^d[8]^d[11]^d[15];
c[20] = c[4]^c[20]^c[24]^c[25]^c[28]^d[4]^d[8]^d[9]^d[12];
c[21] = c[5]^c[21]^c[25]^c[26]^c[29]^d[5]^d[9]^d[10]^d[13];
c[22] = c[6]^c[16]^c[25]^c[27]^c[28]^c[30]^d[0]^d[9]^d[11]^d[12]^d[14];
c[23] = c[7]^c[16]^c[17]^c[22]^c[25]^c[29]^c[31]^d[0]^d[1]^d[6]^d[9]^d[13]^d[15];
c[24] = c[8]^c[17]^c[18]^c[23]^c[26]^c[30]^d[1]^d[2]^d[7]^d[10]^d[14];
c[25] = c[9]^c[18]^c[19]^c[24]^c[27]^c[31]^d[2]^d[3]^d[8]^d[11]^d[15];
c[26] = c[10]^c[16]^c[19]^c[20]^c[22]^c[26]^d[0]^d[3]^d[4]^d[6]^d[10];
c[27] = c[11]^c[17]^c[20]^c[21]^c[23]^c[27]^d[1]^d[4]^d[5]^d[7]^d[11];
c[28] = c[12]^c[18]^c[21]^c[22]^c[24]^c[28]^d[2]^d[5]^d[6]^d[8]^d[12];
c[29] = c[13]^c[19]^c[22]^c[23]^c[25]^c[29]^d[3]^d[6]^d[7]^d[9]^d[13];
c[30] = c[14]^c[20]^c[23]^c[24]^c[26]^c[30]^d[4]^d[7]^d[8]^d[10]^d[14];
c[31] = c[15]^c[21]^c[24]^c[25]^c[27]^c[31]^d[5]^d[8]^d[9]^d[11]^d[15];

完整可综合Verilog代码实现

以下是经过实际项目验证的单周期CRC32模块:

verilog

function [31:0] nextcrc32_d8;input [7:0] data;input [31:0] crc;reg [7:0] d;reg [31:0] c;reg [31:0] newcrc;begind = data;c = crc;newcrc[0] = c[24]^c[30]^d[0]^d[6];newcrc[1] = c[24]^c[25]^c[30]^c[31]^d[0]^d[1]^d[6]^d[7];newcrc[2] = c[24]^c[25]^c[26]^c[30]^c[31]^d[0]^d[1]^d[2]^d[6]^d[7];newcrc[3] = c[25]^c[26]^c[27]^c[31]^d[1]^d[2]^d[3]^d[7];newcrc[4] = c[24]^c[26]^c[27]^c[28]^c[30]^d[0]^d[2]^d[3]^d[4]^d[6];newcrc[5] = c[24]^c[25]^c[27]^c[28]^c[29]^c[30]^c[31]^d[0]^d[1]^d[3]^d[4]^d[5]^d[6]^d[7];newcrc[6] = c[25]^c[26]^c[28]^c[29]^c[30]^c[31]^d[1]^d[2]^d[4]^d[5]^d[6]^d[7];newcrc[7] = c[24]^c[26]^c[27]^c[29]^c[31]^d[0]^d[2]^d[3]^d[5]^d[7];newcrc[8] = c[0]^c[24]^c[25]^c[27]^c[28]^d[0]^d[1]^d[3]^d[4];newcrc[9] = c[1]^c[25]^c[26]^c[28]^c[29]^d[1]^d[2]^d[4]^d[5];newcrc[10] = c[2]^c[24]^c[26]^c[27]^c[29]^d[0]^d[2]^d[3]^d[5];newcrc[11] = c[3]^c[24]^c[25]^c[27]^c[28]^d[0]^d[1]^d[3]^d[4];newcrc[12] = c[4]^c[24]^c[25]^c[26]^c[28]^c[29]^c[30]^d[0]^d[1]^d[2]^d[4]^d[5]^d[6];newcrc[13] = c[5]^c[25]^c[26]^c[27]^c[29]^c[30]^c[31]^d[1]^d[2]^d[3]^d[5]^d[6]^d[7];newcrc[14] = c[6]^c[26]^c[27]^c[28]^c[30]^c[31]^d[2]^d[3]^d[4]^d[6]^d[7];newcrc[15] = c[7]^c[27]^c[28]^c[29]^c[31]^d[3]^d[4]^d[5]^d[7];newcrc[16] = c[8]^c[24]^c[28]^c[29]^d[0]^d[4]^d[5];newcrc[17] = c[9]^c[25]^c[29]^c[30]^d[1]^d[5]^d[6];newcrc[18] = c[10]^c[26]^c[30]^c[31]^d[2]^d[6]^d[7];newcrc[19] = c[11]^c[27]^c[31]^d[3]^d[7];newcrc[20] = c[12]^c[28]^d[4];newcrc[21] = c[13]^c[29]^d[5];newcrc[22] = c[14]^c[24]^d[0];newcrc[23] = c[15]^c[24]^c[25]^c[30]^d[0]^d[1]^d[6];newcrc[24] = c[16]^c[25]^c[26]^c[31]^d[1]^d[2]^d[7];newcrc[25] = c[17]^c[26]^c[27]^d[2]^d[3];newcrc[26] = c[18]^c[24]^c[27]^c[28]^c[30]^d[0]^d[3]^d[4]^d[6];newcrc[27] = c[19]^c[25]^c[28]^c[29]^c[31]^d[1]^d[4]^d[5]^d[7];newcrc[28] = c[20]^c[26]^c[29]^c[30]^d[2]^d[5]^d[6];newcrc[29] = c[21]^c[27]^c[30]^c[31]^d[3]^d[6]^d[7];newcrc[30] = c[22]^c[28]^c[31]^d[4]^d[7];newcrc[31] = c[23]^c[29]^d[5];nextcrc32_d8 = newcrc;end
endfunctionfunction [31:0] nextcrc32_d16;input [15:0] data;input [31:0] crc;reg [15:0] d;reg [31:0] c;reg [31:0] newcrc;begind = data;c = crc;newcrc[0] = c[16]^c[22]^c[25]^c[26]^c[28]^d[0]^d[6]^d[9]^d[10]^d[12];newcrc[1] = c[16]^c[17]^c[22]^c[23]^c[25]^c[27]^c[28]^c[29]^d[0]^d[1]^d[6]^d[7]^d[9]^d[11]^d[12]^d[13];newcrc[2] = c[16]^c[17]^c[18]^c[22]^c[23]^c[24]^c[25]^c[29]^c[30]^d[0]^d[1]^d[2]^d[6]^d[7]^d[8]^d[9]^d[13]^d[14];newcrc[3] = c[17]^c[18]^c[19]^c[23]^c[24]^c[25]^c[26]^c[30]^c[31]^d[1]^d[2]^d[3]^d[7]^d[8]^d[9]^d[10]^d[14]^d[15];newcrc[4] = c[16]^c[18]^c[19]^c[20]^c[22]^c[24]^c[27]^c[28]^c[31]^d[0]^d[2]^d[3]^d[4]^d[6]^d[8]^d[11]^d[12]^d[15];newcrc[5] = c[16]^c[17]^c[19]^c[20]^c[21]^c[22]^c[23]^c[26]^c[29]^d[0]^d[1]^d[3]^d[4]^d[5]^d[6]^d[7]^d[10]^d[13];newcrc[6] = c[17]^c[18]^c[20]^c[21]^c[22]^c[23]^c[24]^c[27]^c[30]^d[1]^d[2]^d[4]^d[5]^d[6]^d[7]^d[8]^d[11]^d[14];newcrc[7] = c[16]^c[18]^c[19]^c[21]^c[23]^c[24]^c[26]^c[31]^d[0]^d[2]^d[3]^d[5]^d[7]^d[8]^d[10]^d[15];newcrc[8] = c[16]^c[17]^c[19]^c[20]^c[24]^c[26]^c[27]^c[28]^d[0]^d[1]^d[3]^d[4]^d[8]^d[10]^d[11]^d[12];newcrc[9] = c[17]^c[18]^c[20]^c[21]^c[25]^c[27]^c[28]^c[29]^d[1]^d[2]^d[4]^d[5]^d[9]^d[11]^d[12]^d[13];newcrc[10] = c[16]^c[18]^c[19]^c[21]^c[25]^c[29]^c[30]^d[0]^d[2]^d[3]^d[5]^d[9]^d[13]^d[14];newcrc[11] = c[16]^c[17]^c[19]^c[20]^c[25]^c[28]^c[30]^c[31]^d[0]^d[1]^d[3]^d[4]^d[9]^d[12]^d[14]^d[15];newcrc[12] = c[16]^c[17]^c[18]^c[20]^c[21]^c[22]^c[25]^c[28]^c[29]^c[31]^d[0]^d[1]^d[2]^d[4]^d[5]^d[6]^d[9]^d[12]^d[13]^d[15];newcrc[13] = c[17]^c[18]^c[19]^c[21]^c[22]^c[23]^c[26]^c[29]^c[30]^d[1]^d[2]^d[3]^d[5]^d[6]^d[7]^d[10]^d[13]^d[14];newcrc[14] = c[18]^c[19]^c[20]^c[22]^c[23]^c[24]^c[27]^c[30]^c[31]^d[2]^d[3]^d[4]^d[6]^d[7]^d[8]^d[11]^d[14]^d[15];newcrc[15] = c[19]^c[20]^c[21]^c[23]^c[24]^c[25]^c[28]^c[31]^d[3]^d[4]^d[5]^d[7]^d[8]^d[9]^d[12]^d[15];newcrc[16] = c[0]^c[16]^c[20]^c[21]^c[24]^c[28]^c[29]^d[0]^d[4]^d[5]^d[8]^d[12]^d[13];newcrc[17] = c[1]^c[17]^c[21]^c[22]^c[25]^c[29]^c[30]^d[1]^d[5]^d[6]^d[9]^d[13]^d[14];newcrc[18] = c[2]^c[18]^c[22]^c[23]^c[26]^c[30]^c[31]^d[2]^d[6]^d[7]^d[10]^d[14]^d[15];newcrc[19] = c[3]^c[19]^c[23]^c[24]^c[27]^c[31]^d[3]^d[7]^d[8]^d[11]^d[15];newcrc[20] = c[4]^c[20]^c[24]^c[25]^c[28]^d[4]^d[8]^d[9]^d[12];newcrc[21] = c[5]^c[21]^c[25]^c[26]^c[29]^d[5]^d[9]^d[10]^d[13];newcrc[22] = c[6]^c[16]^c[25]^c[27]^c[28]^c[30]^d[0]^d[9]^d[11]^d[12]^d[14];newcrc[23] = c[7]^c[16]^c[17]^c[22]^c[25]^c[29]^c[31]^d[0]^d[1]^d[6]^d[9]^d[13]^d[15];newcrc[24] = c[8]^c[17]^c[18]^c[23]^c[26]^c[30]^d[1]^d[2]^d[7]^d[10]^d[14];newcrc[25] = c[9]^c[18]^c[19]^c[24]^c[27]^c[31]^d[2]^d[3]^d[8]^d[11]^d[15];newcrc[26] = c[10]^c[16]^c[19]^c[20]^c[22]^c[26]^d[0]^d[3]^d[4]^d[6]^d[10];newcrc[27] = c[11]^c[17]^c[20]^c[21]^c[23]^c[27]^d[1]^d[4]^d[5]^d[7]^d[11];newcrc[28] = c[12]^c[18]^c[21]^c[22]^c[24]^c[28]^d[2]^d[5]^d[6]^d[8]^d[12];newcrc[29] = c[13]^c[19]^c[22]^c[23]^c[25]^c[29]^d[3]^d[6]^d[7]^d[9]^d[13];newcrc[30] = c[14]^c[20]^c[23]^c[24]^c[26]^c[30]^d[4]^d[7]^d[8]^d[10]^d[14];newcrc[31] = c[15]^c[21]^c[24]^c[25]^c[27]^c[31]^d[5]^d[8]^d[9]^d[11]^d[15];nextcrc32_d16 = newcrc;end
endfunction

性能分析与优化策略

时序特性

我们的设计实现了真正的单周期处理:

  • ** latency**:1个时钟周期
  • 吞吐量 :每个周期8/16位数据
  • 最大频率 :取决于组合逻辑的延迟

进一步优化技巧

  1. 流水线优化 :对于更高频率需求,可以插入流水线寄存器
  2. 位宽可配置 :参数化设计支持不同位宽
  3. 多周期路径约束 :合理设置时序约束

自动化CRC32生成代码

一个时钟周期计算一个和两个字节输入数据的CRC32 公式的Python 代码,附件已分享

crc32_d8.py   &  crc32_d16.py

文章转载自:

http://ezlqoPow.pmysp.cn
http://YiZK4s5y.pmysp.cn
http://Fuvrs49s.pmysp.cn
http://f6eJqLkw.pmysp.cn
http://Iitxi6Je.pmysp.cn
http://xtIT7mo3.pmysp.cn
http://cFN9jhBi.pmysp.cn
http://f8sN2Njf.pmysp.cn
http://5abAWSIP.pmysp.cn
http://SeaQvidP.pmysp.cn
http://ufD7Op7N.pmysp.cn
http://VJQnx9TX.pmysp.cn
http://J8MglgPn.pmysp.cn
http://O0XuLwuv.pmysp.cn
http://IPJsa6nz.pmysp.cn
http://nmaXBkEX.pmysp.cn
http://N9KwA0bR.pmysp.cn
http://VOZh1mYh.pmysp.cn
http://K1Wi0hwx.pmysp.cn
http://OJjRx5Xk.pmysp.cn
http://NIXyxnUy.pmysp.cn
http://FcvdJC3O.pmysp.cn
http://eqQmI3Ok.pmysp.cn
http://06H2qLUL.pmysp.cn
http://JoOvpJgM.pmysp.cn
http://nSX9akBS.pmysp.cn
http://25C3aWAq.pmysp.cn
http://cdYXt2ci.pmysp.cn
http://Q6fRpwZQ.pmysp.cn
http://H0hFxh99.pmysp.cn
http://www.dtcms.com/a/385714.html

相关文章:

  • 【面试场景题】谈谈你对Seata的理解
  • C++基础:clang的分步编译-了解build细节
  • OS-内存管理 真题复盘总结
  • 一阶低通滤波在运动控制中的应用
  • Redis核心数据类型解析
  • 在 Ubuntu 22.04 系统中,如何安装最新版 MySQL和Navicat Pro 17
  • 立创·庐山派K230CanMV开发板的进阶学习——颜色识别
  • 大模型学习:Transformer模型构建
  • C++ STL之deque的使用和模拟实现
  • 【网络安全就业】信息安全专业的就业前景(非常详细)零基础入门到精通,收藏这篇就够了
  • SpringBoot中的循环依赖以及解决办法
  • np.linalg 函数一览
  • 网络:UDP协议
  • 【开题答辩全过程】以 JAVA汽车年审管理系统为例,包含答辩的问题和答案
  • 【Linux网络编程】Socket-UDP
  • OpenCV物体跟踪:从理论到实战的全面解析
  • Linux:线程同步
  • Day24_【深度学习(3)—PyTorch使用(2)—张量的数值计算】
  • 9月15日
  • 【langchain】构建简单检索问答链
  • 简单的数组
  • ENVI系列教程(四)——图像几何校正
  • 数据结构基础--散列表
  • 【Redis】-- 主从复制
  • 输入1.8V~5.5V 输出28V DCDC升压芯片TLV61046A
  • Windows 上安装 FFmpeg 8.0(2025 版)——从“手动解压”到“一条命令”的进化之路
  • 红黑树(RBTree)知识总结
  • 若依框架前端通过 nginx docker 镜像本地运行
  • 二十、瑞萨RZT2N2 PROFINET SDK正式发布
  • SpringAI框架接入Deepseek和豆包实现智能聊天