当前位置:首页>python>用 Python 重塑硬件验证的未来:Cocotb 深度解析

用 Python 重塑硬件验证的未来:Cocotb 深度解析

  • 2026-07-03 15:56:39
用 Python 重塑硬件验证的未来:Cocotb 深度解析

用 Python 重塑硬件验证的未来:Cocotb 深度解析

标签:Cocotb · Python · RTL Simulation · FPGA · ASIC Verification · VPI · Coroutine


一、背景知识:RTL 验证的前世今生

      在数字芯片和 FPGA 的设计流程中,验证(Verification) 是消耗工时最多的环节。业界普遍数据显示,验证工作量占据整个芯片研发周期的 60%~70%。验证的核心目的是在硅片流片或 FPGA 烧录前,通过仿真证明 RTL(Register Transfer Level)设计符合规格书要求。

1.1 传统验证方法的困境

长期以来,硬件验证主要依赖两种技术路线:

  • SystemVerilog + UVM
    :功能强大,但学习曲线陡峭,代码冗长,复用性依赖复杂的工厂模式;
  • VHDL Testbench
    :类型严格,适合特定场景,但生态相对封闭,开发效率低;
  • e / Specman
    :Cadence 专有,授权费用高昂,不适合中小团队。

这些方法都存在一个共同痛点:验证语言本身的生态远远落后于通用编程语言。当 Python 拥有丰富的数学库(NumPy)、机器学习框架、协议解析库时,硬件验证工程师仍需手写 SystemVerilog 来完成最基础的数据处理。

💡 背景洞察:Python 生态在数据处理、网络协议、随机激励生成、回归分析等方面积累了极为丰富的库。将 Python 引入硬件仿真,等于为验证工程师打开了一扇通往万亿行代码生态的大门。

1.2 Python 进入硬件验证的动机

  • 软件工程师加入硬件团队后,不必再学一门"专用"语言;
  • 利用 Python 的 pytestcoveragehypothesis 等工具进行回归与覆盖率分析;
  • 与 ML 模型集成,实现智能激励生成;
  • 快速原型与脚本化验证,大幅缩短迭代周期。

1.3 Cocotb 发展时间线

时间
里程碑
2013
Cocotb 诞生,由 Chris Higgs 在 Potential Ventures 开发,首次将 Python 协程与 VPI 仿真接口结合
2015
在 GitHub 开源,社区开始贡献支持 Icarus Verilog、ModelSim、Aldec 等仿真器的后端
2019
v1.2 里程碑——引入 async/await 语法支持;增加 VHDL VHPI 后端
2022
v1.7——引入 cocotb-bus、改进 Clock/Reset 辅助类,生态扩展出 cocotbext-axi 等协议扩展库
2024-25
支持 Verilator 5.x、改进多时钟域处理,与 GitHub Actions CI 深度集成

二、什么是 Cocotb?

Cocotb(Coroutine Co-simulation Testbench)是一个 Python 协同仿真框架,允许工程师使用纯 Python 编写 RTL 仿真测试台(Testbench),而无需编写任何 SystemVerilog/VHDL 代码。

特性
说明
🐍 纯 Python 测试台
所有测试逻辑用 Python 编写,可利用全部 Python 生态工具链
⚡ 协程驱动
基于 asyncio 协程,自然表达时序等待,无需状态机转换
🔌 仿真器无关
支持 Icarus、ModelSim、VCS、Xcelium、Verilator 等主流仿真器
🧩 协议扩展丰富
cocotbext 提供 AXI4、AXI-Stream、I2C、SPI、Ethernet 等现成 BFM
📊 CI 友好
与 pytest、GitHub Actions、GitLab CI 无缝集成
🆓 BSD 开源
完全开源,无需商业授权

Cocotb 能做什么?

  • 驱动 DUT(Device Under Test)的输入信号;
  • 采样输出信号并进行断言比较;
  • 通过 await 等待时钟边沿、信号变化、固定时间;
  • 并发运行多个协程,模拟复杂总线交互;
  • 生成随机激励,配合 Python 的 randomhypothesis 使用;
  • 调用 Python 参考模型进行"黄金比较"验证;
  • 收集功能覆盖率,生成报告。

三、架构解析

Cocotb 的架构核心思想是:通过标准仿真接口(VPI/VHPI/FLI)将 Python 解释器嵌入仿真器进程,实现对仿真时间的控制和对 RTL 信号的读写。

┌─────────────────────────────────────┐│      Python Test Code               ││   async def test_xxx(dut)           │└──────────────┬──────────────────────┘               │┌──────────────┴──────────────────────┐│  Cocotb Scheduler   │  Triggers     ││  (Coroutine Mgr)    │  (RisingEdge) │└──────────────┬──────────────────────┘               │┌──────────────┴──────────────────────┐│       VPI / VHPI / FLI              ││      (Simulator Interface)          │└──────────────┬──────────────────────┘               │┌──────┬───────┴──────┬───────────────┐│Icarus│  ModelSim    │  VCS/Xcelium  │ Verilator ...└──────┴──────────────┴───────────────┘               │┌──────────────┴──────────────────────┐│    DUT(RTL 设计:Verilog/VHDL)    │└─────────────────────────────────────┘

3.1 关键组件详解

① Scheduler(调度器)

Cocotb 的调度器维护一个协程队列,在仿真时间推进时决定哪些协程可以被"唤醒"。调度器与仿真器之间通过 VPI 回调机制通信:当仿真时间步进到某个时刻,调度器检查哪些 Trigger 已满足条件,并恢复相应协程的执行。

② Triggers(触发器)

Trigger 是 await 的对象,代表"等待某件事发生":

Trigger
含义
RisingEdge(signal)
等待信号上升沿
FallingEdge(signal)
等待信号下降沿
ClockCycles(clk, n)
等待 n 个时钟周期
Timer(100, units='ns')
等待固定时间
Event()
等待 Python Event 被触发
First(*triggers)
等待多个触发器中最先发生的一个

③ Handle(句柄)

dut 对象是 DUT 的根句柄。通过属性访问可以获得任意层次的信号句柄,支持读写:

  • dut.signal.value
     —— 读取当前值(返回 LogicArray
  • dut.signal.value = 1
     —— 强制赋值

④ VPI/VHPI/FLI 接口

连接 Python 与仿真器的"桥梁"。VPI(Verilog Procedural Interface)是 IEEE 1364 标准,几乎所有商业 Verilog 仿真器都支持。

⚠️ 注意:Verilator 并不原生支持 VPI,Cocotb 通过特殊适配层实现支持,部分功能(如 force/release)受限。


四、安装与环境配置

4.1 系统要求

  • Python 3.8+
  • GNU Make
  • 至少一种支持的仿真器(推荐新手使用免费的 Icarus Verilog)

4.2 安装 Cocotb

# 建议在虚拟环境中安装python -m venv venvsource venv/bin/activate  # Windows: venv\Scripts\activate# 安装 cocotb 核心pip install cocotb# 安装常用协议扩展(可选)pip install cocotbext-axi cocotbext-eth cocotbext-i2c# 安装 Icarus Verilog(Ubuntu/Debian)sudo apt install iverilog# macOS(使用 Homebrew)brew install icarus-verilog

4.3 项目目录结构

my_project/├── rtl/│   └── my_module.v          # DUT(被测设计)├── tests/│   ├── test_my_module.py    # Cocotb 测试文件│   └── Makefile             # 构建入口└── sim_build/               # 自动生成的编译中间文件

4.4 Makefile 配置

# 仿真器选择:icarus / questa / vcs / xcelium / verilatorSIM ?= icarusTOPLEVEL_LANG ?= verilogVERILOG_SOURCES += (shell cocotb-config --makefiles)/Makefile.sim

配置完成后,在 tests/ 目录执行 make 即可运行仿真。


五、核心语法与 API

5.1 最小可运行示例

DUT(2 输入加法器):

module adder #(    parameter WIDTH = 8)(    input  [WIDTH-1:0] a,    input  [WIDTH-1:0] b,    output [WIDTH:0]   sum);    assign sum = a + b;endmodule

Cocotb 测试台:

import cocotbfrom cocotb.triggers import Timerimport random@cocotb.test()async def test_adder_basic(dut):    """最基本的加法器测试"""    dut.a.value = 5    dut.b.value = 3    await Timer(10, units='ns')    result = dut.sum.value.integer    assert result == 8f"期望 8,得到 {result}"    dut._log.info(f"5 + 3 = {result} ✓")@cocotb.test()async def test_adder_random(dut):    """随机激励测试,运行 100 次"""    for _ in range(100):        a = random.randint(0255)        b = random.randint(0255)        dut.a.value = a        dut.b.value = b        await Timer(10, units='ns')        assert dut.sum.value.integer == a + b

5.2 @cocotb.test() 装饰器参数

@cocotb.test(    timeout_time=1000,      # 测试超时时间    timeout_unit='us',      # 时间单位    skip=False,             # 是否跳过此测试    expect_fail=False,      # 期望失败(用于负向测试)    expect_error=Exception, # 期望抛出特定异常)async def my_test(dut):    ...

5.3 时钟生成

from cocotb.clock import Clockfrom cocotb.triggers import RisingEdge, ClockCycles@cocotb.test()async def test_with_clock(dut):    # 启动 10ns 周期时钟,在后台持续运行    cocotb.start_soon(Clock(dut.clk, 10, units='ns').start())    # 复位序列    dut.rst_n.value = 0    await ClockCycles(dut.clk, 5)   # 等待 5 个时钟周期    dut.rst_n.value = 1    await RisingEdge(dut.clk)       # 等待下一个上升沿

5.4 并发协程

async def drive_inputs(dut):    """持续产生激励"""    for i in range(20):        dut.data_in.value = i        await RisingEdge(dut.clk)async def monitor_outputs(dut, results):    """采样并记录输出"""    while True:        await RisingEdge(dut.clk)        if dut.valid_out.value:            results.append(dut.data_out.value.integer)@cocotb.test()async def test_pipeline(dut):    cocotb.start_soon(Clock(dut.clk, 10, units='ns').start())    results = []    # 并发启动激励和监控    cocotb.start_soon(monitor_outputs(dut, results))    await drive_inputs(dut)    await ClockCycles(dut.clk, 10)    dut._log.info(f"收集到 {len(results)} 个输出")

六、信号驱动与采样

6.1 信号访问与层次导航

# 顶层信号dut.clk.value = 0# 子模块信号(层次访问)dut.u_fifo.wr_ptr.valuedut.u_core.u_alu.result.value# 数组信号dut.mem[0].value = 0xFF# 读取值的多种方式sig = dut.datasig.value.integer          # 转为无符号整数sig.value.signed_integer   # 转为有符号整数sig.value.buff             # 转为 bytesstr(sig.value)             # '01101101'(二进制字符串)# 高阻/不定态检测if sig.value.is_resolvable:    val = sig.value.integerelse:    dut._log.warning("信号含有 X 或 Z!")

6.2 赋值模式

from cocotb.handle import Deposit, Force, Freeze, Releasedut.signal.value = Deposit(1)  # 普通赋值(默认)dut.signal.value = Force(1)    # 强制保持(RTL 内部驱动也无法改变)dut.signal.value = Freeze()    # 冻结当前值dut.signal.value = Release()   # 释放强制

✅ 最佳实践:在时钟边沿后立即赋值时,先 await RisingEdge,再操作信号,避免竞争条件。


七、高级用法

7.1 参数化测试

@cocotb.test()@cocotb.parametrize(    ("a""b""expected"),    [        (0,   0,   0),        (2551,   256),        (128128256),    ])async def test_adder_param(dut, a, b, expected):    dut.a.value = a    dut.b.value = b    await Timer(10, units='ns')    assert dut.sum.value.integer == expected

7.2 使用 Event 进行协程间通信

from cocotb.triggers import Eventasync def wait_for_interrupt(dut, irq_event):    await RisingEdge(dut.irq)    irq_event.set()@cocotb.test()async def test_interrupt(dut):    cocotb.start_soon(Clock(dut.clk, 10, units='ns').start())    irq_event = Event()    cocotb.start_soon(wait_for_interrupt(dut, irq_event))    dut.trigger_op.value = 1    await ClockCycles(dut.clk, 1)    dut.trigger_op.value = 0    # 等待中断,最多等 100us    await First(irq_event.wait(), Timer(100, units='us'))    assert irq_event.is_set(), "超时:未收到中断"

7.3 使用 cocotbext-axi:零代码 AXI BFM

from cocotbext.axi import AxiLiteMaster, AxiBus@cocotb.test()async def test_axi_lite_rw(dut):    cocotb.start_soon(Clock(dut.clk, 10, units='ns').start())    # 自动绑定 AXI-Lite 信号    axil_master = AxiLiteMaster(AxiBus.from_prefix(dut, "s_axil"), dut.clk, dut.rst)    await axil_master.reset()    # 写寄存器    await axil_master.write(0x000xDEADBEEF)    # 读回并验证    data = await axil_master.read(0x004)    assert int.from_bytes(data.data, 'little') == 0xDEADBEEF

7.4 功能覆盖率收集

import collectionscoverage_bins = collections.Counter()async def collect_coverage(dut):    while True:        await RisingEdge(dut.clk)        state = dut.fsm_state.value.integer        coverage_bins[state] += 1@cocotb.test()async def test_with_coverage(dut):    cocotb.start_soon(Clock(dut.clk, 10, units='ns').start())    cocotb.start_soon(collect_coverage(dut))    await ClockCycles(dut.clk, 1000)    total_states = 8    covered = len(coverage_bins)    dut._log.info(f"覆盖 {covered}/{total_states} 个状态: {dict(coverage_bins)}")

八、案例一:AXI-Stream FIFO 验证

验证一个带 AXI-Stream 接口的同步 FIFO,确保数据无丢失、无重复地传输。

DUT 接口:

module axis_fifo #(    parameter DEPTH      = 16,    parameter DATA_WIDTH = 8)(    input  wire                   clk, rst,    // Slave(写)端口    input  wire [DATA_WIDTH-1:0]  s_axis_tdata,    input  wire                   s_axis_tvalid,    output wire                   s_axis_tready,    // Master(读)端口    output wire [DATA_WIDTH-1:0]  m_axis_tdata,    output wire                   m_axis_tvalid,    input  wire                   m_axis_tready);

完整测试台:

import cocotbfrom cocotb.clock import Clockfrom cocotb.triggers import RisingEdge, ClockCyclesfrom cocotbext.axi import AxiStreamBus, AxiStreamSource, AxiStreamSinkimport randomasync def reset_dut(dut):    dut.rst.value = 1    await ClockCycles(dut.clk, 5)    dut.rst.value = 0    await RisingEdge(dut.clk)@cocotb.test()async def test_fifo_basic(dut):    """基本写入读出测试"""    cocotb.start_soon(Clock(dut.clk, 10, units='ns').start())    axis_src  = AxiStreamSource(AxiStreamBus.from_prefix(dut, "s_axis"), dut.clk, dut.rst)    axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.clk, dut.rst)    await reset_dut(dut)    test_data = [0x010x020x030x04]    await axis_src.send(bytes(test_data))    rx = await axis_sink.recv()    assert list(rx.tdata) == test_data    dut._log.info("基本收发测试通过 ✓")@cocotb.test()async def test_fifo_stress(dut):    """压力测试:随机背压 + 随机数据"""    cocotb.start_soon(Clock(dut.clk, 10, units='ns').start())    axis_src  = AxiStreamSource(AxiStreamBus.from_prefix(dut, "s_axis"), dut.clk, dut.rst)    axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.clk, dut.rst)    axis_sink.pause = True    await reset_dut(dut)    sent_pkts = []    for _ in range(50):        pkt = bytes([random.randint(0255for _ in range(random.randint(18))])        sent_pkts.append(pkt)        await axis_src.send(pkt)    axis_sink.pause = False    for i, expected in enumerate(sent_pkts):        rx = await axis_sink.recv()        assert bytes(rx.tdata) == expected, f"包 {i} 不匹配"    dut._log.info(f"压力测试通过:{len(sent_pkts)} 包全部正确 ✓")

九、案例二:SPI Master 验证

手写 SPI Slave BFM,对 DUT 的 SPI Master 进行验证:

import cocotbfrom cocotb.clock import Clockfrom cocotb.triggers import RisingEdge, FallingEdge, ClockCyclesclass SpiSlaveBFM:    """SPI Slave 总线功能模型(Mode 0: CPOL=0, CPHA=0)"""    def __init__(self, dut):        self.dut    = dut        self.rx_buf = []        self.tx_buf = []    async def _transfer_byte(self) -> int:        """等待并完成一个字节的 SPI 传输"""        rx_byte = 0        tx_byte = self.tx_buf.pop(0if self.tx_buf else 0xFF        for bit in range(7, -1, -1):            await RisingEdge(self.dut.spi_clk)            rx_byte |= (self.dut.mosi.value.integer << bit)            self.dut.miso.value = (tx_byte >> bit) & 1        return rx_byte    async def run(self):        """后台持续监听 SPI 传输"""        while True:            await FallingEdge(self.dut.cs_n)   # 等待片选有效            while not self.dut.cs_n.value:                byte = await self._transfer_byte()                self.rx_buf.append(byte)@cocotb.test()async def test_spi_write(dut):    cocotb.start_soon(Clock(dut.clk, 10, units='ns').start())    spi_slave = SpiSlaveBFM(dut)    cocotb.start_soon(spi_slave.run())    dut.rst_n.value = 0    await ClockCycles(dut.clk, 5)    dut.rst_n.value = 1    # 触发 SPI 写操作(写寄存器 0x12,值 0xAB)    dut.cmd_addr.value  = 0x12    dut.cmd_data.value  = 0xAB    dut.cmd_valid.value = 1    await RisingEdge(dut.clk)    dut.cmd_valid.value = 0    await RisingEdge(dut.done)    assert spi_slave.rx_buf[0] == 0x12    assert spi_slave.rx_buf[1] == 0xAB    dut._log.info("SPI 写测试通过 ✓")

十、案例三:覆盖率驱动的随机验证

结合 Python 参考模型实现"黄金比较"验证,同时驱动覆盖率:

import cocotbfrom cocotb.clock import Clockfrom cocotb.triggers import RisingEdge, ClockCyclesimport random, collectionsdef reference_model(aint, bint, opint) -> int:    """Python 黄金参考模型"""    ops = {        0b00: lambda a, b: a + b,        0b01: lambda a, b: a - b,        0b10: lambda a, b: a & b,        0b11: lambda a, b: a | b,    }    return ops[op](a, b) & 0xFFFF  # 16-bit 截断cov_op = collections.Counter()cov_a  = collections.Counter()def bin_value(vint) -> str:    if   v == 0:      return "zero"    elif v < 0x4000:  return "low"    elif v < 0x8000:  return "mid"    elif v < 0xFFFF:  return "high"    else:             return "max"@cocotb.test()async def test_alu_coverage_driven(dut):    """覆盖率驱动的 ALU 验证"""    cocotb.start_soon(Clock(dut.clk, 10, units='ns').start())    dut.rst_n.value = 0    await ClockCycles(dut.clk, 3)    dut.rst_n.value = 1    target_ops  = {0123}    target_bins = {"zero""low""mid""high""max"}    iterations  = 0    while iterations < 10000:        a  = random.randint(00xFFFF)        b  = random.randint(00xFFFF)        op = random.randint(03)        dut.a.value  = a        dut.b.value  = b        dut.op.value = op        await RisingEdge(dut.clk)        await RisingEdge(dut.clk)  # 1-cycle pipeline delay        expected = reference_model(a, b, op)        actual   = dut.result.value.integer        assert actual == expected, f"op={op}, a={a:#x}, b={b:#x}: expect {expected:#x}, got {actual:#x}"        cov_op[op]          += 1        cov_a[bin_value(a)] += 1        iterations          += 1        if set(cov_op.keys()) >= target_ops and set(cov_a.keys()) >= target_bins:            dut._log.info(f"🎉 全覆盖达成!共 {iterations} 次迭代")            break    dut._log.info(f"操作码覆盖: {dict(cov_op)}")

十一、与其他方法的对比

特性
Cocotb (Python)
UVM (SystemVerilog)
VHDL Testbench
Verilator + C++
学习曲线
✅ 低
❌ 高
生态库丰富度
✅ 极丰富
❌ 有限
商业仿真器支持
✅ 全面
✅ 全面
✅ 全面
仅 Verilator
开源仿真器支持
✅ Icarus/Verilator
有限
有限
✅ 原生
仿真速度
✅ 极快
随机激励
✅ 极强
有限
CI 集成
✅ 无缝 (pytest)
需脚本封装
需脚本封装
需脚本封装
VHDL 支持
✅ VHPI
❌ 不支持
✅ 原生
❌ 不支持
适用规模
模块级~子系统级
子系统级~芯片级
模块级
模块级

💡 选型建议:Cocotb 并非要完全取代 UVM,而是填补了"需要快速验证"和"需要利用 Python 生态"这两个场景的空白。在大型 ASIC 项目中,两者完全可以共存。


十二、最佳实践与工程技巧

12.1 复位辅助函数

# utils/reset.pyasync def apply_reset(dut, rst_sig='rst_n', cycles=10, active_low=True):    rst = getattr(dut, rst_sig)    rst.value = 0 if active_low else 1    await ClockCycles(dut.clk, cycles)    rst.value = 1 if active_low else 0    await RisingEdge(dut.clk)

12.2 使用 pytest 运行

# 安装 pytest-cocotb 插件pip install pytest-cocotb# 运行测试并生成 HTML 报告pytest tests/ --html=report.html --self-contained-html# 并行仿真(需要 pytest-xdist)pytest tests/ -n auto

12.3 常见坑与解决方案

问题
原因
解决方案
信号值为 X
DUT 未正确复位
确保复位后再采样,用 is_resolvable 检测
测试挂死不退出
触发器永远不满足
为所有 await 添加 timeout_time
仿真时间不推进
没有任何触发器
使用 await Timer(0) 让出控制权
多驱动冲突
多个协程同时驱动同一信号
使用 Lock 或设计唯一驱动协程

12.4 推荐项目结构

project/├── rtl/                   # HDL 设计文件├── tb/│   ├── common/│   │   ├── bfm/           # 自定义 BFM(SPI/I2C/...)│   │   └── utils.py       # 公共辅助函数│   ├── tests/│   │   ├── test_unit_a.py│   │   └── test_unit_b.py│   └── Makefile├── ci/│   └── .github/workflows/sim.yml└── README.md

十三、总结

Cocotb 通过一个优雅的设计——将 Python 协程调度器嵌入仿真时间轴,彻底改变了硬件验证的体验。

场景
建议
✅ 适合 Cocotb
模块级单元测试、协议 BFM 快速开发、开源 FPGA 项目、CI 自动化回归
⚖️ 需权衡
超大规模全芯片 SoC 验证(UVM 更成熟)、极高仿真速度需求(Verilator+C++ 更快)
🌱 未来趋势
随着开源 EDA 工具崛起,Cocotb 正成为学术界和初创公司的首选验证框架

延伸阅读

  • 官方文档:https://docs.cocotb.org
  • AXI 协议扩展:https://github.com/alexforencich/cocotbext-axi
  • 官方示例仓库:https://github.com/cocotb/cocotb/tree/master/examples
  • 社区讨论:https://github.com/cocotb/cocotb/discussions

如果这篇文章对你有帮助,欢迎点赞收藏。从一个小模块的单元测试开始,体验用 Python 驾驭硬件仿真的乐趣 🚀

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 22:57:38 HTTP/2.0 GET : https://f.mffb.com.cn/a/491321.html
  2. 运行时间 : 0.329618s [ 吞吐率:3.03req/s ] 内存消耗:4,806.34kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=585a4e0c76d774b083e8e13e9970d9ae
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.001137s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001395s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.006848s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.001568s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001836s ]
  6. SELECT * FROM `set` [ RunTime:0.005067s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001581s ]
  8. SELECT * FROM `article` WHERE `id` = 491321 LIMIT 1 [ RunTime:0.002828s ]
  9. UPDATE `article` SET `lasttime` = 1783090658 WHERE `id` = 491321 [ RunTime:0.012689s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000821s ]
  11. SELECT * FROM `article` WHERE `id` < 491321 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.021339s ]
  12. SELECT * FROM `article` WHERE `id` > 491321 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.002184s ]
  13. SELECT * FROM `article` WHERE `id` < 491321 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.009316s ]
  14. SELECT * FROM `article` WHERE `id` < 491321 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.027574s ]
  15. SELECT * FROM `article` WHERE `id` < 491321 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.068676s ]
0.333727s