# Linux Kernel Module Cheat

###### 24.22.6.1.2. gem5 `O3ThreadContext`

Instantiation happens in the `FullO3CPU` constructor:

    FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)

        for (ThreadID tid = 0; tid < this->numThreads; ++tid) {
            if (FullSystem) {
                // SMT is not supported in FS mode yet.
                assert(this->numThreads == 1);
                this->thread[tid] = new Thread(this, 0, NULL);

            // Setup the TC that will serve as the interface to the threads/CPU.
            O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>;

and the SimObject `DerivO3CPU` is just a `FullO3CPU` instantiation:

    class DerivO3CPU : public FullO3CPU<O3CPUImpl>

`O3ThreadContext` is a template class:

    template <class Impl>
    class O3ThreadContext : public ThreadContext

The only `Impl` used appears to be `O3CPUImpl`? This is explicitly instantiated in the source:

    template class O3ThreadContext<O3CPUImpl>;

see also: https://stackoverflow.com/questions/64420547/in-gem5-how-do-i-know-the-specific-location-of-the-class/64423633#64423633

Unlike in `SimpleThread` however, `O3ThreadContext` does not contain the register data itself, e.g. `O3ThreadContext::readIntRegFlat` instead forwards to `cpu`:

    template <class Impl>
    RegVal
    O3ThreadContext<Impl>::readIntRegFlat(RegIndex reg_idx) const
    {
        return cpu->readArchIntReg(reg_idx, thread->threadId());
    }

where:

        typedef typename Impl::O3CPU O3CPU;

       /** Pointer to the CPU. */
        O3CPU *cpu;

and:

    struct O3CPUImpl
    {
        /** The O3CPU type to be used. */
        typedef FullO3CPU<O3CPUImpl> O3CPU;

and at long last `FullO3CPU` contains the register values:

    template <class Impl>
    RegVal
    FullO3CPU<Impl>::readArchIntReg(int reg_idx, ThreadID tid)
    {
        intRegfileReads++;
        PhysRegIdPtr phys_reg = commitRenameMap[tid].lookup(
                RegId(IntRegClass, reg_idx));

        return regFile.readIntReg(phys_reg);
    }

So we guess that this difference from `SimpleThread` is due to register renaming of the out of order implementation.