mirror of https://github.com/XS-MLVP/picker.git
feat: add FlushWaveForm() to write wave immediately, for debugger
add doc: API statement
This commit is contained in:
parent
3c1e6cc43f
commit
7b70577b45
|
@ -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()
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}")
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue