E8 后端物理设计和流片准备

你已经将NPC接入SoC了, 验证了SoC系统的功能, 也测量了NPC在SoC上的性能表现. 此外, 你也已经完成了NPC的综合, 生成了网表, 距离流片的目标已经很接近了. 剩余的工作就是开展后端物理设计, 从网表生成可流片的GDS版图.

需要说明的是, 在流片的芯片中, 我们会负责提供正确的ysyxSoC, 你生成的版图将会和其他学生的版图一同接入到我们提供的ysyxSoC中. 也就是说, 在将要流片的芯片中, 所有学生将共享同一个SoC. 因此, 你只需要单独对NPC进行综合与后端物理设计即可, 这个过程无需包含ysyxSoC. 之前你将NPC接入ysyxSoC, 更多是为了测试NPC能否在ysyxSoC中正确仿真.

不过, 在进行后端物理设计之前, 你还需要完成一些前端的准备工作, 来排除NPC中一些潜在的问题.

前端准备工作

开放NPC的地址空间

流片环境所使用的SoC会集成比ysyxSoC更多的设备, 从而让你的NPC在回片后具有更加丰富的展示效果. 但是, 如果NPC提前拦截了相应地址空间的访问, NPC将无法在流片后访问这些设备. 因此, 我们建议你在NPC中开放所有的地址空间, 让所有地址的读写请求都通过NPC对外的SimpleBus总线接口发送出去.

开放NPC的地址空间

检查你的NPC实现, 看是否开放了所有地址空间. 如果你的NPC拦截了部分地址空间的访问, 你需要修改NPC的代码.

去除下降沿触发的时钟

上升沿和下降沿混用, 会导致时序收敛更加困难, 增加后端物理实现的难度. 通常来说, 在处理器内部, 并不需要使用下降沿触发的时钟.

去除下降沿触发的时钟

你需要检查你的代码中是否包含下降沿触发的时钟, 若有, 你需要修改相应模块中的代码去除它们.

去除锁存器

在同步时序逻辑电路中, 所有存储单元的访问都受时钟控制. 但锁存器的写入不受时钟驱动, 时序分析工具难以对其进行分析, 因此一般不在同步时序逻辑电路中使用.

去除锁存器

在ICsprout55中, 锁存器单元的命名以LAT*开头. 你需要检查综合的网表中是否包含锁存器单元, 若有, 你可以根据网表中注释中的源文件位置, 找到相应的RTL代码并去除它们.

Chisel福利

Chisel生成的Verilog代码描述的都是同步时序逻辑电路, 如果你使用Chisel开发, 你不必担心会生成锁存器.

命名修改

新版流片集成方案不要求大家进行命名修改

在新版流片集成方案中, 大家完成物理设计后, 会将版图集成到一个SoC中. 在这种基于版图的集成方案中, 大家在RTL代码中的命名并不会互相影响. 因此, 原则上大家不需要修改RTL代码中的命名, 这一小节的内容也不需要完成.

不过, 我们正在逐渐过渡到新版的流片集成方案. 在过渡阶段, 这部分讲义内容仍然保留, 供需要的时候参考.

我们会将多个同学的代码集成到同一个SoC中(这是旧的集成方案), 如果代码的模块名相同, 会导致EDA工具报告模块重复定义的错误. 为了解决这个问题, 我们要求大家进行以下修改:

  1. 将CPU代码合并到一个.v文件, 文件名为ysyx_8位学号.v, 如ysyx_22040228.v
    • 在Linux上可通过cat命令实现:
      $> cat CPU.v ALU.v regs.v ... > ysyx_22040228.v
      
  2. 将CPU顶层命名修改为ysyx_8位学号,如ysyx_22040228
  3. 为CPU内所有用define定义的变量添加前缀ysyx_8位学号_, 如 `define SIZE 5需要修改为 `define ysyx_22040228_SIZE 5; 如果你使用Chisel, 你不必进行这部分的修改
  4. 为CPU内的所有模块名添加前缀ysyx_8位学号_, 如module ALU修改为module ysyx_22040228_ALU

Chisel福利(2)

如果你使用Chisel开发, 可以采用Chisel的module prefixing特性来自动添加模块名前缀, 具体使用方式可参考相关文档和示例在新窗口中打开. 如果你使用Verilog/SystemVerilog开发, 目前暂时无法进行模块名前缀的自动添加, 请手动进行添加.

代码静态检查

Verilator可以对verilog进行代码静态检查, 并提示代码中潜在的错误风险之处, 修复这些问题有助于提升代码的正确性. 具体地, 可以通过verilator的--lint-only选项来进行上述检查.

为了让verilator进行尽可能多的检查工作, 可以添加-Wall选项. verilator的手册在新窗口中打开记录了所有warning的含义, 原则上来说, 你需要尽可能清除它们, 来让你的代码变得更规范, 除了以下两种warning:

  1. DECLFILENAME的warning与代码逻辑无关, 可通过添加-Wno-DECLFILENAME来忽略它.
  2. 对于UNUSED相关的warning, 有的是因为输入端口未使用, 确认后可以忽略; 有的可能是因为你的代码编写不规范, 你需要仔细确认其原因. 如果你决定忽略一个warning, 你需要清楚这可能会引起什么问题, 并对你自己的决定负责.

借助verilator检查RTL代码

通过verilator的--lint-only选项检查代码, 查阅verilator报告的信息, 逐项确认是否需要修改相应的RTL代码.

Chisel福利(3)

Chisel生成的Verilog代码通常是符合规编码规范的, 但也会出现信号和位宽相关的UNUSED warning. 如果你使用Chisel开发, 在这部分工作中你会稍微轻松一些, 但我们仍然建议你仔细核对每个warning.

触发器的复位和四值仿真

对触发器进行复位的必要性

系统的启动分冷启动和热启动, 其中冷启动是指系统在断电状态下进行上电和复位, 而热启动则是指在上电状态下直接进行复位. 我们知道电路的状态由时序逻辑元件的状态决定, 因此我们期望电路在复位后能进入一个预期的正确状态, 然后从这个状态开始工作. 要实现这一点, 就需要对时序逻辑元件指定复位值.

一个方案是对所有时序逻辑元件进行复位, 保证无论是冷启动还是热启动, 系统都能在复位后进入完全一致的状态. 但对于包含随机存储器的电路来说, 这是难以做到的, 因为随机存储器一般不提供复位功能, 不管是集成在CPU内部的SRAM, 还是位于CPU外部的DRAM. 这意味着, 在热启动的场景下, 随机存储器中存储阵列的状态不受复位信号的影响, 其中已经存储的数据会被带进下一次复位中. 因此, 计算机的软硬件系统必须保证, 无论复位后随机存储器中存储什么数据, 系统都应该能正确工作. 换句话说, 系统复位时的行为必须设计成与随机存储器所存储的内容无关.

如果不考虑随机存储器, 剩下的时序逻辑元件就是触发器. 对所有触发器进行复位固然可以使得系统以更大的概率进入正确的状态, 但这也可能会带来额外的延迟和一定的面积开销. 一方面, 布线时需要将复位信号传递到所有触发器中, 因此复位信号的传播延迟也会更高; 另一方面, 触发器的复位功能也需要占用一定的门电路, 这些门电路也会占用一定的面积.

在真实的项目中, 一般是保证系统在复位后能正确工作的条件下, 仅仅对触发器的一个最小子集进行复位. 至于那些不需要进行复位的触发器, 它们的状态不受复位信号的影响, 因此系统的复位信号到来时, 它们仍然保留之前的状态. 只要一个触发器存储的值不影响系统在复位后的行为, 它就不需要进行复位.

通常来说, 不需要进行复位的触发器主要有两类:

  1. 软件在使用之前可对其初始化的寄存器. 这意味着这些寄存器需要是软件可见的, 换句话说, 它们是由ISA规范定义的. 例如, 对于除了零寄存器以外的通用寄存器, RISC-V规范约定, 复位后其值是未定义的, 因此软件在读出它们之前, 应该对这些通用寄存器进行写入, 确保其中已经存放一个有意义的值. 事实上, 相关ISA规范将这些寄存器的初值约定为未定义, 本质上是将相关寄存器的初始化从硬件层面移动到软件层面, 从而优化了电路的面积和延迟.
  2. 在数据通路上与控制信号关联的触发器. 通常来说, 类似valid, en等控制信号会用于指示相应的数据信号是否有效, 如果无效, 这些控制信号所连接的下游模块一般不会使用或存储相应的数据信号. 因此, 数据通路上的大部分触发器可以不进行复位, 只要保证电路在产生与其关联的控制信号时, 相应的触发器已经包含有效的数据即可.

对不需要进行复位的触发器进行了复位, 最多是浪费了面积, 增加了复位信号的传播延迟, 不会对电路的正确性产生影响; 但如果没有对需要复位的触发器进行复位, 就可能会使得电路在复位后无法正确工作. 因此, 后者的情况是需要避免的.

四值仿真工具iverilog

之前我们一直使用verilator进行仿真, 它是一个二值仿真工具, 所有信号的值只包含01两种情况, 因此所有触发器在复位时都有一个具体的值, 不能很好地检查上述问题.

而在支持四值仿真的RTL仿真器中, 可以通过不定态X来表示一个未复位触发器的初值. X信号参与门电路运算时, 结果也可能会是X信号, 因此它可以在电路中进行传播. 如果存在一个需要复位但未进行复位的触发器, X信号就可能会在电路中大范围传播, 使得其他触发器的值也为X, 无法精确表示一个信号的值, 最终使得电路收敛到另一个与预期的正确状态不同的状态, 处理器上的程序将无法得到预期的运行结果. 相反, 如果不存在这样的触发器, X信号在电路中的传播就会被控制信号遏制, 并随着有效数据的更新, X信号将会逐渐减少, 最终使得电路收敛到预期的正确状态.

iverilog的全称是ICARUS verilog在新窗口中打开, 它是一款支持四值仿真的RTL仿真器, 我们可以使用它来检查是否存在需要复位但还未进行复位的触发器. 你之前现在下载开源CAD工具套件oss-cad-suite的时候已经获得它了.

尝试使用iverilog

参考iverilog的文档在新窗口中打开, 在iverilog中运行一个简单的示例.

由于我们会保证流片时所使用的ysyxSoC的正确性, 你目前只需要在iverilog上单独仿真NPC, 并在其上运行minirv-npc的AM程序即可.

不过, 由于iverilog暂不支持DPI-C, 驱动仿真的方式也与verilator有所不同, 因此我们需要对RTL代码和仿真环境进行一些改动. 使用iverilog进行编译时, 会自动定义宏__ICARUS__, 因此你可以把这些改动用条件编译语句包含起来, 从而使得你的代码同时支持verilator和iverilog进行仿真.

通过VPI机制实现访存

在iverilog中, 我们可以通过VPI机制在新窗口中打开来实现verilog和C代码之间的通信. 你可以先阅读相关文档, 了解如何在iverilog中使用VPI机制.

初步了解VPI机制后, 我们就可以考虑如何在iverilog中通过VPI机制实现访存. 一个想法是, 通过VPI机制分别注册一个名为$pmem_read$pmem_write的系统任务, 将verilog代码中对DPI-C函数pmem_read()pmem_write()的调用, 改写为对系统任务$pmem_read$pmem_write的调用. 然后在为这些系统任务注册的处理函数(C代码)中, 调用之前已经实现的C函数pmem_read()pmem_write(), 这些C函数最终会访问C代码中用于模拟内存的数组.

但还有一些问题需要解决:

  • 如何在系统任务的处理函数中获取verilog代码传递的参数?
  • 如何让$pmem_read返回通过pmem_read()读出的值?
  • 如何在开始仿真之前, 将需要运行的程序加载到数组中?

iverilog文档中对VPI机制的介绍并未包含这些内容, 你需要STFW了解VPI机制的更多功能. 如果需要, 你也可以通过Verilog标准手册在新窗口中打开来查阅所需内容.

检查未复位触发器对电路行为的影响

除了通过VPI机制实现访存, 你还需要进行如下改动:

  • 让NPC从0x80000000开始执行程序, 可以考虑但不限于以下方法:
    • 将PC的复位值改为0x80000000
    • 将PC的复位值保持0x30000000, 但在0x30000000的位置放置若干指令, NPC通过这些指令马上跳转到0x80000000, 从而执行riscv32e-npc的AM程序
  • 识别出ebreak指令后, 可以通过$display()输出信息, 并通过$finish$fatal结束仿真
  • 关闭DiffTest机制
  • 编写一个简单的仿真顶层, 在其中实例化时钟和复位信号, 并驱动NPC的仿真, 例如:
    module iverilog_top();
      reg clock;
      reg reset;
      initial begin
        clock = 0;
        reset = 1;
        # 10 reset = 0;
      end
      always # 1 clock = ~clock;
      Top top(clock, reset);
    endmodule
    
    其中, Top模块中包含了NPC和存储器模块, 存储器模块通过VPI机制实现访存

完成上述改动后, 你就可以尝试用iverilog进行编译了. 不过你需要注意如下事项:

  • 虽然iverilog可以自动识别顶层模块, 但我们还是建议你通过-s选项显示指定顶层模块, 避免iverilog识别到的顶层模块不符合预期
  • iverilog支持的语法比verilator要少, 我们建议你通过-g2012选项来采用较新的语言标准, 但你还是可能会遇到verilator编译通过, iverilog编译不通过的情况, 你需要根据报错信息修改你的代码
    • 特别地, 如果你使用Chisel, 你还需要给firtool添加选项 --lowering-options=disallowLocalVariables,disallowPackedArrays, 来屏蔽一些iverilog不支持的语言特性
  • 你可能还会遇到以下报错信息, 该信息可忽略:
    sorry: constant selects in always_* processes are not currently supported (all bits will be included).
    
  • 由于目前无法使用DiffTest, 如果仿真结果与预期不符, 你需要通过波形来诊断问题. 具体地, 你可以阅读iverilog中关于查看波形的文档在新窗口中打开, 来了解如何在iverilog中生成波形
    • 但我们建议你先通过verilator和DiffTest排除尽可能多的问题, 然后再使用iverilog进行仿真
    • 你也可以尝试在iverilog的仿真环境中通过VPI机制实现DiffTest

通过四值仿真检查X信号传播问题

在iverilog中仿真NPC并运行microbench等程序. 如果程序运行失败, 你需要修改相应的RTL代码来解决X信号的传播问题.

网表仿真

由于Verilog本质上是一门事件驱动的建模语言, 可综合的Verilog只是其中一个子集, 因此Verilog仿真器可能会接受一些不可综合的代码. 这并不是Verilog仿真器的bug, 它只是按照Verilog标准手册在新窗口中打开中定义的行为来进行仿真. 显然, 在RTL设计中, 我们并不希望编写出这样的代码.

为了检查项目中是否包含不可综合代码, 一个方案是对综合后的电路进行仿真. 如果项目中包含不可综合代码, 综合后的电路可能与综合前不一致, 从而帮助我们发现相关错误.

综合的步骤是将RTL代码转换成逻辑等价的标准单元, 描述这些标准单元之间的连接关系的文件称为网表. 在网表中, 标准单元是以模块的方式进行实例化的, 因此, 要对网表进行仿真, 就需要提供这些标准单元的行为级仿真模型. 事实上, ICsprout55 PDK项目中已经提供了相应的仿真模型, 具体位于:

  • icsprout55-pdk/IP/STD_cell/ics55_LLSC_H7C_V1p10C100/ics55_LLSC_H7CH/verilog/ics55_LLSC_H7CH.v
  • icsprout55-pdk/IP/STD_cell/ics55_LLSC_H7C_V1p10C100/ics55_LLSC_H7CR/verilog/ics55_LLSC_H7CR.v
  • icsprout55-pdk/IP/STD_cell/ics55_LLSC_H7C_V1p10C100/ics55_LLSC_H7CL/verilog/ics55_LLSC_H7CL.v

更新PDK

我们更新了ICsprout55 PDK中的仿真模型, 修复了verilator无法正确仿真的问题. 如果你在2026年8月21日14:30:00之前获取ICsprout55 PDK, 请删除PDK并重新获取, 具体可参考之前获取PDK的操作.

我们先考虑使用verilator进行网表仿真, 具体的仿真目标是, 用综合后的NPC网表模块替代综合前的NPC RTL模块:

+--------------------------------+
| Top                            |
|  +-------------+       +-----+ |
|  | NPC-netlist | <---> | Mem | |
|  +-------------+       +-----+ |
+--------------------------------+

具体地, 我们需要对如下文件进行仿真:

  1. NPC综合后的网表文件. 你需要使用命名为xxx_Synthesis_sim.v.gz的网表文件, 但它是经过压缩的, RTL仿真器无法直接读取, 因此你还需要使用gunzip命令对其进行解压缩
  2. 用DPI-C实现访存的存储器模块
  3. 上文提到的标准单元的行为级仿真模型文件

需要说明的是, ECC在综合后会产生两个网表文件, 分别用于两种不同的场合. 其中, 命名为xxx_Synthesis_sim.v.gz是面向仿真的网表, 其顶层模块端口信号和综合之前的顶层模块完全一致, 用于直接替代综合前的RTL模块, 易于进行网表仿真; 命名为xxx_Synthesis.v.gz是面向后端物理设计的网表, 其顶层模块的向量端口被拆分成多个单bit的端口, 易于被后端EDA工具处理.

标准单元的行为级仿真模型文件中还包含一些时序检查相关的语句. 但我们目前只需要进行功能仿真, 无需关心这些语句, 因此需要给verilator的命令行额外添加如下编译选项:

  • --timescale "1ns/1ns"
  • --no-timing
  • -D__VERILATOR__
  • -Dfunctional

由于综合过程无法识别DPI-C, 因此我们无法通过DPI-C机制在网表中和C代码之间进行交互. 此外, 由于通用寄存器堆已经被综合成一个个触发器, 我们很难对网表中的这些触发器进行拼接, 来得到通用寄存器堆的状态. 因此, 在网表仿真中很难通过DiffTest定位问题. 上述这两点都会给网表仿真的调试带来新的挑战. 正因如此, 我们建议你先用verilator进行RTL仿真, 通过DiffTest排除尽可能多的问题, 然后再进行网表仿真.

用verilator进行网表仿真

按照上述要求用verilator进行网表仿真, 尝试在NPC的网表上运行microbench等程序.

Chisel福利(4)

Chisel生成的Verilog代码都是可综合的, 如果你使用Chisel开发, 网表仿真大概率会直接成功, 但我们仍然建议你不要因此跳过网表仿真.

最后, 我们还需要用iverilog进行网表仿真, 来检查综合得到的网表是否存在X态信号传播导致无法成功仿真的问题. 由于网表中的代码仅仅是标准单元的实例化, 而之前你已经通过VPI机制实现了访存, 因此, 为了使用iverilog进行仿真, 你无需进行代码上的调整.

用iverilog进行网表仿真

用iverilog进行网表仿真, 尝试在NPC的网表上运行microbench等程序.

再次检查你的代码

如果你在上述过程中修改了代码, 请重新进行上述检查, 避免在修改代码的途中再次引入了不符合要求的代码.

后端物理设计

EDA工具可能会频繁迭代更新

ECC和ECOS Studio于2026年8月首次对外发布, 发布后ECOS团队收到大量反馈和改进意见. 因此在2026年下半年, 预计ECC和ECOS Studio会频繁迭代, 以修复各种问题, 同时也支持更多更方便的功能. 讲义中的相关内容也会随之更新, 希望能尽快给大家带来更好的使用体验.

如果你在使用ECC和ECOS Studio的过程中遇到Bug, 或者对这两款工具有任何建议, 欢迎通过github的issue功能提出你的反馈:

初步验证网表功能的正确性之后, 就可以进行后端物理设计了.

获取ECOS Studio

我们使用ECOS Studio在新窗口中打开这款GUI工具来开展后端物理设计. 后端物理设计和芯片的物理视角有很强的关联, 如果你是这方面的初学者, 可以借助ECSO Studio中的可视化功能进一步了解后端物理设计的过程.

首先你需要获取ECOS Studio v0.1.0-alpha.9在新窗口中打开. 点击链接后, 在页面下方找到Assets列表, 点击后缀为AppImage的链接下载. .AppImage是一个可执行文件, 下载完成后, 需要先为其添加可执行权限:

chmod a+x ECOS-Studio_..._x86_64.AppImage

你需要根据版本号补充上述文件名. 添加可执行权限后, 可以直接执行它:

./ECOS-Studio_..._x86_64.AppImage

用ECOS Studio进行后端物理设计

打开ECOS Studio后, 点击Backend Design, 然后点击New Workspace. 在弹出的导向窗口中进行如下操作:

  1. Project Setup
    • 点击Create Project
      • 输入Project Name
      • 指定Project Parent Path
    • 点击Continue
  2. Basic Info
    • 输入Workspace Name
    • 点击Continue
  3. Flow Setup
    • START STEP的下拉菜单中选择Floorplan
      • 此操作表示跳过Synthesis步骤, 因为我们之前已经通过ECC进行综合并得到了网表
    • 点击Continue
  4. Design Files
    • 点击Import Verilog, 选择之前通过ECC综合得到的网表文件, 如light/runs/default/Synthesis_yosys/output/light_Synthesis.v.gz.
      • 注意, 此处应该选择面向后端物理设计的网表文件, 即名称不含_sim的文件
    • 点击Continue
  5. PDK Config
    • 查看Process Design Kit信息框
      • 如果ECOS Studio自动识别到ICsprout55 PDK的路径, 请检查路径是否正确
      • 如果ECOS Studio并未自动识别, 点击Import PDK并手动选择ICsprout55 PDK的路径
    • Config Mode信息框中选择Default Config
    • 点击Continue
  6. Spec Setting
    • 输入Design Name, 可与代码中的顶层模块名称不同
    • 输入Top Module Name, 必须与代码中的顶层模块名称一致
    • 输入Clock Signal Name, 必须与代码中顶层模块的时钟信号名称一致
    • 其他参数采用默认配置即可
      • 但你可以关注Frequency max [MHz]Origin Core Utilization这两个参数, 前者表示芯片的目标频率, 后者表示芯片面积的利用率
    • 点击Create Workspace

完成上述操作后, ECOS Studio将会创建工作空间, 并弹出Step Configuration窗口. 目前我们不必单独配置每个步骤的细节, 点击右上角的关闭按钮即可. 关闭Step Configuration窗口后, 我们位于工作空间的DASHBOARD页面. 界面左侧还有很多子页面可以点击查看, 目前我们先不查看其他子页面. 在DASHBOARD页面右上方的Flow status区域有一个开始按钮, 点击后会依次运行所有步骤.

所有步骤都成功执行后, 就可以查看后端物理设计的结果了. 在DASHBOARD页面左下方的Key Metrics区域展示了设计结果的一些关键指标, 一些关键指标如下:

  • Die Area - 芯片面积, 设置利用率越小, Die Area则越大
  • Frequency - 完成后端物理设计后的频率
    • 这个数据会比综合时报告的频率低很多, 主要有两个原因
      1. 综合报告的频率是根据标准单元本身的延迟来计算的, 而后端物理设计结果中的频率还算上了标准单元之间走线的延迟
      2. 综合报告的频率是假设芯片在普通环境中工作来计算的, 而后端物理设计结果中的频率是假设芯片在极端环境中工作来计算的, 因此比综合报告的频率悲观很多

所有步骤都成功执行后, 就可以导出签核包了. 具体地, 点击左上角菜单栏的File->Export Signoff Package, 在弹出的Signoff Package Review窗口中了解将要导出的资源信息. 在窗口的Risk Details信息栏中可能会提示缺少config.macro_locations, 这是符合预期的, 因为目前我们的设计中不包含宏单元. 除此之外, Risk Details信息栏不应该提示其他警告或错误. 点击右下方的Export Package按钮, 选择导出路径, 即可完成签核包的导出.

如果无法点击菜单栏的Export Signoff Package, 或无法点击Signoff Package Review窗口中的Export Package按钮, 通常是因为后端物理设计的结果没有达到及格标准. 此时, 可以找到工作空间的Checklist区域(在Flow status区域的左侧), 点击区域右下角的Sign-off details, 在新窗口中查看检查表中的哪些内容不达标. 然后根据查看结果, 修改工作空间Spec Setting中的部分参数.

  • 如果是STA相关的内容不达标, 可以尝试设置一个更小的目标频率
  • 如果是DRC或LVS相关的内容不达标, 可以尝试设置一个更小的利用率

具体地, 你可以点击菜单栏的File->New Workspace来创建一个新的工作空间, 也可以点击菜单栏的File->Update Workspace来更新当前工作空间的参数. 你可以在新的工作空间中重新进行后端物理设计, 直到设计结果达到标准.

使用ECOS Studio完成NPC的后端物理设计

根据上述流程, 尝试对NPC进行后端物理设计.

探索ECOS Studio

如果你感兴趣, 尝试寻找一个可以成功生成签核包的最大利用率.

后端物理设计的新概念非常多, 我们不打算在这里展开介绍. 我们将会在D阶段再仔细讲解这些概念. 如果你想进一步了解ECOS Studio的介绍, 可以参考ECOS Studio User Guide在新窗口中打开这个文档.

待续未完

建设中

最近更新时间:
贡献者: Zihao Yu