IOMMU多级页表查找的验证
IOMMU多级页表查找的验证
本文将提供:
- SystemC参考模型(SC Reference Model):一个SystemC模块,实现x86风格的页表走查,支持可变级别(2-5级)。这是一个行为级黄金模型(golden model),用于验证Verilog RTL的正确性。模型使用SystemC 2.3+,模拟内存读取和走查过程。
- 完整IOMMU Verilog模块:基于前述页表walker扩展成一个更完整的IOMMU模块,包括TLB(简单缓存)、配置寄存器(级别、root_base)和fault处理。支持可变级别。
- Verilog Testbench:一个完整的testbench,实例化IOMMU模块,模拟内存(reg array for页表示例),注入多种测试场景(不同级别、hit/miss、fault),并与SystemC模型比较输出(通过VPI或简单日志)。
注意:
- 编译/运行:
- SystemC:需SystemC库(e.g., g++ -o sc_model sc_model.cpp -lsystemc)。
- Verilog:用iverilog或VCS(e.g., iverilog -o tb tb_iommu.v iommu.v ; vvp tb)。
- Testbench中,我简化了SystemC集成(通过日志比较);实际中,可用VSI(Verilog-SystemC Interface)或co-simulation工具如Verdi。
- 假设:4KB页,48位地址,简化无大页/权限检查。实际IOMMU更复杂(e.g., 支持ATS、两级翻译)。
- 覆盖:Testbench覆盖2-5级、fault、TLB hit/miss。
如果您需要进一步扩展(如两级翻译、ATS支持或UVM集成),请告知。
SystemC参考模型(SC Reference Model)
这是一个SystemC模块,模拟页表走查的参考行为。支持可变级别,通过SC_THREAD处理请求。内存用sc_fifo模拟(实际可替换为array)。
#include "systemc.h"#define ADDR_WIDTH 48
#define LEVEL_BITS 9
#define ENTRY_WIDTH 64
#define MAX_LEVELS 5
#define FAULT -1LLSC_MODULE(sc_page_walker) {sc_in<bool> clk;sc_in<bool> reset_n;// 输入端口sc_in<bool> start;sc_in<sc_uint<ADDR_WIDTH> > va;sc_in<sc_uint<3> > levels; // 2-5sc_in<sc_uint<ADDR_WIDTH> > root_base;// 输出端口sc_out<bool> done;sc_out<bool> fault;sc_out<sc_uint<ADDR_WIDTH> > pa;// 模拟内存 (简单array, 假设足够大)sc_uint<ENTRY_WIDTH> memory[1 << 20]; // 示例大小SC_CTOR(sc_page_walker) {SC_THREAD(walk_process);sensitive << clk.pos();async_reset_signal_is(reset_n, false);}void walk_process() {while (true) {wait();if (!reset_n.read()) {done.write(false);fault.write(false);pa.write(0);continue;}if (start.read()) {sc_uint<ADDR_WIDTH> current = root_base.read();sc_uint<3> lvl = levels.read();sc_uint<ADDR_WIDTH> vaddr = va.read();bool is_fault = false;sc_uint<ADDR_WIDTH> result_pa = 0;if (lvl < 2 || lvl > MAX_LEVELS) {is_fault = true;} else {int shift = 12 + (LEVEL_BITS * (lvl - 1));for (int level = lvl; level > 0; level--) {sc_uint<LEVEL_BITS> index = (vaddr >> shift) & ((1 << LEVEL_BITS) - 1);sc_uint<ADDR_WIDTH> entry_addr = current + (index * (ENTRY_WIDTH / 8)); // 字节地址// 模拟读内存sc_uint<ENTRY_WIDTH> entry = memory[entry_addr];if ((entry & 1) == 0) { // Present=0is_fault = true;break;}if (level == 1) { // 叶级result_pa = (entry & ~((1ULL<<12)-1)) + (vaddr & ((1ULL<<12)-1));break;}current = (entry & ~((1ULL<<12)-1)); // 下一基址shift -= LEVEL_BITS;}}done.write(true);fault.write(is_fault);pa.write(result_pa);} else {done.write(false);}}}// 方法: 初始化模拟内存 (测试用)void init_memory(sc_uint<ADDR_WIDTH> addr, sc_uint<ENTRY_WIDTH> value) {memory[addr] = value;}
};
SystemC模型解释
- 输入/输出:start触发走查,输出done/fault/pa。
- 过程:SC_THREAD在clk pos边沿运行,循环计算索引、模拟读entry、检查Present、更新基址。支持可变
levels
(调整shift和循环)。 - 内存模拟:用array;实际testbench中,可通过init_memory设置页表示例。
- 使用:作为参考,与Verilog RTL比较输出,确保一致性。
完整IOMMU Verilog模块
这是一个扩展的Verilog IOMMU模块,包括:
- 配置寄存器(levels, root_base)。
- 简单TLB(4-entry associative cache)。
- 页表走查器(从前述扩展,支持2-5级)。
- Fault处理和done信号。
module iommu #(parameter ADDR_WIDTH = 48, // VA/PA宽度parameter LEVEL_BITS = 9, // 每级索引位parameter ENTRY_WIDTH = 64, // entry大小parameter MAX_LEVELS = 5, // 支持最大级别parameter TLB_SIZE = 4 // TLB entries (简单全相联)
) (input clk,input reset_n,// 配置接口 (e.g., from CPU/hypervisor)input config_valid, // 配置有效input [$clog2(MAX_LEVELS)-1:0] config_levels, // 级别 (0=2, ..., 3=5)input [ADDR_WIDTH-1:0] config_root_base, // 根表基址// 翻译请求接口input translate_req, // 请求翻译