2

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.

Martin Thompson
  • 16,395
  • 1
  • 38
  • 56
Andry
  • 16,172
  • 27
  • 138
  • 246

2 Answers2

3

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?

Martin Thompson
  • 16,395
  • 1
  • 38
  • 56
  • You're right Martin... I didn't try it but I am sure it is correct what you just said. I've written code in VHDL and also knew that this problem persists in SystemC too (it is not a problem, just a time model). I do not know why I was so stubborn not seeing this stupid problem... I am somehow ashamed for having asked... Thankyou very much... :) – Andry Apr 13 '11 at 15:29
0

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

Daniel
  • 53
  • 7
  • Now that project of mine is in standby but when I will get on it again I'll try this... thankyou for caring :) – Andry May 11 '12 at 07:19