SystemC 仿真应用程序中的信号处理问题

发布于 2024-10-31 21:20:55 字数 4863 浏览 0 评论 0原文

我正在模拟 CPU,并使用高级模拟工具来完成此操作。 SystemC 是实现这些目的的一个很好的资源。我使用两个模块:

  • DataPath

  • Memory

更好:

CPU 数据路径被建模为一个独特的高级实体,但是以下代码肯定比任何其他解释 下面是 datapath.hpp

SC_MODULE(DataPath) {
    sc_in_clk clk;
    sc_in<bool> rst;
    ///
    /// Outgoing data from memory.
    ///
    sc_in<w32> mem_data;
    ///
    /// Memory read enable control signal.
    ///
    sc_out<sc_logic> mem_ctr_memreadenable;
    ///
    /// Memory write enable control signal.
    ///
    sc_out<sc_logic> mem_ctr_memwriteenable;
    ///
    /// Data to be written in memory.
    ///
    sc_out<w32> mem_dataw; //w32 is sc_lv<32>
    ///
    /// Address in mem to read and write.
    ///
    sc_out<memaddr> mem_addr;
    ///
    /// Program counter.
    ///
    sc_signal<w32> pc;
    ///
    /// State signal.
    ///
    sc_signal<int> cu_state;
    ///
    /// Other internal signals mapping registers' value.
    /// ...

    // Defining process functions
    ///
    /// Clock driven process to change state.
    ///
    void state_process();
    ///
    /// State driven process to apply control signals.
    ///
    void control_process();

    // Constructors
    SC_CTOR(DataPath) {
        // Defining first process
        SC_CTHREAD(state_process, clk.neg());
        reset_signal_is(this->rst, true);
        // Defining second process
        SC_METHOD(control_process);
        sensitive << (this->cu_state) << (this->rst);
    }

    // Defining general functions
    void reset_signals();
};

下面是 datapath.cpp

void DataPath::state_process() {
    // Useful variables
    w32 ir_value; /* Placing here IR register value */
    // Initialization phase
    this->cu_state.write(StateFetch); /* StateFetch is a constant */
    wait(); /* Wait next clock fall edge */
    // Cycling
    for (;;) {
        // Checking state
        switch (this->cu_state.read()) { // Basing on state, let's change the next one
        case StateFetch: /* FETCH */
            this->cu_state.write(StateDecode); /* Transition to DECODE */
            break;
        case StateDecode: /* DECODE */
            // Doing decode
            break;
        case StateExecR: /* EXEC R */
            // For every state, manage transition to the next state
            break;
        //...
        //...
        default: /* Possible not recognized state */
            this->cu_state.write(StateFetch); /* Come back to fetch */
        } /* switch */
        // After doing, wait for the next clock fall edge
        wait();
    } /* for */
} /* function */

// State driven process for managing signal assignment
// This is a method process
void DataPath::control_process() {
    // If reset signal is up then CU must be resetted
    if (this->rst.read()) {
        // Reset
        this->reset_signals(); /* Initializing signals */
    } else {
        // No Reset
        // Switching on state
        switch (this->cu_state.read()) {
        case StateFetch: /* FETCH */
            // Managing memory address and instruction fetch to place in IR
            this->mem_ctr_memreadenable.write(logic_sgm_1); /* Enabling memory to be read */
            this->mem_ctr_memwriteenable.write(logic_sgm_0); /* Disabling memory from being written */
            std::cout << "Entering fetch, memread=" << this->mem_ctr_memreadenable.read() << " memwrite=" << this->mem_ctr_memreadenable.read() << std::endl;
            // Here I read from memory and get the instruction with some code that you do not need to worry about because my problem occurs HERE ###
            break;
        case kCUStateDecode: /* DECODE */
            // ...
            break;
        //...
        //...
        default: /* Unrecognized */
            newpc = "00000000000000000000000000000000";
        } /* state switch */
    } /* rst if */
} /* function */

// Resetting signals
void DataPath::reset_signals() {
    // Out signals
    this->mem_ctr_memreadenable.write(logic_sgm_1);
    this->mem_ctr_memwriteenable.write(logic_sgm_0);
}

如您所见,我们有一个处理 cpu 转换(更改状态)的时钟驱动进程和一个为 cpu 设置信号的状态驱动进程。

我的问题是,当我到达 ### 时,我希望指令被内存释放(您看不到指令,但它们是正确的,内存组件使用输入和输出信号连接到数据路径可以在hpp文件中看到)。 内存让我“XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX”,因为mem_ctr_memreadenablemem_ctr_memwriteenable都设置为'0'。 内存模块是为了成为即时组件而编写的。它是使用 SC_METHOD 编写的,其 sensitive 在输入信号上定义(包括读使能和写使能)。当 mem_ctr_memreadenable 信号为 '0' 时,内存组件获取 “XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX”

为什么是'0'?我重置信号并将该信号设置为'1'。我不明白为什么我一直使用 '0' 作为读取启用信号。

你能帮助我吗? 谢谢。

I am simulating a CPU and I'm doing this using high level simulation tools. SystemC is a good resource for these purposes. I'm using two modules:

  • DataPath

  • Memory

CPU datapath is modeled as a unique high level entity, however the following code will sure be better than any other explaination:

The following is datapath.hpp

SC_MODULE(DataPath) {
    sc_in_clk clk;
    sc_in<bool> rst;
    ///
    /// Outgoing data from memory.
    ///
    sc_in<w32> mem_data;
    ///
    /// Memory read enable control signal.
    ///
    sc_out<sc_logic> mem_ctr_memreadenable;
    ///
    /// Memory write enable control signal.
    ///
    sc_out<sc_logic> mem_ctr_memwriteenable;
    ///
    /// Data to be written in memory.
    ///
    sc_out<w32> mem_dataw; //w32 is sc_lv<32>
    ///
    /// Address in mem to read and write.
    ///
    sc_out<memaddr> mem_addr;
    ///
    /// Program counter.
    ///
    sc_signal<w32> pc;
    ///
    /// State signal.
    ///
    sc_signal<int> cu_state;
    ///
    /// Other internal signals mapping registers' value.
    /// ...

    // Defining process functions
    ///
    /// Clock driven process to change state.
    ///
    void state_process();
    ///
    /// State driven process to apply control signals.
    ///
    void control_process();

    // Constructors
    SC_CTOR(DataPath) {
        // Defining first process
        SC_CTHREAD(state_process, clk.neg());
        reset_signal_is(this->rst, true);
        // Defining second process
        SC_METHOD(control_process);
        sensitive << (this->cu_state) << (this->rst);
    }

    // Defining general functions
    void reset_signals();
};

The following is datapath.cpp

void DataPath::state_process() {
    // Useful variables
    w32 ir_value; /* Placing here IR register value */
    // Initialization phase
    this->cu_state.write(StateFetch); /* StateFetch is a constant */
    wait(); /* Wait next clock fall edge */
    // Cycling
    for (;;) {
        // Checking state
        switch (this->cu_state.read()) { // Basing on state, let's change the next one
        case StateFetch: /* FETCH */
            this->cu_state.write(StateDecode); /* Transition to DECODE */
            break;
        case StateDecode: /* DECODE */
            // Doing decode
            break;
        case StateExecR: /* EXEC R */
            // For every state, manage transition to the next state
            break;
        //...
        //...
        default: /* Possible not recognized state */
            this->cu_state.write(StateFetch); /* Come back to fetch */
        } /* switch */
        // After doing, wait for the next clock fall edge
        wait();
    } /* for */
} /* function */

// State driven process for managing signal assignment
// This is a method process
void DataPath::control_process() {
    // If reset signal is up then CU must be resetted
    if (this->rst.read()) {
        // Reset
        this->reset_signals(); /* Initializing signals */
    } else {
        // No Reset
        // Switching on state
        switch (this->cu_state.read()) {
        case StateFetch: /* FETCH */
            // Managing memory address and instruction fetch to place in IR
            this->mem_ctr_memreadenable.write(logic_sgm_1); /* Enabling memory to be read */
            this->mem_ctr_memwriteenable.write(logic_sgm_0); /* Disabling memory from being written */
            std::cout << "Entering fetch, memread=" << this->mem_ctr_memreadenable.read() << " memwrite=" << this->mem_ctr_memreadenable.read() << std::endl;
            // Here I read from memory and get the instruction with some code that you do not need to worry about because my problem occurs HERE ###
            break;
        case kCUStateDecode: /* DECODE */
            // ...
            break;
        //...
        //...
        default: /* Unrecognized */
            newpc = "00000000000000000000000000000000";
        } /* state switch */
    } /* rst if */
} /* function */

// Resetting signals
void DataPath::reset_signals() {
    // Out signals
    this->mem_ctr_memreadenable.write(logic_sgm_1);
    this->mem_ctr_memwriteenable.write(logic_sgm_0);
}

As you can see we have a clock driven process that handles cpu transitions (changing state) and a state driven process that sets signals for cpu.

My problem is that when I arrive in ### I expect the instruction being released by memory (you cannot see the instructions but they are correct, the memory component is connected to datapath using in and out singals you can see in the hpp file).
Memory gets me "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" because mem_ctr_memreadenable and mem_ctr_memwriteenable are both set to '0'.
Memory module is written in order to be an instant component. It is written using a SC_METHOD whose sensitive is defined on input signals (read enable and write enable included). The memory component gets "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" when the mem_ctr_memreadenable signal is '0'.

Why is it '0'? I reset signals and set that signal to '1'. I do not understand why I keep having '0' for the read enable signal.

Can you help me?
Thankyou.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

虐人心 2024-11-07 21:20:55

我不是 SystemC 专家,但它看起来可能与常见的 VHDL 问题类似,即信号在至少经过一个 delta 周期后才会更新:

this->mem_ctr_memreadenable.write(logic_sgm_1); /* Enabling memory to be read */
this->mem_ctr_memwriteenable.write(logic_sgm_0); /* Disabling memory from being written */

我的猜测:这两行和下一行之间没有时间经过:

std::cout << "Entering fetch, memread=" << this->mem_ctr_memreadenable.read() << " memwrite=" << this->mem_ctr_memreadenable.read() << std::endl;

所以内存还没有看到读取信号变化。顺便说一句,是否应该将 read() 调用之一附加到 mem_ctr_memwriteenable - 两者似乎都是可读的?

如果您:

wait(1, SC_NS);

在这两点之间,事情是否有所改善?

I'm no SystemC guru, but it looks like it might be a similar problem to a common VHDL problem of signals not updating until at least a delta-cycle has passed:

this->mem_ctr_memreadenable.write(logic_sgm_1); /* Enabling memory to be read */
this->mem_ctr_memwriteenable.write(logic_sgm_0); /* Disabling memory from being written */

My guess: No time passes between these two lines and this next line:

std::cout << "Entering fetch, memread=" << this->mem_ctr_memreadenable.read() << " memwrite=" << this->mem_ctr_memreadenable.read() << std::endl;

So the memory hasn't yet seen the read signal change. BTW, should one of the read() calls attached to mem_ctr_memwriteenable - the both seem to be on readenable?

If you:

wait(1, SC_NS);

between those two points, does it improve matters?

三生路 2024-11-07 21:20:55

要获得与内存模块的零时间同步,您应该使用
等待(SC_ZERO_TIME); //等待一个增量周期
不要在定时模拟中引入任意的时间消耗。
这也迫使您将 control_process 升级为 SC_THREAD

To get a zero time synchronization with the memory module you should use
wait(SC_ZERO_TIME); //wait one delta cycle
not to introduce an arbitrary consumtion of time in your timed simulation.
This also impose you upgrade your control_process to an SC_THREAD

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文