feat: add FlushWaveForm() to write wave immediately, for debugger

add doc: API statement
This commit is contained in:
Makiras 2024-12-27 14:58:11 +08:00 committed by Makiras
parent 3c1e6cc43f
commit 7b70577b45
8 changed files with 95 additions and 42 deletions

View File

@ -7,16 +7,22 @@
在DUT对应的Class中以**大驼峰命名**的函数为用户需要使用的常用函数,其他命名方式的函数为内部函数,不建议用户使用。
|编号|API名称|参数|说明|
|-|--|---|---|
|1|InitClock(name)|字符类型,时钟引脚,或引脚的名称|初始化时钟让DUT中的|-XClock绑定对应的引脚|
|2|Step(i)|int类型时钟周期个数|推进时序电路i个时钟周期|
|3|StepRis(callback)|函数类型,回调函数|设置上升沿触发的回调函数|
|4|StepFal(callback)|函数类型,回调函数|设置下降沿触发的回调函数|
|5|SetWaveform(file)|字符类型,文件名,含路径|设置波形输出的文件|
|6|SetCoverage(file)|字符类型,文件名,含路径|设置覆盖率输出的文件|
|7|Finish()|-|结束仿真,保持波形,覆盖率等结果文件|
|8|RefreshComb()|-|推进组合电路|
|编号|API名称|参数|返回值|说明|
|-|--|---|---|---|
|1|InitClock(name)|字符类型,时钟引脚,或引脚的名称|-|初始化时钟让DUT中的`XClock`绑定对应的引脚|
|2|Step(i)|int类型时钟周期个数|-|推进时序电路i个时钟周期|
|3|StepRis(callback)|函数类型,回调函数|-|设置上升沿触发的回调函数|
|4|StepFal(callback)|函数类型,回调函数|-|设置下降沿触发的回调函数|
|5|SetWaveform(file)|字符类型,文件名,含路径|-|设置波形输出的文件|
|6|FlushWaveform()|-|-|将波形内容立即刷新到文件中,**频繁调用可能导致FST压缩能力失效**|
|7|SetCoverage(file)|字符类型,文件名,含路径|-|设置覆盖率输出的文件|
|8|CheckPoint(file)|字符类型,文件名,含路径|int类型当前时钟周期|保存当前仿真状态到文件|
|9|Restore(file)|字符类型,文件名,含路径|int类型保存时的时钟周期|从文件中恢复仿真状态|
|10|GetInternalSignal(name)|字符类型,信号名称|XData类型|通过变量名获取的内部信号对象,需要开启 `--vpi`**影响性能**|
|11|VPIInternalSignalList(prefix, deep)|字符类型,前缀,深度层级|int类型信号名称列表|获取内部信号列表,需要开启 `--vpi`|
|12|Finish()|-|-|结束仿真,保持波形,覆盖率等结果文件|
|13|RefreshComb()|-|-|推进组合电路|
#### C++
```c++
@ -25,7 +31,12 @@ void Step(int i = 1);
void StepRis(std::function<void(uint64_t, void*)>, void*args=nullptr);
void StepFal(std::function<void(uint64_t, void*)>, void*args=nullptr);
void SetWaveform(std::string filename);
void FlushWaveform();
void SetCoverage(std::string filename);
int CheckPoint(const std::string filename);
int Restore(const std::string filename);
XData GetInternalSignal(const std::string name);
std::vector<std::string> VPIInternalSignalList(std::string prefix="", int deep=99);
void Finish();
void RefreshComb();
```
@ -38,7 +49,12 @@ Step(i:int = 1)
StepRis(callback: Callable, args=None, args=(), kwargs={})
StepFal(callback: Callable, args=None, args=(), kwargs={})
SetWaveform(filename)
FlushWaveform()
SetCoverage(filename)
CheckPoint(filename: str) -> int
Restore(filename: str) -> int
GetInternalSignal(name: str) -> XData
VPIInternalSignalList(self, prefix="", deep=99) -> List[str]
Finish()
RefreshComb()
```

View File

@ -26,35 +26,33 @@ def as_uint(x, nbits):
return x & ((1 << nbits) - 1)
def main():
dut = DUTAdder("+verilator+debug") # Assuming USE_VERILATOR
dut = DUTAdder() # Assuming USE_VERILATOR
print("Initialized UTAdder")
print(dut.VPIInternalSignalList())
# for c in range(11451):
# i = input_t(random_int(), random_int(), random_int() & 1)
# o_dut, o_ref = output_t(), output_t()
for c in range(11451):
i = input_t(random_int(), random_int(), random_int() & 1)
o_dut, o_ref = output_t(), output_t()
# def dut_cal():
# dut.a.value, dut.b.value, dut.cin.value = i.a, i.b, i.cin
# dut.Step(1)
# o_dut.sum = dut.sum.value
# o_dut.cout = dut.cout.value
def dut_cal():
dut.a.value, dut.b.value, dut.cin.value = i.a, i.b, i.cin
dut.Step(1)
o_dut.sum = dut.sum.value
o_dut.cout = dut.cout.value
# def ref_cal():
# sum = as_uint( i.a + i.b + i.cin, 128+1)
# o_ref.sum = as_uint(sum, 128)
# o_ref.cout = as_uint(sum >> 128, 1)
def ref_cal():
sum = as_uint( i.a + i.b + i.cin, 128+1)
o_ref.sum = as_uint(sum, 128)
o_ref.cout = as_uint(sum >> 128, 1)
# dut_cal()
# ref_cal()
dut_cal()
ref_cal()
# print(f"[cycle {dut.xclock.clk}] a=0x{i.a:x}, b=0x{i.b:x}, cin=0x{i.cin:x}")
# print(f"DUT: sum=0x{o_dut.sum:x}, cout=0x{o_dut.cout:x}")
# print(f"REF: sum=0x{o_ref.sum:x}, cout=0x{o_ref.cout:x}")
print(f"[cycle {dut.xclock.clk}] a=0x{i.a:x}, b=0x{i.b:x}, cin=0x{i.cin:x}")
print(f"DUT: sum=0x{o_dut.sum:x}, cout=0x{o_dut.cout:x}")
print(f"REF: sum=0x{o_ref.sum:x}, cout=0x{o_ref.cout:x}")
# assert o_dut.sum == o_ref.sum, "sum mismatch"
assert o_dut.sum == o_ref.sum, "sum mismatch"
print("Test Passed, destroy UTAdder")
dut.Finish() # When using VCS, DUT.Finish() will exit the program, so it should be the last line of the program

View File

@ -8,7 +8,7 @@ except:
if __name__ == "__main__":
dut = DUTvpi()
dut = DUTvpi("+verilator+debug")
print("internal signals: ", dut.VPIInternalSignalList())
v1 = dut.GetInternalSignal("vpi._v1_base")
v2 = dut.GetInternalSignal("vpi._v2_base")
@ -17,8 +17,10 @@ if __name__ == "__main__":
dut.InitClock("clk")
print("data size: v1:%2d v2:%2d v3:%2d v4:%2d" % (v1.W(), v2.W(), v3.W(), v4.W()))
print("------------------step-------------------")
for i in range(20):
dut.Step(1)
dut.FlushWaveform()
if i == 10:
# write to internal signals
v1.value = 1 # 1 bit, type logic, .W() is 0
@ -27,4 +29,5 @@ if __name__ == "__main__":
v4.value = 30 # 64 bits
print("%2d v1:%3s v2:%3s v3:%3s v4:%3s | _v1:%3s, _v2:%3s, _v3:%3s, _v4:%3s" % (i, dut.v1.value, dut.v2.value, dut.v3.value, dut.v4.value,
v1.value, v2.value, v3.value, v4.value))
input("Press Enter to continue...")
dut.Finish()

View File

@ -14,6 +14,6 @@ fi
# run cache codegen
rm -rf ./picker_out
./build/bin/picker export example/InternalSignals/vpi.v --autobuild false --sdir ./template --vpi --sname vpi --tdir ./picker_out/InterlSinals --sim verilator --lang python
./build/bin/picker export example/InternalSignals/vpi.v --autobuild false --sdir ./template --vpi --sname vpi --tdir ./picker_out/InterlSinals --sim verilator --lang python $@
cp example/InternalSignals/example.py picker_out/InterlSinals/python/
cd picker_out/InterlSinals && make EXAMPLE=ON

View File

@ -7,9 +7,9 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# enable coroutines
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines -ftls-model=global-dynamic $ENV{CFLAGS}")
set(CFLAGS "$ENV{CFLAGS} -ftls-model=global-dynamic")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines ${CFLAGS}")
set(SIMULATOR_FLAGS "$ENV{SIMULATOR_FLAGS}")
set(CFLAGS "$ENV{CFLAGS}")
set(COVERAGE "$ENV{COVERAGE}")
set(CHECKPOINTS "$ENV{CHECKPOINTS}")
set(VPI "$ENV{VPI}")

View File

@ -86,7 +86,10 @@ void DutVcsBase::SetCoverage(const char *filename)
{
XInfo("VCS coverage is not supported");
};
void DutVerilatorBase::FlushWaveform()
{
XInfo("VCS waveform is not supported");
};
int DutVcsBase::CheckPoint(const char *filename)
{
XFatal("VCS checkpoint is not supported");
@ -163,9 +166,12 @@ int DutVerilatorBase::Step(uint64_t ncycle, bool dump)
if (dump) {
for (int i = 0; i < ncycle; i++) {
#if defined(VL_VPI)
VerilatedVpi::callValueCbs();
VerilatedVpi::callValueCbs(); // for vpi_put_value
#endif
((V{{__TOP_MODULE_NAME__}} *)(top))->eval();
#if defined(VL_VPI)
VerilatedVpi::callValueCbs(); // for vpi_get_value
#endif
((V{{__TOP_MODULE_NAME__}} *)(top))->contextp()->timeInc(1);
}
} else {
@ -206,6 +212,17 @@ void DutVerilatorBase::SetWaveform(const char *filename)
#endif
};
void DutVerilatorBase::FlushWaveform()
{
#if defined(VL_TRACE)
V{{__TOP_MODULE_NAME__}} *topp = (V{{__TOP_MODULE_NAME__}} *)(this->top);
topp->rootp->vlSymsp->__Vm_dumperp->flush();
#else
std::cerr << "Verilator waveform is not enabled";
exit(-1);
#endif
};
void DutVerilatorBase::SetCoverage(const char *filename)
{
#if defined(VL_COVERAGE)
@ -492,6 +509,15 @@ std::vector<std::string> DutUnifiedBase::VPIInternalSignalList(std::string name,
vpi_iterate_t _vpi_iterate = (vpi_iterate_t)this->GetVPIFuncPtr("vpi_iterate");
vpi_handle_func _vpi_handle = (vpi_handle_func)this->GetVPIFuncPtr("vpi_handle");
// Remove extra "TOP" while input name is empty(TOP)
std::function<std::string(std::string)> remove_top = [&](std::string sig) {
#ifdef USE_VERILATOR
return sig.substr(4);
#else
return sig;
#endif
};
// Define the lambda function to traverse the VPI handle
std::function<void(vpi_handle_t, int)> traverse = [&](vpi_handle_t handle, int depth) {
if (depth == 0) { return; }
@ -502,7 +528,7 @@ std::vector<std::string> DutUnifiedBase::VPIInternalSignalList(std::string name,
while ((vpi_handle = _vpi_scan(regs)) != 0) {
char *name = (char *)_vpi_get_str(vpiFullName, vpi_handle);
XDebug("Found reg %s", name);
res.push_back(std::string(name) + " (reg)");
res.push_back(remove_top(name));
}
// get vpi reg array
@ -510,7 +536,7 @@ std::vector<std::string> DutUnifiedBase::VPIInternalSignalList(std::string name,
while ((vpi_handle = _vpi_scan(reg_arrays)) != 0) {
char *name = (char *)_vpi_get_str(vpiFullName, vpi_handle);
XDebug("Found reg array %s", name);
res.push_back(std::string(name) + " (reg array)");
res.push_back(remove_top(name));
}
// get vpi net
@ -518,7 +544,7 @@ std::vector<std::string> DutUnifiedBase::VPIInternalSignalList(std::string name,
while ((vpi_handle = _vpi_scan(nets)) != 0) {
char *name = (char *)_vpi_get_str(vpiFullName, vpi_handle);
XDebug("Found net %s", name);
res.push_back(std::string(name) + " (net)");
res.push_back(remove_top(name));
}
// get vpi net array
@ -526,7 +552,7 @@ std::vector<std::string> DutUnifiedBase::VPIInternalSignalList(std::string name,
while ((vpi_handle = _vpi_scan(net_arrays)) != 0) {
char *name = (char *)_vpi_get_str(vpiFullName, vpi_handle);
XDebug("Found net array %s", name);
res.push_back(std::string(name) + " (net array)");
res.push_back(remove_top(name));
}
// get vpi module
@ -644,7 +670,10 @@ void DutUnifiedBase::SetWaveform(const std::string filename)
{
return this->dut->SetWaveform(filename.c_str());
}
void DutUnifiedBase::FlushWaveform()
{
return this->dut->FlushWaveform();
}
int DutUnifiedBase::CheckPoint(const char *filename)
{
return this->dut->CheckPoint(filename);

View File

@ -20,6 +20,7 @@ public:
// Set waveform file path
virtual void SetWaveform(const char *filename) = 0;
virtual void FlushWaveform() = 0;
// Set coverage file path
virtual void SetCoverage(const char *filename) = 0;
// Save Model Status with Simulator Capabilities
@ -45,6 +46,7 @@ public:
int Step(uint64_t cycle, bool dump);
int Finish();
void SetWaveform(const char *filename);
void FlushWaveform();
void SetCoverage(const char *filename);
int CheckPoint(const char *filename);
int Restore(const char *filename);
@ -79,6 +81,7 @@ public:
int Step(uint64_t cycle, bool dump);
int Finish();
void SetWaveform(const char *filename);
void FlushWaveform();
void SetCoverage(const char *filename);
int CheckPoint(const char *filename);
int Restore(const char *filename);
@ -128,6 +131,7 @@ public:
std::vector<std::string> VPIInternalSignalList(std::string name, int depth);
void SetWaveform(const char *filename); // Set waveform file path
void SetWaveform(const std::string filename); // Set waveform file path
void FlushWaveform();
void SetCoverage(const char *filename); // Set coverage file path
void SetCoverage(const std::string filename); // Set coverage file path
int CheckPoint(const char *filename);

View File

@ -59,6 +59,9 @@ class DUT{{__TOP_MODULE_NAME__}}(object):
def SetWaveform(self, filename: str):
self.dut.SetWaveform(filename)
def FlushWaveform(self):
self.dut.FlushWaveform()
def SetCoverage(self, filename: str):
self.dut.SetCoverage(filename)