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

Spatial 语言核心概念简介

 

我们来详细解析一下斯坦福大学的 Spatial 语言。这是一个非常专业且强大的领域特定语言(DSL),用于高性能硬件(如FPGA或ASIC)生成。

一、Spatial 语言核心概念简介

Spatial 是一个嵌入在 Scala 内部的 DSL(Domain-Specific Language)。它的根本目标是让软件工程师和算法专家能够用高级的、类似软件的语法来描述计算密集型算法,然后由 Spatial 编译器自动地将该高级描述综合(Synthesize) 成高效的、并行的硬件设计(最终生成 Verilog 代码)。

其核心思想是将计算与通信分离,并让程序员通过高级原语来控制内存层次结构、并行性和数据流,而无需手动编写繁琐的硬件描述语言(如 Verilog/VHDL)。


二、Spatial 在 Scala 基础上增加了什么?

Scala 为 Spatial 提供了强大的宿主语言环境,包括:函数式编程、类型系统、元编程(Macros)等。Spatial 利用这些特性构建了一整套用于描述硬件行为的领域特定构造(Domain-Specific Constructs)。

以下是 Spatial 引入的核心语法和概念,这些是纯 Scala 所没有的:

1. 数据类型(Data Types)

Spatial 引入了代表硬件中实际位宽(bit-width)的数据类型,这是硬件精确建模的基础。

  • FixPt[S, I, F]:定点数(Fixed-Point)类型。这是硬件设计中非常关键的类型,用于处理小数运算而不使用昂贵的浮点单元。

    • S: 符号性(TRUE(有符号), FALSE(无符号))

    • I: 整数部分的位宽

    • F: 小数部分的位宽

    • 例如:FixPt[TRUE, _16, _8] 表示一个 16位整数、8位小数的有符号定点数。

  • FltPt[G, E]:浮点数(Floating-Point)类型。

    • G: 总位宽(如 32, 64)

    • E: 指数部分位宽

  • Struct:结构体,用于将多个数据类型打包成一个聚合类型。

2. 内存体系(Memory Hierarchy)

这是 Spatial 最核心和创新的部分之一。它提供了一系列抽象的内存节点(Memory Nodes),让程序员可以构建一个分层的内存结构。

  • Reg:寄存器。最基本的存储单元,用于存储单个值。

  • SRAM:片上静态存储器。相当于 FPGA 中的 Block RAM 或 ASIC 中的 SRAM 数组。用于存储小块数据,提供快速访问。

  • DRAM:片外动态存储器。抽象代表主机(CPU)内存或FPGA板卡上的 DDR 内存。容量大但延迟高。

  • FIFOLIFO:先进先出/后进先出队列。用于实现数据流(Streaming)应用。

  • LineBuffer:行缓冲区。专门为图像处理等应用优化,可以高效地滑动窗口(例如卷积核)。

  • Stream:流。用于在加速器单元之间建立数据流通道。

3. 控制结构(Control Constructs)

Spatial 提供了用于描述硬件并行性和流水线的控制原语。

  • ForeachReduceFoldFilter:高阶操作。类似于 Scala 的集合操作,但编译器会将它们并行化并映射到硬件流水线上。

    scala
    // 一个简单的并行累加器
    val result = Reduce(Reg[Int](0))(N by 1 par 16){ i =>mySRAM(i)
    }{_+_}
    // `par 16` 表示同时启动16个加法器进行并行计算
  • Parallel:并行块。块内的所有操作都会并行执行。

    scala
    Parallel {sram0(0) = 10sram1(0) = 20
    }
  • Pipe:流水线。内部的逻辑会被综合成多级流水线。

  • Sequential:顺序块。块内的操作会严格按照顺序执行(非并行、非流水线)。

4. 主机(Host)- 加速器(Accelerator)交互

Spatial 程序通常分为两部分:

  1. Host Code:在 CPU 上运行的 Scala 代码,负责准备数据、控制流程。

  2. Accelerator Code:在 accel 块中定义的、将被编译成硬件的代码。

  • accel:加速器块。所有放在这个块里的代码都会被编译成硬件。

    scala
    accel {// 这里面的所有逻辑都会变成硬件Foreach(0 until 1024 par 16) { i =>val data = dram(i) // 从DRAM读sram(i) = data * 2dram(i) = sram(i) // 写回DRAM}
    }
  • setMem / getMem:用于在主机代码中为 DRAM 填充数据或获取结果。

5. 元编程与静态计算(Metaprogramming & Static Elaboration)

Spatial 程序在 Scala 编译时(compile-time)就已经开始“运行”。编译器会执行你的 Spatial 代码,但不进行实际的计算,而是构建一个代表硬件结构的中间表示(IR)。这意味着 iffor 等控制流在生成硬件时就被确定(静态展开),而不是在硬件运行时才判断。

scala
val depth = 1024 // 这个值在编译时是已知的
val mySRAM = SRAM[Int](depth) // 编译器会生成一个深度为1024的SRAM// 这个循环会在编译时被展开,生成1024个硬件单元或一个循环结构
Foreach(0 until depth) { i => ... }

三、语法手册、教程和参考手册

Spatial 是一个学术研究项目,其文档不像主流工业级项目那样完善,但核心资源是存在的。

  1. 官方主站(最核心的资源):

    • URL: https://spatial-lang.org/

    • 内容:包含入门指南(Getting Started)、语言文档(Language Documentation)、教程(Tutorials)、示例库(Examples)和 API 文档。这是学习的起点。

  2. GitHub 仓库:

    • URL: https://github.com/stanford-ppl/spatial

    • 内容:源代码、问题追踪(Issues)。apps 目录下有大量示例应用程序,是学习的最佳素材。

  3. 学术论文:
    要深入理解其设计哲学和实现技巧,阅读原始论文是关键。

    • 主要论文:Spatial: A Language and Compiler for Application Accelerators (PLDI 2018)。这是 Spatial 语言的“出生证明”,必读。

    • 其他相关论文:在 Spatial 官网和 GitHub 上通常会有引用,关于其特定优化(如定点数分析、内存子系统等)。

  4. 教程与示例:

    • 官网的 Tutorials 部分会引导你完成一些基础概念,如创建项目、编写第一个 accelerator、使用不同的内存类型等。

    • Examples 包含了从简单的矩阵乘法、卷积到复杂的机器学习内核(如RNN、LSTM)和图像处理算法。通过阅读和运行这些例子是上手最快的方式。

总结

 
特性纯 ScalaSpatial (基于 Scala)
目的 通用软件编程 硬件生成(FPGA/ASIC)
核心添加 - 硬件数据类型(FixPtFltPt),内存抽象(DRAMSRAMReg),并行控制原语(Foreach parPipeParallel),主机-加速器交互(accel 块)
执行模型 运行时在 CPU 上动态执行 编译时元编程构建硬件结构,生成的是静态的、并行的硬件电路
关键概念 面向对象、函数式编程 计算与通信分离、内存层次结构、并行性与流水线

学习 Spatial 需要同时具备软件思维(Scala)和硬件思维(对并行性、流水线、内存带宽和延迟有基本概念)。它是一个非常强大的工具,能够极大地提升硬件加速器的设计效率。

 
 
 
 

相关文章:

Spatial 语言核心概念简介

我们来详细解析一下斯坦福大学的 Spatial 语言。这是一个非常专业且强大的领域特定语言(DSL),用于高性能硬件(如FPGA或ASIC)生成。 一、Spatial 语言核心概念简介 Spatial 是一个嵌入在 Scala 内部的 DSL(Domain-Specific Language)。它的根本目标是让软件工程师和算法专…...

Redis数据库的五类核心数据结构

Redis是一个开源的键值存储系统,支持多种类型的值模型,其中五种核心的数据结构是:String(字符串)、List(列表)、Set(集合)、Hash(哈希表)、和Sorted Set(有序集合)。下面将对每种数据结构进行详细解析。 1. String(字符串) String数据结构是最简单的数据类型,通…...

RAG 个人知识库 向量查找原理

...

css-1

css的三大特性继承性:子元素继承父元素样式主要是跟文字相关的样式继承。层叠性:后面样式会覆盖前面样式,主要解决样式冲突问题。但是要看选择器权重来确定优先级优先级:优先级由选择器的 权重 决定,权重高的规则覆盖权重低的规则css的优先级原则:1. 优先级相等的时候,CS…...

Java-JDK8新特性

Java-JDK8新特性主要讲解: 1.Java8概述 2.Lambda表达式 3.函数式接口 4.方法引用 5.Stream API 6.新时间API 1.Java8概述 略 2.Lambda表达式 https://github.com/godmaybelieve...

解决MySQL ONLY_FULL_GROUP_BY 错误的方案

在MySQL数据库中,ONLY_FULL_GROUP_BY是一个服务器SQL模式,它用于控制对 GROUP BY子句的处理。如果启用了 ONLY_FULL_GROUP_BY,任何不在 GROUP BY子句中也没有使用聚合函数的非聚合列都会导致错误。这是为了防止不确定的结果,因为当选择非聚合列而没有明确指定如何对这些列进…...

博客园美化

参考: 基本模板:博客园美化(最全) 看板猫:博客园看板猫 大部分套用的是模板,自己更改了一些尺寸、位置、透明度之类的。下面放上博客定制css。 #google_ad_c1, #google_ad_c2 {display:none;} .syntaxhighlighter a, .syntaxhighlighter div, .syntaxhighlighter code, .…...

spatial 一个芯片设计语言的简介 scala dsl 并行支持 -1

以下是对原网站内容的翻译 https://spatial-lang.readthedocs.io/en/legacy/tutorial/starting.html 以下是您提供的Spatial框架入门指南的中英对照翻译:​​0. Getting Started | 0. 开始使用​​ ​​Prerequisites | 先决条件​​ First, make sure to download and instal…...

NOIP备考

模拟赛 1 T1 https://www.luogu.com.cn/problem/T664700 前置知识是 P5019。 很典的思路。在 \(a\) 序列前后都塞 \(a_0=a_{n+1}=0\)。算长 \(n+2-1=n+1\) 的差分数组 \(c\)。易知 \(a\) 是 \(c\) 的一个前缀和数组,即 \(a_i+c_i=a_{i+1}\)。已知 \(a_0=0\),只需要差分数组都…...

NVIDIA GPGPU 访存通路设计调研

纵向结构上,传统架构仅对用户暴露 2 层存储交互,而随着 Hopper 添加 st.async ,NVIDIA GPU 完成暴露 3 层存储结构的双向通信接口,即 \(2\times C_{3}^{2}=6\) 一共 6 种指令。Src\Dst RF SMEM DRAMRF x st. Shared st. GlobalSMEM ld. Shared x st. Async (Hopper)DRAM ld…...

用 Java 和 Tesseract 实现验证码图像识别

验证码图像识别在自动化测试、信息采集、系统登录等场景中有着重要的应用价值。本文将介绍如何使用 Java 语言结合 Tesseract OCR 引擎,构建一个完整的验证码图像识别流程,包括图像预处理与识别优化。 一、环境准备 安装 Java(推荐版本 11 及以上) 安装 Tesseract OCR 引擎…...

AGC003D

题意是给定一个集合 \(S\) 要求找到它的最大的子集使得子集里的任意两个数相乘都不是完全立方数。 \(S_i\le1e10\),集合大小小于 \(1e5\)。 首先对于每个数都把它的因子的指数对 \(3\) 取模,然后可以发现操作完了的形式都只有一种形式与它相乘可以得到完全立方数的数。那就在…...

Java 实现验证码图像识别与处理流程详解

在实际开发中,自动化处理验证码图像是提升系统智能化和测试效率的一个关键点。Java 作为一门稳健的编程语言,结合 OCR 技术可以有效实现验证码识别。本文将介绍如何使用 Java 配合 Tesseract OCR 引擎完成从图像读取、预处理到文字识别的完整流程。 一、项目依赖准备 安装 Ja…...

图论杂题。

胡马渐远蹄声尽,四顾萧条暮色起。 空城角随西风吟,废池乔木,犹厌言兵。 ——《无题》luogu P6880 反转边等价于删一条再加一条边。 加边的肯定随便求。 删边,如果删在最短路上我们就暴力跑一遍;否则肯定还是最短路。两个方向最短路上 \(\mathcal{O}(n)\) 条边。用稠密图朴…...

暑假训练小结

主要做bzoj题单。 前几天相当痛苦,水平太菜题单根本做不下去。 基本都是跟着题解写代码。 还记得最开始写的是一道网络流然后学的是ek。 熬过第一个阶段之后,从杀蚂蚁那道题之后开始发现自己可以大概看懂大部分题解的思路了。 别问我为什么是杀蚂蚁,因为那段时间里这个记得最…...

初识python:一些基础的知识(函数)

目录函数函数的几种定义方法函数的返回值函数的调用函数的实参和形参实参的分类 函数 函数的几种定义方法 函数拥有以下几种定义方法,第一种:没有参数 def self_max(): a,b = 10,20 if a > b: print(a) elif a == b: print(别搞,两个变量相同。) else: print(b) self_max(…...

Java并发编程(3)

Java内存模型 1、说一下你对Java内存模型(JMM)的理解Java程序运行在各种硬件和操作系统上,不同硬件的CPU缓存策略、内存访问顺序、指令重排规则可能都不一样。那JMM是Java规范定义的一个抽象模型,是一套规则:线程和主内存的交互:线程如何从主内存读变量、写变量 可见性保…...

斐波那契子序列

到处乱逛找到的一道有意思的题。 定义斐波那契序列为:前两项值不做限制,\(f_i=f_{i-1}+f_{i-2}(2<i\le n)\)。 给定一个长度为 \(n\) 的序列 \(a\),找出其最长的斐波那契子序列。 如果有多个最长输出字典序最小的一个。 正解做法貌似为 \(n^2logn\)。即动态规划加二分。 …...

[豪の学习笔记] 软考中级备考 基础复习#10

UML建模概述、类图、用例图、顺序图、活动图、状态图、通信图、构件图跟学视频:学以致知Learning - 软件设计师 基础阶段|考点理论精讲 Chapter 10 - UML建模 1 - 概述 ​ 统一建模语言UML是面向对象软件的标准化建模语言。UML由三个要素构成:UML的基本构造块、支配这些构造块…...

题解:CF2137D Replace with Occurrences

题意为给定一个长度为 \(n\) 的序列 \(b\),要求你构造一个序列 \(a\) 使得对于每一个序列 \(a\) 中的数 \(a_i\),在序列 \(a\) 都出现了 \(b_i\) 次。 可以发现 \(a\) 序列中的数的大小是无关紧要的,重要的是出现次数。 一开始可以很快的得出一个错解那就是判断完有无解之后…...

题解:CF2137C Maximum Even Sum

题意是给定两个数 \(a,b\),你可以进行一次操作,选定一个 \(b\) 的因数 \(k\),将 \(a\) 变为 \(a \times k\),并将 \(b\) 变为 \(b/k\),求出如何操作可以使得 \(a+b\) 是一个偶数,并且值最大,请输出这个最大值。 如果不考虑 \(a+b\) 是否为偶数,容易想到最大值为 \(a\ti…...

第02周 java预习

课前问题列表 1.方法相关问题 public class Main {static void changeStr(String x) {x = "xyz";}static void changeArr(String[] strs) {for (int i = 0; i < strs.length; i++) {strs[i] = strs[i]+""+i;}}public static void main(String[] args) {…...

编码规范

1.不对指针变量进行sizeof操作。 2.数组作为函数参数时,必须同时将其长度作为函数的参数。 3.字符串或指针作为函数参数时,请检查参数是否为NULL. 4.对字符串进行存储操作,确保字符串有\0结束符。 5.整数之间运算时必须严格检查,确保不会出现溢出、符号反转或除以0。 6.内存…...

深入解析:【译】Visual Studio 八月更新已发布 —— 更智能的人工智能、更出色的调试功能以及更多控制权

深入解析:【译】Visual Studio 八月更新已发布 —— 更智能的人工智能、更出色的调试功能以及更多控制权pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &q…...

命令模式在 TPL Dataflow 反馈回路管道中的应用及问题解决

命令模式与 TPL Dataflow 基础概念 命令模式的核心在于对一类对象公共操作的抽象,通过定义统一的方法签名,将操作封装为独立对象。这种设计思路不仅实现了调用者与实现者的解耦,还为事件驱动架构和 AOP 思想提供了天然支持。在.NET 生态中,TPL Dataflow 组件为这种抽象提供…...

Ubuntu 24.04 服务器调整MySQL 8.0.42 三节点集群(一主两从架构)安装部署配置教程

Ubuntu 24.04 服务器调整MySQL 8.0.42 三节点集群(一主两从架构)安装部署配置教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", &q…...

使用almalinux基础镜像创建nginx镜像

前言 使用almalinux:latest镜像构建nginx镜像,启动容器时,nginx自动启动 创建基本文件 cd ~ mkdir nginxtest cd nginxtest/ echo nginx s running!!! >> index.html vi Dockerfile编辑dockerfile文件内容 FROM almalinux:latest MAINTAINER "smartaiops<smar…...

docke容器版Nessus登录+破解+激活+特征库更新

docke容器版Nessus登录+破解+激活+特征库更新 安装Nessus docker run -itd --name=ramisec_nessus -p 8834:8834 ramisec/nessus 重置账号密码1. 进入容器 docker exec -it ramisec_nessus bash2. 查看用户 /opt/nessus/sbin/nessuscli lsuser3. 修改指定用户的密码(以admin为…...

我把Cursor当磁盘清理工具用,非常棒! - ukyo-

我来帮您删除这个Colima虚拟磁盘镜像文件: [2 tools called] ✅ **文件删除成功!** **文件信息**:- **文件名**: basedisk- **位置**: ~/.colima/_lima/colima/- **大小**: 456MB- **类型**: Colima 虚拟磁盘镜像文件 **释放的磁盘空间**: **456MB** **删除后的影响**:- Co…...

vue项目

新建文件夹,然后用vscode打开这个文件然后在终端新建vue文件...

第九篇:数据库服务克隆应用

数据库克隆概念介绍 在数据库MySQL 8.0(8.0.17+)版本中,引入了数据库的克隆功能,主要是借助clone-plugin实现的,是对数据页底层克隆; 克隆的数据是InnoDB存储引擎中的物理快照信息,包括schemas, tables, tablespaces, and data dictionary metadata; 在数据库中出现克隆…...

Anti-Proxy Attendance 题解

CF1924F 题解题目传送门:CF1924F 还是第一次见这种势能题。 先把交互库的回答转成 \(0,1\) 表示答案是否在这个区间中。 首先把题目转化一下,对每个位置 \(i\) 维护一个 01 串 \(S_i\) 表示:如果 \(i\) 是答案,那么当前交互库的每个回答是否是真话。即如果当前询问 \([l,r]…...

【2024-2025第二学期】助教工作总结

一、助教工作的具体职责和任务 路由交换技术的助教的具体职责在于课前配合老师发布预习任务,在同学预习存在困难时给予问题解答;课中主要帮助同学解决实验遇到的卡壳问题,帮助同学们更快更全面的掌握实验内容和相应的理论知识;课后批改同学的作业、实验报告,并且对课中未完…...

开始每小时记录日程

每小时记录一次做的事,公开 20250914_155401 看b站视频,吃东西...

5【鸿蒙/OpenHarmony/NDK】使用Node-API进行异步任务开发

各位码友们好!今天这篇干货主要聚焦实操细节,希望能帮大家少踩坑。​ 要是过程中遇到哪块没看懂、有疑问,或者你有更优的实现思路,评论区尽管聊!发现文档里有疏漏或错误也尽管指出来 —— 技术这东西就得互相挑刺才能越磨越精,咱们一起把这些知识点吃透~是什么?与同步处…...

控制器指令

cpu中有控制器和运算器 这里就要开始学控制器 指令 指令分为两个部分: 操作码 做什么事情 地址码 对谁做 当cpu检测到操作码为000110的时候,就要执行停机操作 指令是计算机的最小功能单位 计算机智能执行自己指令系统中的指令,不能执行其他系统的指令 比如说inter芯片一般都…...

题解:AT_abc421_c [ABC421C] Alternated

题面 思路 似乎有很多大神用类似逆序对的方法 \(O(n\log n)\) 通过了此题,不过此题是有贪心 \(O(n)\) 做法的。 我们可以从结果推导,每一个 A 和 B 都相邻的情况只有两种:AB...AB 和 BA...BA,以下称这两个结果串为 \(t\),题目给出的串为 \(s\)。 考虑怎样使得其消耗代价最…...

MySQL数据库:SQL数据类型

SQL数据类型 数值类型 字符类型 时间日期类型...

Ubuntu 安装

太好了!系统已经安装完成了! 您现在看到的是安装成功的最终界面。这意味着所有步骤,包括分区、复制文件、安装更新和配置引导程序,都已全部顺利完成。您现在有两个选择:立即重启 (推荐)点击这个按钮,计算机将会重启。重启后,它会从硬盘启动,您将进入刚刚安装好的全新 U…...

幼等数论

整除 T1-1. Propose that \(m > n \geqslant 0\), Prove that \( (2{2n} + 1) \mid (2{2m} - 1) \) . Since we have:\[x^n - y^n = (x - y)(x^{n-1} + x^{n-2}y + \cdots + xy^{n-2} + y^{n-1})\] Therefore, we can rewrite:\[ 2{2m} - 1 = (2{2{n+1}}){2{m-n-1}} - 1{2{…...

搭建rocketmq的三主三从遇到的坑

1、机器配置cat /etc/hosts 192.168.224.128 worker1 192.168.224.129 worker2 192.168.224.130 worker3 2、broker配置 128机器 a-master#所属集群名字,名字⼀样的节点就在同⼀个集群内 brokerClusterName=rocketmq-cluster #broker名字,名字⼀样的节点就是⼀组主从节点。 …...

深入解析:轻松Linux-9.进程间通信

深入解析:轻松Linux-9.进程间通信pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; f…...

2025.9.14——1黄1绿

普及/提高- P2278 [HNOI2003] 操作系统 就是模拟,但是机房噪音太大调了好久…… 普及+/提高 P2233 [HNOI2002] 公交车路线 该说果然是老题吗……好简单的DP啊,应该只有黄的水平。...

Ubuntu 中改图片大小

在 Ubuntu 中,可以使用 ImageMagick 工具来调整图片的大小。ImageMagick 是一个强大的图像处理工具,支持多种图像格式和操作。 安装 ImageMagick 首先,您需要安装 ImageMagick。打开终端并输入以下命令: sudo apt-get install imagemagick使用 ImageMagick 缩放图片 安装完…...

认识眼图和眼图的参数

认识眼图 眼图(Eye Diagram)是用余辉方式累积叠加显示采集到的串行信号的比特位的结果,叠加后的图形形状看起来和眼睛很像,故名眼图。眼图的分析是数字系统信号完整性分析的关键之一。 眼图的形成 由于眼图是示波器用余辉方式将采集到的一系列串行信号的多个单位间隔(UI)…...

【芯片设计-信号完整性 SI 学习 1.2 -- loopback 回环测试】 - 实践

【芯片设计-信号完整性 SI 学习 1.2 -- loopback 回环测试】 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New…...

【科研绘图系列】R语言绘制地图和散点图 - 指南

【科研绘图系列】R语言绘制地图和散点图 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !…...

Java NIO 学习小记

Java NIO 学习小记 :Buffer、Channel 与 Selector 在 Java 的 I/O 体系中,NIO(New Input/Output)是对传统 BIO(Blocking I/O)的优化。NIO 提供了更高效的 面向缓冲区、基于通道 的数据处理方式,并且通过 多路复用器(Selector) 实现了单线程处理多个连接的能力。本文简…...

扩展欧几里得算法求乘法逆元

之前学过用快速幂求逆元,条件是当模数 \(p\) 为质数的时候,\(a\) 的逆元就是 \(a^{p - 2}\)。 但相较于扩展欧几里得算法求逆元,适用的范围是比较小的,因为扩展欧几里得算法适用于所有逆元存在的情况。在以下的式子中,模数为 \(m\) 的情况下,\(x\) 就是 \(a\) 的逆元 \[a…...

redis实现缓存3-封装redis工具类

具体实现: CacheClient package com.hmdp.utils;import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.data.re…...