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

个人学习笔记12

最终版test_macro.svhifndef TEST_MACRO_SVH define TEST_MACRO_SVH // // Color Definition // define COLOR_RESET \033[0m define COLOR_BOLD_BLUE \033[1;34m define COLOR_BOLD_GREEN \033[1;32m define COLOR_BOLD_RED \033[1;31m define COLOR_BOLD_YELLOW \033[1;33m define COLOR_BOLD_CYAN \033[1;36m // // Global Counter (需要在TB里定义) // int total_pass, total_fail; // // // Test Suite // define TEST_SUITE_BEGIN(name) \ $display(\n); \ $display(COLOR_BOLD_CYAN COLOR_RESET); \ $display(COLOR_BOLD_CYAN Test Suite: %s COLOR_RESET, name); \ $display(COLOR_BOLD_CYAN COLOR_RESET); // // Test Case (支持 name id) // 会定义局部变量 __test_name / __test_id // define TEST_CASE_BEGIN(name, id) \ string __test_name name; \ int __test_id id; \ $display(\n); \ $display(COLOR_BOLD_BLUE [TEST CASE %0d] %s COLOR_RESET, __test_id, __test_name); // // Step // define TEST_STEP(msg) \ $display(COLOR_BOLD_YELLOW [STEP][TC%0d][%0t] %s COLOR_RESET, \ __test_id, $time, msg); // // PASS / FAIL // define TEST_PASS(msg) \ begin \ total_pass; \ $display(COLOR_BOLD_GREEN [PASS][TC%0d][%0t] %s COLOR_RESET, \ __test_id, $time, msg); \ end define TEST_FAIL(msg) \ begin \ total_fail; \ $display(COLOR_BOLD_RED [FAIL][TC%0d][%0t] %s COLOR_RESET, \ __test_id, $time, msg); \ end // // CHECK (最常用) // define TEST_CHECK(cond, msg) \ if (cond) begin \ TEST_PASS(msg) \ end else begin \ TEST_FAIL(msg) \ end // // Summary // define TEST_SUMMARY \ $display(\n); \ $display(COLOR_BOLD_CYAN TEST SUMMARY COLOR_RESET); \ $display(COLOR_BOLD_GREEN TOTAL PASS %0d COLOR_RESET, total_pass); \ $display(COLOR_BOLD_RED TOTAL FAIL %0d COLOR_RESET, total_fail); \ $display(COLOR_BOLD_CYAN COLOR_RESET); // // Optional: Abort on Fail // define TEST_CHECK_FATAL(cond, msg) \ if (!(cond)) begin \ TEST_FAIL(msg) \ $fatal; \ end else begin \ TEST_PASS(msg) \ end endif✅ Testbench 里正确用法必须这样写include test_macro.svh module tb; int total_pass 0; int total_fail 0; initial begin TEST_SUITE_BEGIN(LPDDR6 Initialization) // Test Case 1 TEST_CASE_BEGIN(Power-up Sequence, 1) TEST_STEP(Check reset low) reset_n 0; TEST_CHECK(reset_n 0, RESET_n is LOW) TEST_STEP(Release reset) reset_n 1; TEST_CHECK(reset_n 1, RESET_n is HIGH) // Test Case 2 TEST_CASE_BEGIN(Command Test, 2) TEST_STEP(Send NOP) cs 0; TEST_CHECK(cs 0, CS is LOW) // Summary TEST_SUMMARY #10us; $finish; end endmodule给你一版可以直接放进 testbench 使用的 LPDDR6 上电初始化 task同时支持单通道lpddr6_powerup_seq(1)双通道lpddr6_powerup_seq(2)这张图对应 JEDEC 的Voltage Ramp and Device Initialization / Power Ramp and Initialization Sequence关键参数包括tINIT1200us、tINIT210ns、tINIT34ms、tINIT45nCK、tINIT52us、tZQLATmax(30ns,4nCK)LPDDR6 每个 sub-channel 有独立的CK/CS/CA/WCK/DQ信号。// // LPDDR6 Power-up Sequence Task // Support single channel / dual channel // localparam int LPDDR6_MAX_CH 2; localparam int CA_W 4; localparam int DQ_W 12; localparam time tCK 5000ps; // Example boot CK period: 200MHz localparam time tINIT1 200us; localparam time tINIT2 10ns; localparam time tINIT3 4ms; localparam time tINIT4 5 * tCK; localparam time tINIT5 2us; localparam time tZQLAT 30ns; // max(30ns, 4nCK), example uses 30ns // ------------------------------------------------------------ // LPDDR6 TB driving signals // ch0/ch1 represent sub-channel 0 / sub-channel 1 // ------------------------------------------------------------ logic [LPDDR6_MAX_CH-1:0] ck_t; logic [LPDDR6_MAX_CH-1:0] ck_c; logic [LPDDR6_MAX_CH-1:0] wck_t; logic [LPDDR6_MAX_CH-1:0] wck_c; logic reset_n; // RESET_n is usually device-level logic [LPDDR6_MAX_CH-1:0] cs; logic [LPDDR6_MAX_CH-1:0][CA_W-1:0] ca; // DQ is bidirectional, so use tri output enable tri [LPDDR6_MAX_CH-1:0][DQ_W-1:0] dq; logic [LPDDR6_MAX_CH-1:0] dq_oe; logic [LPDDR6_MAX_CH-1:0][DQ_W-1:0] dq_drv; genvar gi; generate for (gi 0; gi LPDDR6_MAX_CH; gi) begin : GEN_DQ_ASSIGN assign dq[gi] dq_oe[gi] ? dq_drv[gi] : z; end endgenerate// // CK generation // CK_t / CK_c are differential and complementary // task automatic start_ck(input int ch_id); fork forever begin #(tCK/2); ck_t[ch_id] ~ck_t[ch_id]; ck_c[ch_id] ~ck_c[ch_id]; end join_none endtask // // WCK generation // LPDDR6 WCK:CK 2:1 // So WCK period tCK / 2 // task automatic start_wck(input int ch_id); fork forever begin #(tCK/4); wck_t[ch_id] ~wck_t[ch_id]; wck_c[ch_id] ~wck_c[ch_id]; end join_none endtask// // Drive command to one channel // NOTE: // ca_value is placeholder now. // Later you should replace it with real LPDDR6 command encoding. // task automatic lpddr6_drive_cmd_one_ch( input int ch_id, input string cmd_name, input logic [CA_W-1:0] ca_value, input int nck_cycles ); TEST_STEP($sformatf(CH%0d send command: %s, ch_id, cmd_name)) (posedge ck_t[ch_id]); cs[ch_id] 1b1; ca[ch_id] ca_value; repeat (nck_cycles) (posedge ck_t[ch_id]); cs[ch_id] 1b0; ca[ch_id] 0; endtask// // Drive command to active channels // active_ch_num 1: only CH0 // active_ch_num 2: CH0 CH1 // task automatic lpddr6_drive_cmd_active_ch( input int active_ch_num, input string cmd_name, input logic [CA_W-1:0] ca_value, input int nck_cycles ); if (active_ch_num 1) begin lpddr6_drive_cmd_one_ch(0, cmd_name, ca_value, nck_cycles); end else if (active_ch_num 2) begin fork lpddr6_drive_cmd_one_ch(0, cmd_name, ca_value, nck_cycles); lpddr6_drive_cmd_one_ch(1, cmd_name, ca_value, nck_cycles); join end else begin TEST_FAIL(active_ch_num must be 1 or 2) end endtask核心上电初始化 task// // LPDDR6 Voltage Ramp and Device Initialization Sequence // // active_ch_num: // 1 - single channel mode, only CH0 is driven // 2 - dual channel mode, CH0 and CH1 are driven // task automatic lpddr6_powerup_seq(input int active_ch_num); int ch; TEST_CASE_BEGIN(LPDDR6 Voltage Ramp and Device Initialization, 1) if (!(active_ch_num inside {1, 2})) begin TEST_FAIL(active_ch_num must be 1 or 2) return; end // -------------------------------------------------------- // Phase Ta: before / during power ramp // Required: // RESET_n LOW // CS LOW // CA valid low level // CK/WCK stable complementary or inactive // DQ High-Z // -------------------------------------------------------- TEST_STEP(Ta: initialize all driven signals before power ramp) reset_n 1b0; for (ch 0; ch LPDDR6_MAX_CH; ch) begin ck_t[ch] 1b0; ck_c[ch] 1b1; wck_t[ch] 1b0; wck_c[ch] 1b1; cs[ch] 1b0; ca[ch] 0; dq_oe[ch] 1b0; dq_drv[ch] 0; end TEST_CHECK(reset_n 1b0, RESET_n is LOW during power ramp) TEST_CHECK(cs[0] 1b0, CH0 CS is LOW during power ramp) if (active_ch_num 2) begin TEST_CHECK(cs[1] 1b0, CH1 CS is LOW during power ramp) end // -------------------------------------------------------- // Ta - Tb: power ramp // In digital TB, supplies are usually abstracted by delay. // If your DUT has supply-good signals, drive them here. // -------------------------------------------------------- TEST_STEP(Ta to Tb: simulate power ramp until supplies are stable) // Example delay. Real max tINIT0 is 20ms. // You can replace this with your own supply-good handshake. #(1ms); TEST_STEP(Tb: supplies are considered stable) // -------------------------------------------------------- // Tb - Tc: keep RESET_n LOW for tINIT1 // -------------------------------------------------------- TEST_STEP(Tb to Tc: keep RESET_n LOW for tINIT1) #(tINIT1); // -------------------------------------------------------- // Before RESET_n deassertion: // CS must already be LOW for at least tINIT2 // -------------------------------------------------------- TEST_STEP(Wait tINIT2: CS LOW before RESET_n HIGH) #(tINIT2); // -------------------------------------------------------- // Tc: deassert RESET_n // CK_t / CK_c need to toggle or be valid complementary // almost at the same time // -------------------------------------------------------- TEST_STEP(Tc: deassert RESET_n and start CK) reset_n 1b1; if (active_ch_num 1) begin start_ck(0); end if (active_ch_num 2) begin start_ck(1); end #1ps; TEST_CHECK(reset_n 1b1, RESET_n is deasserted HIGH) // -------------------------------------------------------- // Tc - Td: CS must remain LOW for tINIT3 // -------------------------------------------------------- TEST_STEP(Tc to Td: keep CS LOW for tINIT3 after RESET_n HIGH) #(tINIT3); TEST_CHECK(cs[0] 1b0, CH0 CS remains LOW during tINIT3) if (active_ch_num 2) begin TEST_CHECK(cs[1] 1b0, CH1 CS remains LOW during tINIT3) end // -------------------------------------------------------- // Td - Te: CK stable for at least tINIT4 5nCK // -------------------------------------------------------- TEST_STEP(Td to Te: wait tINIT4, stable CK before first CS toggle) repeat (5) (posedge ck_t[0]); // -------------------------------------------------------- // Te: first CS toggle with NOP // -------------------------------------------------------- TEST_STEP(Te: issue first NOP command) lpddr6_drive_cmd_active_ch( active_ch_num, NOP, 4b0000, 2 ); // -------------------------------------------------------- // Te - Tf: wait tINIT5 before first MRW/MRR // -------------------------------------------------------- TEST_STEP(Te to Tf: wait tINIT5 before first MRW/MRR) #(tINIT5); // -------------------------------------------------------- // Tf: issue initial MRW / MRR // These CA values are placeholders. // Replace with real command truth table encoding later. // -------------------------------------------------------- TEST_STEP(Tf: issue initial MRW/MRR commands) lpddr6_drive_cmd_active_ch( active_ch_num, MRW_INIT, 4b0001, 2 ); lpddr6_drive_cmd_active_ch( active_ch_num, MRR_CHECK, 4b0010, 2 ); // -------------------------------------------------------- // ZQ Latch command // Initial ZQ calibration is automatically started after RESET_n high. // Controller should issue ZQ Cal Latch command later. // -------------------------------------------------------- TEST_STEP(Issue MPC ZQ Calibration Latch) lpddr6_drive_cmd_active_ch( active_ch_num, MPC_ZQ_CAL_LATCH, 4b0011, 2 ); TEST_STEP(Wait tZQLAT after ZQ Calibration Latch) #(tZQLAT); // -------------------------------------------------------- // After ZQ Latch: // Optional training may start. // Start WCK before WCK/DQ related training. // -------------------------------------------------------- TEST_STEP(Start WCK for later training) if (active_ch_num 1) begin start_wck(0); end if (active_ch_num 2) begin start_wck(1); end // -------------------------------------------------------- // Simplified optional training sequence // -------------------------------------------------------- TEST_STEP(Optional Training: Command Bus Training) lpddr6_drive_cmd_active_ch(active_ch_num, ENTER_CBT, 4b0100, 2); lpddr6_drive_cmd_active_ch(active_ch_num, CBT_PATTERN, 4b0101, 8); lpddr6_drive_cmd_active_ch(active_ch_num, EXIT_CBT, 4b0110, 2); TEST_STEP(Optional Training: WCK2CK Leveling) lpddr6_drive_cmd_active_ch(active_ch_num, ENTER_WCK2CK_LEVELING, 4b0111, 2); lpddr6_drive_cmd_active_ch(active_ch_num, WCK2CK_LEVELING, 4b1000, 8); lpddr6_drive_cmd_active_ch(active_ch_num, EXIT_WCK2CK_LEVELING, 4b1001, 2); TEST_STEP(Optional Training: DQ Training) lpddr6_drive_cmd_active_ch(active_ch_num, DQ_TRAINING, 4b1010, 8); TEST_PASS(LPDDR6 power-up initialization sequence finished) endtask在 testbench 里这样调用initial begin TEST_SUITE_BEGIN(LPDDR6 Initialization Test) // 单通道只驱动 CH0 lpddr6_powerup_seq(1); // 或者双通道同时驱动 CH0 CH1 // lpddr6_powerup_seq(2); TEST_SUMMARY #10us; $finish; end

相关文章:

个人学习笔记12

最终版 test_macro.svhifndef TEST_MACRO_SVH define TEST_MACRO_SVH// // Color Definition // define COLOR_RESET "\033[0m" define COLOR_BOLD_BLUE "\033[1;34m" define COLOR_BOLD_GREEN "\033[1;32m" define COLOR_BOLD…...

Oracle11g服务端安装包

下载地址:https://pan.baidu.com/s/1coKaGW1z0aqtV6pZYYgs_w?pwdhaev 一、前言 在数据库学习、项目本地测试、内网环境部署场景中,Oracle 11g 凭借稳定性强、占用资源低、企业普及率高,一直是开发与运维人员常用的经典版本。 很多新手在搭…...

今天力扣周赛 , 就做出来了三道题 . 我真的也是废了 ... (简短版)

今天吃的 香蕉 , 梨 , 绿豆沙 , 煎饺 , 黑米粥. 马上五一放假了. 大二 All in Java 大三 All in AI 晚上 自己搞了: 观看技术直播 AI 大模型应用开发 Python持续学习 AI 相关知识…进程就是正在运行的程序(比如QQ , 浏览器)今天力扣周赛 , 就做出来了三道题 . 我真的也是…...

第一个作业

我是一名大一新生,现在刚开始学习编程C语言,我学习编程不仅是为了学校的考试,更想精通编程语言,使之成为自己得力的助手。我打算每日都练习一点编程,除了自学教材,还会结合B站上的视频进行学习,…...

《Science》:智能体引领社会智能跃迁

导语Google团队联合芝加哥大学、UCSD学者在 Science 发表论文,颠覆了AI圈几十年的“奇点叙事”。他们发现,DeepSeek-R1 等推理模型会自发产生内部多角色辩论,使准确率从27.1%飙升至54.8%。论文指出,下一轮智能爆发将像城市生长&am…...

过度依赖 AI 对中小学生的危害:弱化思考,扼杀创新

过度依赖 AI 对中小学生的危害:弱化思考,扼杀创新“工具的意义在于延伸人的能力,而非替代人的思考。当学生把学习的目的从’理解世界’变成’获取答案’,教育便已悄然失守。”📌 引言:AI 时代的学习"捷…...

【文献解析】TRPM channels in human cancers: regulatory mechanism and therapeutic prospects

1. 领域背景与文献引入 文献英文标题:TRPM channels in human cancers: regulatory mechanism and therapeutic prospects;发表期刊:Biomarker Research;影响因子:4.518(2023年);研…...

记录使用C#编程中遇到的一个小bug

近期在写程序时使用NumericUpDown进行一个整数的输入。如果用户输入小数NumericUpDown会自动四舍五入成整数显示在界面,但是实际的value还是用户输入的实际值。我在处理这个数据时,使用了Convert.ToInt32()对输入的值进行了转换。出现了一个神奇的问题&a…...

Bash上传代码到github命令

本教程详细介绍如何将本地项目通过Bash 终端上传代码到 GitHub 准备工作 1. 安装 Git 一款免费、开源的「本地版本管理工具」,只负责一件事:追踪你文件夹里所有文件的修改、保存版本、记录改动。 winget install Git.Git集成右键上下文菜单参照→bash…...

揭秘HotGo插件化架构:从微内核设计到企业级扩展的实战指南

揭秘HotGo插件化架构:从微内核设计到企业级扩展的实战指南 【免费下载链接】hotgo HotGo 是一个基于 vue 和 goframe2.0 开发的全栈前后端分离的开发基础平台和移动应用平台,集成jwt鉴权,动态路由,动态菜单,casbin鉴权…...

暗黑3智能宏工具D3KeyHelper:一键解放双手的游戏效率革命

暗黑3智能宏工具D3KeyHelper:一键解放双手的游戏效率革命 【免费下载链接】D3keyHelper D3KeyHelper是一个有图形界面,可自定义配置的暗黑3鼠标宏工具。 项目地址: https://gitcode.com/gh_mirrors/d3/D3keyHelper 还在为暗黑3中重复的技能操作感…...

DeepSeek-V4-Pro模型配置解读

参考:https://modelscope.cn/models/deepseek-ai/DeepSeek-V4-Pro/file/view/master/config.json?status1一、基础模型标识"architectures": ["DeepseekV4ForCausalLM"], "model_type": "deepseek_v4", "transformers_version&q…...

解密中兴光猫工厂模式:zteOnu工具深度实战与安全渗透技术

解密中兴光猫工厂模式:zteOnu工具深度实战与安全渗透技术 【免费下载链接】zteOnu A tool that can open ZTE onu device factory mode 项目地址: https://gitcode.com/gh_mirrors/zt/zteOnu 中兴光猫作为家庭和企业网络的核心入口设备,其隐藏的工…...

HX711压力传感器模块的5个常见调试“坑”及解决方法(基于STM32 HAL库)

HX711压力传感器模块的5个常见调试“坑”及解决方法(基于STM32 HAL库) 当你第一次尝试在STM32上驱动HX711压力传感器时,可能会遇到各种令人困惑的问题。作为一名经历过无数次深夜调试的工程师,我想分享几个最常见的"坑"…...

浮点运算单元形式化验证:挑战与方法

1. 浮点运算形式化验证的核心挑战浮点运算单元(FPU)的验证一直是硬件设计中最具挑战性的任务之一。与整数运算不同,浮点数的IEEE-754标准定义了复杂的异常处理机制(如溢出、下溢、非规格化数等),使得验证过…...

别再死记硬背了!用一张图搞懂SAR成像里的‘方位向’、‘斜距’和‘零多普勒’

用视觉化思维破解SAR成像核心概念:方位向、斜距与零多普勒的几何奥秘 当第一次接触合成孔径雷达(SAR)成像时,许多工程师都会被那些抽象的空间几何术语搞得晕头转向。方位向、斜距平面、零多普勒面...这些概念如果仅靠文字定义去记…...

Tree-GRPO:用可微决策树实现可解释强化学习策略优化

1. 项目概述:当强化学习遇上决策树最近在折腾一个智能体决策优化的项目,偶然间在GitHub上看到了AMAP-ML团队开源的Tree-GRPO项目。这个标题乍一看有点“缝合怪”的味道,把“树”和“GRPO”这两个看似不搭界的东西组合在了一起。GRPO&#xff…...

无需网络依赖:Hunyuan-MT 7B纯本地翻译方案搭建教程

无需网络依赖:Hunyuan-MT 7B纯本地翻译方案搭建教程 1. 项目背景与核心优势 在全球化协作日益频繁的今天,语言障碍仍然是跨文化交流的主要瓶颈。传统在线翻译服务存在三大痛点:网络依赖导致离线场景不可用、商业API存在隐私泄露风险、小语种…...

AI像素画创作:pixel-agents智能体框架原理与实践指南

1. 项目概述与核心价值 最近在探索AI与创意工具结合的领域时,我遇到了一个非常有意思的项目: pablodelucca/pixel-agents 。乍一看这个标题,你可能会联想到像素艺术或者某种智能体,没错,它正是将这两者结合的一个开源…...

AgenticHub:macOS原生AI工具资源管理器,高效管理MCP服务器与Agent技能

1. 项目概述:一个为AI开发者打造的macOS中心化工具如果你和我一样,每天都在和Claude、Cursor这类AI助手打交道,并且热衷于探索各种MCP服务器和Agent技能来扩展它们的能力,那你一定体会过那种“信息过载”的烦恼。官方MCP注册表里有…...

Python asyncio 信号处理机制

Python asyncio信号处理:异步编程的优雅控制 在现代异步编程中,Python的asyncio库为开发者提供了强大的协程支持,而信号处理则是其关键能力之一。信号(Signal)是操作系统与进程通信的重要机制,例如SIGINT&…...

西门子博途V17程序块加密实战:从‘专有技术保护’到‘防拷贝’,手把手教你保护PLC代码(附避坑点)

西门子博途V17程序块加密实战:从‘专有技术保护’到‘防拷贝’,手把手教你保护PLC代码(附避坑点) 在工业自动化领域,PLC程序往往承载着核心工艺逻辑和关键技术细节。一位资深工程师曾分享过他的经历:某个经…...

法律AI实战:基于RAG与大模型微调构建智能法律助手

1. 项目概述:当法律遇上AI,一场关于记忆与模仿的深度探索最近在开源社区里,一个名为memovai/mimiclaw的项目引起了我的注意。乍一看这个标题,它像是一个密码,由两个核心词拼接而成:“memovai”和“mimiclaw…...

Stable-Diffusion-V1-5 开发环境问题排查:GitHub访问与依赖下载加速方案

Stable-Diffusion-V1-5 开发环境问题排查:GitHub访问与依赖下载加速方案 你是不是也遇到过这种情况?兴致勃勃地想搭建一个Stable Diffusion V1.5的开发环境,准备大展身手,结果第一步就被卡住了。git clone 一个仓库,进…...

机器学习战略:从失败案例看问题定义的重要性

1. 为什么机器学习战略比技术本身更重要?在过去的十年里,我见过太多机器学习项目以失败告终——不是因为模型不够精准,而是因为从一开始就走错了方向。记得2018年参与的一个电商推荐系统项目,团队花了六个月优化AUC指标&#xff0…...

Abaqus新手避坑指南:从建模到网格划分,这些操作细节千万别忽略

Abaqus新手避坑指南:从建模到网格划分的关键细节解析 刚接触Abaqus的工程师们常常会陷入一种困境——明明按照教程步骤操作,却总在莫名其妙的地方报错或得到不合理的结果。这往往不是因为软件本身的问题,而是那些容易被忽略的操作细节在作祟。…...

RWKV7-1.5B-world应用场景:智能硬件语音助手后端——低资源+高响应速度组合

RWKV7-1.5B-world应用场景:智能硬件语音助手后端——低资源高响应速度组合 1. 模型概述 RWKV7-1.5B-world是基于第7代RWKV架构的轻量级双语对话模型,专为资源受限环境下的智能硬件应用而设计。这个15亿参数的模型采用创新的线性注意力机制,…...

u-blox MAYA-W4三模物联网模块技术解析与应用

1. u-blox MAYA-W4三模物联网模块深度解析在工业物联网和智能家居领域,无线连接模块的性能和可靠性直接决定了终端设备的用户体验。去年我们评测的u-blox MAYA-W3模块采用了Infineon的三频段独立芯片方案,而今年新推出的MAYA-W4系列则带来了更具突破性的…...

手把手教你为UniApp微信小程序项目配置安全的WSS WebSocket连接(Vue3版)

从零构建UniApp微信小程序的WSS WebSocket全链路配置指南 微信小程序作为日活超4亿的超级入口,其安全策略要求所有网络请求必须通过HTTPS加密传输,这对WebSocket连接提出了WSS的强制要求。许多全栈开发者在项目上线时,往往卡在如何从普通WS服…...

AI生成技术架构图:excalidraw-diagram-skill实现视觉验证与自动化设计

1. 项目概述与核心价值最近在折腾AI编程助手,发现一个挺有意思的痛点:让AI画技术架构图。你肯定也遇到过,让Claude Code或者Cursor这类工具画个系统流程图,它要么给你整一堆规规矩矩的方框加箭头,要么生成的Excalidraw…...