本文为英文版本翻译,原文地址:
Delta Cycle
Sensitivity
增量周期(Delta Cycle)
增量周期可以理解为仿真中一段非常小的时间,这段时间不会增加用户可见时间。
一个增量周期有单独的评估和更新阶段,在一个特定的仿真时间可能发生多个增量周期。
当发生一个信号赋值时,其它仿真过程直到下一个增量周期后才能观察到新的赋值。
什么时候使用增量周期:
When is delta cycle used:
notify(SC_ZERO_TIME)
:下一个增量周期的评估阶段通知事件,称为“增量通知”(delta notification)request_update()
:直接或间接调用request_update()
会触发当前增量周期更新阶段调用update()
示例代码
下面是该接的示例代码:
// Learn with Examples, 2020, MIT license
#include <systemc>
using namespace sc_core;
SC_MODULE(DELTA) {
int x = 1, y = 1; // defines two member variables
SC_CTOR(DELTA) {
SC_THREAD(add_x); // x += 2
SC_THREAD(multiply_x); // x *= 3
SC_THREAD(add_y); // y += 2
SC_THREAD(multiply_y); // y *= 3
}
void add_x() { // x += 2 happens first
std::cout << "add_x: " << x << " + 2" << " = ";
x += 2;
std::cout << x << std::endl;
}
void multiply_x() { // x *= 3 happens after a delta cycle
wait(SC_ZERO_TIME);
std::cout << "multiply_x: " << x << " * 3" << " = ";
x *= 3;
std::cout << x << std::endl;
}
void add_y() { // y += 2 happens after a delta cycle
wait(SC_ZERO_TIME);
std::cout << "add_y: " << y << " + 2" << " = ";
y += 2;
std::cout << y << std::endl;
}
void multiply_y() { // y *=3 happens first
std::cout << "multiply_y: " << y << " * 3" << " = ";
y *= 3;
std::cout << y << std::endl;
}
};
int sc_main(int, char*[]) {
DELTA delta("delta");
sc_start();
return 0;
}
运行结果:
# because of the delta_cycle, x and y goes through different orders of arithmetic calculation, achieving different results.
add_x: 1 + 2 = 3 # x += 2 happens first
multiply_y: 1 * 3 = 3 # y *= 3 happens first
add_y: 3 + 2 = 5 # (y*3) + 2 = 5
multiply_x: 3 * 3 = 9 # (x+2) * 3 = 9
敏感元(Sensitivity)
仿真进程的敏感元是一系列事件,超时等集合,它们可以引起继续执行或触发仿真进程。
事件(Event)
如果一个事件被添加到仿真进程实例的静态敏感元或动态敏感元,那么这个仿真进程实例就对该事件敏感。
超时(Timeout)
超时在设定的时间流逝后触发。
两种敏感元
- 静态敏感
Static sensitivity
:通过给模型中仿真进程提供敏感列表实现,其在阐述阶段确定 - 动态敏感
Dynamic sensitivity
在仿真进程中会有不同操作,例如:
SC_THREAD注册的仿真进程中:wait()
SC_METHOD注册的仿真进程中:next_trigger()
示例代码
// Learn with Examples, 2020, MIT license
#include <systemc>
using namespace sc_core;
SC_MODULE(SENSITIVITY) {
sc_event e1, e2; // events for inter-process triggering
SC_CTOR(SENSITIVITY) {
SC_THREAD(trigger_1); // register processes
SC_THREAD(trigger_2);
SC_THREAD(catch_1or2_dyn);
SC_THREAD(catch_1or2_static);
sensitive << e1 << e2; // static sensitivity for the preceeding process, can only "OR" the triggers
}
void trigger_1() {
wait(SC_ZERO_TIME); // delay trigger by a delta cycle, make sure catcher is ready
while (true) {
e1.notify(); // trigger e1
wait(2, SC_SEC); // dynamic sensitivity, re-trigger after 2 s
}
}
void trigger_2() { // delay trigger by a delta cycle
wait(SC_ZERO_TIME);
while (true) {
e2.notify(); // trigger e2
wait(3, SC_SEC); // dynamic sensitivity, re-trigger after 3 s
}
}
void catch_1or2_dyn() {
while (true) {
wait(e1 | e2); // dynamic sensitivity
std::cout << "Dynamic sensitivty: e1 or e2 @ " << sc_time_stamp() << std::endl;
}
}
void catch_1or2_static(void) {
while (true) {
wait(); // static sensitivity
std::cout << "Static sensitivity: e1 or e2 @ " << sc_time_stamp() << std::endl;
}
}
};
int sc_main(int, char*[]) {
SENSITIVITY sensitivity("sensitivity");
sc_start(7, SC_SEC);
return 0;
}
运行结果:
# e1 triggered at 0, 2, 4, 6 s; e2 triggered at 0, 3, 6 s
Static sensitivity: e1 or e2 @ 0 s # e1 or e2
Dynamic sensitivty: e1 or e2 @ 0 s # e1 or e2
Static sensitivity: e1 or e2 @2 s # e1 or e2
Dynamic sensitivty: e1 or e2 @2 s # e1 or e2
Static sensitivity: e1 or e2 @3 s # e2
Dynamic sensitivty: e1 or e2 @3 s # e2
Static sensitivity: e1 or e2 @4 s # e1
Dynamic sensitivty: e1 or e2 @4 s # e1
Static sensitivity: e1 or e2 @6 s # e1 or e2
Dynamic sensitivty: e1 or e2 @6 s # e1 or e2