SystemC在CPU/GPU验证中的应用(三)
摘要:下面分享50个逐步升级SystemC编程能力的示例及建议的学习路线图。您可以一次一批地完成它们——从前五个基础的例子开始,然后转向channels, TLM, bus models, simple CPU/GPU kernels等等。在每个阶段掌握之后,再进行下一组的学习。
50个代表性的SystemC例子
- Hello, SystemC! (module + sc_main)
- Simple clock generator
- 4-bit up/down counter
- Blocking FIFO channel
- Non-blocking handshake channel
- Combinational AND/OR modules
- D-flip‐flop with async reset
- 8×1 multiplexer
- Simple RAM model (blocking accesses)
- Simple ROM model
- Dual-port RAM
- Bus arbiter (round-robin)
- TLM2.0 blocking transport (initiator)
- TLM2.0 blocking transport (target)
- TLM2.0 non-blocking transport
- TLM2.0 analysis port / export
- Simple AXI-Lite bus model
- AXI-Lite master + slave example
- Quantum keeper & time annotation
- tlm_utils::simple_initiator_socket
- tlm_utils::simple_target_socket
- Hierarchical module instantiation
- Dynamic process spawn & kill
- Event notification & sc_event_queue
- Reset synchronization circuit
- Clock domain crossing FIFO
- Bus monitor / tracer (TLM analysis)
- Memory-mapped register file
- Interrupt controller model
- Pipeline stage model (fetch/decode/execute)
- Simple 4-stage CPU datapath
- Cache model (direct-mapped)
- DMA engine model
- GPGPU kernel launcher skeleton
- GPU shader core (vector add)
- Barrier synchronization (sc_barrier emulation)
- Producer-consumer with sc_mutex
- sc_semaphore example
- SystemC-AMS basic RC filter
- Fixed-point arithmetic with sc_fixed
- Power‐aware sc_trace (VCD generation)
- Cross-trade-off analysis (timing vs. power)
- SystemC assertions (SC_ASSERT)
- UVM-SystemC basic use case
- Co-simulation stub (Verilog DPI)
- SystemC Python binding stub
- Parameterized module (SC_MODULE_T)
- TLM-2.0 generic payload extensions
- Simple NoC router model
- Full mini‐SOC: CPU + L2 cache + memory + interconnect
Third Batch: Examples 11–20
Below are the first five examples with complete code + detailed comments.
11. Dual-port RAM (阻塞访问)
文件名:dual_port_ram.cpp
#include <systemc.h>
#include <vector>
// 定义 RAM 接口(阻塞)
struct ram_if : sc_interface {
virtual unsigned int read(unsigned int addr, unsigned int port) = 0;
virtual void write(unsigned int addr, unsigned int data, unsigned int port) = 0;
};
// 双端口 RAM 模块
SC_MODULE(DualPortRAM) : public ram_if {
std::vector<unsigned int> mem;
sc_time latency;
SC_CTOR(DualPortRAM)
: mem(256, 0) // 256×32-bit
, latency(sc_time(20, SC_NS))
{}
// 端口 port = 0 或 1
unsigned int read(unsigned int addr, unsigned int port) override {
wait(latency);
if (addr < mem.size()) return mem[addr];
return 0;
}
void write(unsigned int addr, unsigned int data, unsigned int port) override {
wait(latency);
if (addr < mem.size()) mem[addr] = data;
}
};
// Testbench
SC_MODULE(TB_DualPortRAM) {
sc_port<ram_if> ram0, ram1; // 两个端口
SC_CTOR(TB_DualPortRAM) {
SC_THREAD(proc0);
SC_THREAD(proc1);
}
void proc0() {
// 端口 0 先写
for (unsigned i = 0; i < 8; ++i) {
ram0->write(i, i*100, 0);
cout << sc_time_stamp() << " P0 WRITE ["<< i <<"]="<< i*100 << endl;
}
wait(100, SC_NS);
// 端口 0 读
for (unsigned i = 0; i < 8; ++i) {
unsigned d = ram0->read(i, 0);
cout << sc_time_stamp() << " P0 READ ["<< i <<"]="<< d << endl;
}
}
void proc1() {
// 稍后启动端口1,模拟并发
wait(40, SC_NS);
for (unsigned i = 0; i < 8; ++i) {
ram1->write(i, i*1000, 1);
cout << sc_time_stamp() << " P1 WRITE ["<< i <<"]="<< i*1000 << endl;
}
wait(100, SC_NS);
for (unsigned i = 0; i < 8; ++i) {
unsigned d = ram1->read(i, 1);
cout << sc_time_stamp() << " P1 READ ["<< i <<"]="<< d << endl;
}
sc_stop();
}
};
int sc_main(int, char*[]) {
DualPortRAM ram("ram");
TB_DualPortRAM tb("tb");
tb.ram0(ram);
tb.ram1(ram);
sc_start();
return 0;
}
12. Bus Arbiter(轮询)
文件名:bus_arbiter.cpp
#include <systemc.h>
// 简单 4-master 轮询仲裁器
SC_MODULE(Arbiter) {
sc_in<bool> req[4];
sc_out<bool> gnt[4];
unsigned idx; // 下一个检查的 master
SC_CTOR(Arbiter): idx(0) {
SC_METHOD(prioritize);
for (int i = 0; i < 4; ++i)
sensitive << req[i];
}
void prioritize() {
// 清空所有 grant
for (int i = 0; i < 4; ++i) gnt[i].write(false);
// 轮询检查请求
for (int cnt = 0; cnt < 4; ++cnt) {
unsigned i = (idx + cnt) % 4;
if (req[i].read()) {
gnt[i].write(true);
idx = (i + 1) % 4; // 下次从 i+1 开始
return;
}
}
}
};
// Testbench
SC_MODULE(TB_Arbiter) {
sc_signal<bool> req[4], gnt[4];
Arbiter arb;
SC_CTOR(TB_Arbiter): arb("arb") {
// 端口绑定
for (int i = 0; i < 4; ++i) {
arb.req[i](req[i]);
arb.gnt[i](gnt[i]);
}
SC_THREAD(stimulus);
SC_METHOD(monitor);
for (int i = 0; i < 4; ++i) sensitive << gnt[i];
}
void stimulus() {
// 不同 master 在不同时间发出请求
req[0].write(true); wait(10, SC_NS);
req[1].write(true); wait(10, SC_NS);
req[0].write(false); wait(10, SC_NS);
req[2].write(true); wait(10, SC_NS);
req[1].write(false); req[2].write(false); req[3].write(true);
wait(10, SC_NS);
sc_stop();
}
void monitor() {
cout << sc_time_stamp() << " grants:";