目录
使用 TLM (Transaction-Level Modeling) 创建硬件模型
使用 TLM (Transaction-Level Modeling) 创建硬件模型
TLM(Transaction-Level Modeling)是一种高层次的硬件建模方法,主要用于系统级仿真和验证。TLM 允许开发者以事务的形式描述硬件组件之间的交互,从而简化了复杂系统的建模和仿真。本教程将详细讲解如何使用 TLM 创建硬件模型。
1. TLM 基本概念
1.1 什么是 TLM?
TLM 是一种建模方法,它使用事务(transaction)来表示数据包或操作请求。事务可以跨越多个时钟周期,因此 TLM 模型通常运行得比传统的 RTL 模型更快。TLM 主要用于系统级仿真和早期软件开发。
1.2 TLM 层次
TLM 分为多个层次,每个层次有不同的抽象级别:
- TLM 0:最低层次,接近于 RTL,每个操作都在一个时钟周期内完成。
- TLM 1:中等层次,使用同步事务,所有操作在一个事务周期内完成。
- TLM 2:最高层次,使用异步事务,支持非阻塞调用和多线程操作。
1.3 TLM 标准
- TLM 1.0:早期标准,主要支持同步事务。
- TLM 2.0:现代标准,支持异步事务和多线程操作,更灵活和高效。
2. 安装 SystemC 和 TLM 库
确保你已经安装了 SystemC 和 TLM 库。以下是安装步骤:
2.1 下载 SystemC
从官方网站下载 SystemC 的最新版本:
- 官方网站:Download SystemC
2.2 解压和安装
解压下载的文件并安装 SystemC:
Sh
深色版本
wget https://accellera.org/images/downloads/standards/systemc/systemc-2.3.3.tar.gz
tar -xzf systemc-2.3.3.tar.gz
cd systemc-2.3.3
2.3 编译和安装
编译和安装 SystemC:
Sh
深色版本
mkdir build
cd build
cmake ..
make
sudo make install
2.4 设置环境变量
编辑 ~/.bashrc
文件,添加 SystemC 的路径:
Sh
深色版本
export SYSTEMC_HOME=/usr/local/systemc-2.3.3
export PATH=$PATH:$SYSTEMC_HOME/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SYSTEMC_HOME/lib-linux
应用环境变量:
Sh
深色版本
source ~/.bashrc
3. 创建 TLM 模型
3.1 创建项目目录结构
创建一个项目目录结构,组织你的源代码和仿真文件。例如:
Sh
深色版本
mkdir -p project/src/hardware
mkdir -p project/src/software
mkdir -p project/sim
mkdir -p project/build
3.2 编写 TLM 模型
3.2.1 创建一个 TLM 存储器模块
在 project/src/hardware
目录下创建一个 TLM 存储器模块文件 tlm_memory.cpp
:
Cpp
深色版本
#include <systemc>
#include <tlm>
using namespace sc_core;
using namespace tlm;
SC_MODULE(TLMMemory) {
tlm::tlm_target_socket<> target_socket;
TLMMemory(sc_module_name name) : target_socket("target_socket") {
target_socket.register_b_transport(this, &TLMMemory::b_transport);
}
void b_transport(tlm::tlm_generic_payload& trans, sc_time& delay) {
tlm::tlm_command cmd = trans.get_command();
sc_dt::uint64 addr = trans.get_address();
unsigned char* payload = trans.get_data_ptr();
unsigned int len = trans.get_data_length();
if (cmd == tlm::TLM_READ_COMMAND) {
// 读操作
for (unsigned int i = 0; i < len; ++i) {
payload[i] = memory[addr + i];
}
} else if (cmd == tlm::TLM_WRITE_COMMAND) {
// 写操作
for (unsigned int i = 0; i < len; ++i) {
memory[addr + i] = payload[i];
}
}
trans.set_response_status(tlm::TLM_OK_RESPONSE);
}
private:
std::vector<uint8_t> memory(1024, 0); // 1KB 存储器
};
3.2.2 创建一个 TLM 发起者模块
在 project/src/hardware
目录下创建一个 TLM 发起者模块文件 tlm_initiator.cpp
:
Cpp
深色版本
#include <systemc>
#include <tlm>
using namespace sc_core;
using namespace tlm;
SC_MODULE(TLMInitiator) {
tlm::tlm_initiator_socket<> initiator_socket;
TLMInitiator(sc_module_name name) : initiator_socket("initiator_socket") {
SC_THREAD(run);
}
void run() {
tlm::tlm_generic_payload trans;
unsigned char buffer[4];
// 写操作
trans.set_command(tlm::TLM_WRITE_COMMAND);
trans.set_address(0x100);
trans.set_data_ptr(buffer);
trans.set_data_length(4);
buffer[0] = 0x12;
buffer[1] = 0x34;
buffer[2] = 0x56;
buffer[3] = 0x78;
initiator_socket->b_transport(trans, sc_time(10, SC_NS));
// 读操作
trans.set_command(tlm::TLM_READ_COMMAND);
trans.set_address(0x100);
trans.set_data_ptr(buffer);
trans.set_data_length(4);
initiator_socket->b_transport(trans, sc_time(10, SC_NS));
std::cout << "Read data: ";
for (int i = 0; i < 4; ++i) {
std::cout << std::hex << (int)buffer[i] << " ";
}
std::cout << std::endl;
}
};
3.3 创建顶层模块
在 project/src
目录下创建一个顶层模块文件 system_top.cpp
,集成 TLM 模块:
Cpp
深色版本
#include <systemc>
#include <tlm>
using namespace sc_core;
using namespace tlm;
#include "hardware/tlm_memory.cpp"
#include "hardware/tlm_initiator.cpp"
SC_MODULE(SystemTop) {
TLMMemory memory;
TLMInitiator initiator;
tlm::tlm_target_socket<> target_socket;
tlm::tlm_initiator_socket<> initiator_socket;
SC_CTOR(SystemTop) : memory("memory"), initiator("initiator") {
initiator_socket.bind(initiator.initiator_socket);
memory.target_socket.bind(initiator_socket);
// 记录波形
sc_trace_file *tf = sc_create_vcd_trace_file("wave");
sc_trace(tf, sc_time_stamp(), "time");
}
~SystemTop() {
sc_close_vcd_trace_file(tf);
}
};
3.4 编写测试平台
在 project/src
目录下创建一个测试平台文件 testbench.cpp
,用于驱动顶层模块:
Cpp
深色版本
#include <systemc>
using namespace sc_core;
#include "system_top.cpp"
void test() {
SystemTop top("top");
// 运行仿真
sc_start(100, SC_NS);
}
int sc_main(int argc, char* argv[]) {
test();
return 0;
}
4. 编写 Makefile
在 project
目录下创建一个 Makefile,用于编译和链接源代码:
Makefile
深色版本
# Makefile
CC = g++
SYSTEMC_HOME = /usr/local/systemc-2.3.3
SYSTEMC_LIB = $(SYSTEMC_HOME)/lib-linux
SYSTEMC_INCLUDE = $(SYSTEMC_HOME)/include
CFLAGS = -I$(SYSTEMC_INCLUDE) -Wall -g
LDFLAGS = -L$(SYSTEMC_LIB) -lsystemc -lm -lrt
SRCS = $(wildcard src/hardware/*.cpp) $(wildcard src/*.cpp)
OBJS = $(SRCS:.cpp=.o)
TARGET = sim/system_top
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^
%.o: %.cpp
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJS) $(TARGET)
5. 编译和运行仿真
5.1 编译源代码
在终端中运行以下命令编译源代码:
Sh
深色版本
cd project
make
5.2 运行仿真
创建一个脚本文件(例如 run_sim.sh
),用于运行仿真:
Sh
深色版本
#!/bin/bash
./sim/system_top
确保脚本文件具有可执行权限:
Sh
深色版本
chmod +x sim/run_sim.sh
运行仿真:
Sh
深色版本
./sim/run_sim.sh
6. 查看仿真结果
6.1 使用波形查看器
使用波形查看器(如GTKWave)查看仿真结果:
Sh
深色版本
gtkwave wave.vcd
7. 调试和优化
7.1 使用调试工具
使用调试工具(如GDB)进行调试:
Sh
深色版本
gdb ./sim/system_top
在GDB中设置断点、单步执行和查看变量:
Sh
深色版本
(gdb) break TLMMemory::b_transport
(gdb) run
(gdb) step
(gdb) print addr
7.2 性能分析
使用SystemC提供的性能分析工具,评估仿真过程中的性能指标,如CPU利用率、内存占用等。根据分析结果优化代码和硬件模型。
总结
通过以上步骤,你已经学会了如何使用 TLM 创建和仿真一个简单的硬件模型。从安装 SystemC 和 TLM 库、创建项目目录结构、编写 TLM 模型和顶层模块、编写测试平台、编译和运行仿真,到查看仿真结果和调试优化,每个步骤都至关重要。希望这些内容能帮助你更好地理解和应用 TLM 技术。