20150107

1. 영어 기사 읽기
1) Teen Inventors Connect DVR to Your Zzzs, Scientific American
– Beyond guaranteeing that you don’t miss a moment of valuable television programming, such biometric gizmos someday might be able to sleep-control other aspects of your domestic Internet of things. (gizmo – 새롭고 쓸모있는 간단한 장치)
2) What to Expect Scientists to Do in 2015, Scientific American
– Big changes are afoot. (afoot – 진행 중인)
– The European Union will mull over how to replace the science-adviser position that was scrapped in 2014, and the U.S. will see its Congress move under Republican control. (mull over – 심사숙고하다)
– And Japan is likely to restart “scientific” whaling in Antarctic waters after a hiatus imposed by the International Court of Justice. (hiatus – 중단)


2. MARSS 소스 코드 분석
MARSS의 초기화 및 동작 과정을 이해함. 초기화는 어제 이해한 내용에서 조금 더 구체적으로 확인한 정도임. 오늘 새롭게 이해한 것은 MARSS의 연결 구조 및 동작 과정이다. 이전에도 확인했듯이, 핵심 루틴은 runcycle 함수이다. runcycle에서 파이프라인의 각 과정을 거치며, 한 사이클마다의 동작 과정을 시뮬레이션한다. fetch, issue 등의 함수에서 이벤트를 queue에 등록한다. memoryHierarchy->clock()을 호출하면 적절한 시점에 이벤트를 실행한다.
캐시에 접근하는 과정을 살펴보며 연결 관계를 살펴보자. 캐시에 access할 때 MARSS는 memoryHierarchy->access_cache()를 호출한다. 캐시에 access하는 함수들 중에 하나인 fetch 함수부터 시작해보자.
./ptlsim/core/ooo-core/ooo-pipe.cpp : fetch()

            bool hit;
            assert(!waiting_for_icache_fill);

            Memory::MemoryRequest *request = core.memoryHierarchy->get_free_request(core.get_coreid());
            assert(request != NULL);

            request->init(core.get_coreid(), threadid, physaddr, 0, sim_cycle,
                    true, 0, 0, Memory::MEMORY_OP_READ);
            request->set_coreSignal(&core.icache_signal);

            hit = core.memoryHierarchy->access_cache(request);

./ptlsim/cache/memoryHierarchy.cpp : MemoryHierarchy::access_cache()

bool MemoryHierarchy::access_cache(MemoryRequest *request)
{
    W8 coreid = request->get_coreid();
    CPUController *cpuController = (CPUController*)cpuControllers_[coreid];
    assert(cpuController != NULL);

    int ret_val;
    ret_val = ((CPUController*)cpuController)->access(request);

    if(ret_val == 0)
        return true;

    if(request->get_type() == MEMORY_OP_WRITE)
        return true;

    return false;
}

./ptlsim/cache/cpuController.h : CPUController::access()

        int access(MemoryRequest *request) {
            return access_fast_path(NULL, request);
        }

./ptlsim/cache/cpuController.cpp : CPUController::access_fast_path()

            cache_access_cb(queueEntry);

./ptlsim/build/cache/cpuController.cpp : CPUController::cache_access_cb()

bool CPUController::cache_access_cb(void *arg)
{
    CPUControllerQueueEntry* queueEntry = (CPUControllerQueueEntry*)arg;

    if unlikely (queueEntry->annuled || queueEntry->cycles > 0)
        return true;

    /* Send request to corresponding interconnect */
    Interconnect *interconnect;
    if unlikely (queueEntry->request->is_instruction())
        interconnect = int_L1_i_;
    else
        interconnect = int_L1_d_;

    Message& message = *memoryHierarchy_->get_message();
    message.sender = this;
    message.request = queueEntry->request;
    bool success = interconnect->get_controller_request_signal()->
        emit(&message);
    /* Free the message */
    memoryHierarchy_->free_message(&message);

    if(!success) {
        marss_add_event(&cacheAccess_, 1, queueEntry);
    }

    return true;
}

./ptlsim/cache/interconnect.h : Interconnect

class Interconnect
{
    private:
        stringbuf name_;
        Signal controller_request_;

    public:
        MemoryHierarchy *memoryHierarchy_;
        Interconnect(const char *name, MemoryHierarchy *memoryHierarchy)
            : controller_request_("Controller Request")
            , memoryHierarchy_(memoryHierarchy)
        {
            name_ << name;
            controller_request_.connect(signal_mem_ptr(*this,
                        &Interconnect::controller_request_cb));
        }

        virtual ~Interconnect()
        {
            memoryHierarchy_ = NULL;    
        }

        virtual bool controller_request_cb(void *arg)=0;
        virtual void register_controller(Controller *controller)=0;
        virtual int access_fast_path(Controller *controller,
                MemoryRequest *request)=0;
        virtual void print_map(ostream& os)=0;
        virtual void print(ostream& os) const = 0;
        virtual int get_delay()=0;      
        virtual void annul_request(MemoryRequest* request) = 0;
        virtual void dump_configuration(YAML::Emitter &out) const = 0;

        Signal* get_controller_request_signal() {
            return &controller_request_;
        }

        char* get_name() const {            
            return name_.buf;
        }
};

./ptlsim/build/cache/p2p.cpp : P2PInterconnect::controller_request_cb

bool P2PInterconnect::controller_request_cb(void *arg)
{
    /*
     * P2P is 0 latency interconnect so directly
     * pass it to next controller
     */
    Message *msg = (Message*)arg;

    Controller *receiver = get_other_controller(
            (Controller*)msg->sender);

    Message& message = *memoryHierarchy_->get_message();
    message.sender = (void *)this;  
    message.request = msg->request; 
    message.hasData = msg->hasData; 
    message.arg = msg->arg;

    bool ret_val;
    ret_val = receiver->get_interconnect_signal()->emit((void *)&message);

    /* Free the message */
    memoryHierarchy_->free_message(&message);

    return ret_val;

}

./ptlsim/cache/controller.h : Controller

class Controller
{
    private:
        stringbuf name_;
        Signal handle_interconnect_;    
        bool isPrivate_;

    public:
        MemoryHierarchy *memoryHierarchy_; 
        W8 idx;

        Controller(W8 coreid, const char *name, 
                MemoryHierarchy *memoryHierarchy)
            : handle_interconnect_("handle_interconnect")
            , memoryHierarchy_(memoryHierarchy)
            , idx(coreid)
        {
            name_ << name;
            isPrivate_ = false;

            handle_interconnect_.connect(signal_mem_ptr \
                    (*this, &Controller::handle_interconnect_cb));
        }

        virtual ~Controller()
        {
            memoryHierarchy_ = NULL;    
        }

        virtual bool handle_interconnect_cb(void* arg)=0;
        virtual int access_fast_path(Interconnect *interconnect,
                MemoryRequest *request) { return -1; };
        virtual void register_interconnect(Interconnect* interconnect,
                int conn_type)=0;       
        virtual void print_map(ostream& os)=0;

        virtual void print(ostream& os) const =0;
        virtual bool is_full(bool fromInterconnect = false, MemoryRequest *request = NULL) const = 0;
        virtual void annul_request(MemoryRequest* request) = 0;
        virtual void dump_configuration(YAML::Emitter &out) const = 0;

        int flush() {
            return 0;
        }

        int get_no_pending_request(W8 coreid) { assert(0); return 0; }

        Signal* get_interconnect_signal() { 
            return &handle_interconnect_;
        }

        char* get_name() const {            
            return name_.buf;
        }

        void set_private(bool flag) {       
            isPrivate_ = flag;
        }

        bool is_private() { return isPrivate_; }

};

./ptlsim/build/cache/cacheController.cpp : CacheController::handle_interconnect_cb

bool CacheController::handle_interconnect_cb(void *arg)
{
    Message *msg = (Message*)arg;
    Interconnect *sender = (Interconnect*)msg->sender;

    memdebug("Message received is: ", *msg);

    if(sender == upperInterconnect_ || sender == upperInterconnect2_) {

        if(msg->hasData && msg->request->get_type() !=
                MEMORY_OP_UPDATE)
            return true;

        /*
         * if pendingRequests_ queue is full then simply
         * return false to indicate that this controller
         * can't accept new request at now
         */
        if(is_full(true)) {
            memdebug(get_name() << "Controller queue is full\n");
            return false;
        }

        memdebug(get_name() <<
                " Received message from upper interconnect\n");

        CacheQueueEntry *queueEntry = pendingRequests_.alloc();

        /* set full flag if buffer is full */
        if(pendingRequests_.isFull()) {
            memoryHierarchy_->set_controller_full(this, true);
        }

        if(queueEntry == NULL) {
            return false;
        }

        queueEntry->request = msg->request;
        queueEntry->sender = sender;
        queueEntry->source = (Controller*)msg->origin;
        queueEntry->dest = (Controller*)msg->dest;
        queueEntry->request->incRefCounter();
        ADD_HISTORY_ADD(queueEntry->request);

        /*
         * We are going to access the cache later, to make
         * sure that this entry is not cleared enable the
         * cache access event flag of this entry
         */
        queueEntry->eventFlags[CACHE_ACCESS_EVENT]++;

        if(queueEntry->request->get_type() == MEMORY_OP_UPDATE &&
                wt_disabled_ == false) {
            if(type_ == L2_CACHE || type_ == L3_CACHE) {
                memdebug("L2/L3 cache update sending to lower\n");
                queueEntry->eventFlags[
                    CACHE_WAIT_INTERCONNECT_EVENT]++;
                queueEntry->sendTo = lowerInterconnect_;
                marss_add_event(&waitInterconnect_,
                        0, queueEntry);
            }
        }

        /* Check dependency and access the cache */
        CacheQueueEntry* dependsOn = find_dependency(msg->request);

        if(dependsOn) {
            /* Found an dependency */
            memdebug("dependent entry: " << *dependsOn << endl);
            dependsOn->depends = queueEntry->idx;
            dependsOn->dependsAddr = queueEntry->request->get_physical_address();
            OP_TYPE type = queueEntry->request->get_type();
            bool kernel_req = queueEntry->request->is_kernel();
            if(type == MEMORY_OP_READ) {
                N_STAT_UPDATE(new_stats.cpurequest.stall.read.dependency, ++, kernel_req);
            } else if(type == MEMORY_OP_WRITE) {
                N_STAT_UPDATE(new_stats.cpurequest.stall.write.dependency, ++, kernel_req);
            }
        } else {
            cache_access_cb(queueEntry);
        }

        memdebug("Cache: " << get_name() << " added queue entry: " <<
                *queueEntry << endl);
    } else {
        memdebug(get_name() <<
                " Received message from lower interconnect\n");

        if(msg->hasData) {
            /*
             * This may be a response to our previous request
             * or we might have a pending request to same address
             */
            CacheQueueEntry *queueEntry = find_match(msg->request);

            if(queueEntry != NULL) {
                /*
                 * Do the following only when:
                 *  - we received response to our request
                 *  - we have read miss on same request
                 *
                 * two things here: insert cache entry and response to
                 * upper cache.
                 * So we create two events in parallel.
                 */

                queueEntry->eventFlags[CACHE_WAIT_RESPONSE]--;

                if(queueEntry->prefetch) {
                    /* In case of prefetch just wakeup the dependents entries */
                    queueEntry->prefetchCompleted = true;
                    queueEntry->eventFlags[CACHE_INSERT_EVENT]++;
                    marss_add_event(&cacheInsert_, 1,
                            (void*)(queueEntry));
                } else if(msg->request == queueEntry->request ||
                        (msg->request != queueEntry->request &&
                         queueEntry->request->get_type() ==
                         MEMORY_OP_READ) ) {

                    queueEntry->sendTo = queueEntry->sender;

                    queueEntry->eventFlags[CACHE_INSERT_EVENT]++;
                    queueEntry->eventFlags[
                        CACHE_WAIT_INTERCONNECT_EVENT]++;

                    memdebug("Queue entry flag after both events: " <<
                            queueEntry->eventFlags << endl);

                    marss_add_event(&cacheInsert_, 0,
                            (void*)(queueEntry));
                    marss_add_event(&waitInterconnect_, 0,
                            (void*)(queueEntry));
                }
            } else if (!is_lowest_private()) {
                /*
                 * if request is cache update, then access the cache
                 * and update its data
                 */
                if(msg->request->get_type() == MEMORY_OP_UPDATE) {

                    if(is_full(true)) {
                        memdebug(get_name() << "Controller queue is full\n");
                        return false;
                    }

                    CacheQueueEntry *newEntry = pendingRequests_.alloc();
                    assert(newEntry);
                    /* set full flag if buffer is full */
                    if(pendingRequests_.isFull()) {
                        memoryHierarchy_->set_controller_full(this, true);
                    }

                    newEntry->request = msg->request;
                    newEntry->sender = sender;
                    newEntry->source = (Controller*)msg->origin;
                    newEntry->dest = (Controller*)msg->dest;
                    newEntry->request->incRefCounter();
                    ADD_HISTORY_ADD(newEntry->request);

                    newEntry->eventFlags[CACHE_ACCESS_EVENT]++;

                    /* if its a L2 cache or L3 cache send to lower memory */
                    if((type_ == L2_CACHE || type_ == L3_CACHE) &&
                                isLowestPrivate_ == false) {
                        memdebug("L2 cache update sending to lower\n");
                        newEntry->eventFlags[
                            CACHE_WAIT_INTERCONNECT_EVENT]++;
                        newEntry->sendTo = lowerInterconnect_;
                        marss_add_event(&waitInterconnect_,
                                0, newEntry);
                    }

                    marss_add_event(&cacheAccess_, 0,
                            newEntry);
                }
                else {
                    memdebug("Request " << *msg->request << " does not\
                            has data but not update and can't find\
                            any pending local entry\n");
                }
            }
        } else {
            /*
             * Its a request from other caches, ignore them unless
             * its a cache update request. In case of cache update
             * if we have cached same line, update that line
             */
            if(msg->request->get_type() == MEMORY_OP_UPDATE) {
                assert(0);
            }
            else {
                memdebug("message doesn't have data for request:" <<
                        *(msg->request) << endl);
            }
        }
    }

    return true;
}

CPUController, Interconnect, CacheController 등이 연결되어 있음을 볼 수 있다. 각 controller는 자기가 원하는 이벤트를 바로 그 다음 레벨로 넘기는 것이 아니라, 큐에 넣어두고 적절한 시점에 다음으로 전달해준다. 각 controller는 pendingQueue_ 변수를 갖고 있다.

한편, Context 구조체와 Thread 구조체의 차이는 무엇인가?
정섭이 형에게 소스 코드 설명을 들음.

정섭이 형에게 받은 소스 코드를 마침내 실행해보려 했는데, 에러가 발생했다.


3. SIGOPS([OSDI’14] Arrakis: The Operating System is the Control Plane)
IO 중에서도 네트워크 그리고 저장장치에 접근에서 오버헤드가 심하다. 이를 줄이기 위해 어플리케이션이 kernel 영역을 우회하여, 직접 IO 장치에 접근 가능하도록 하자. 가상화 기술 SR-IOV와 IOMMU를 사용해 성능 향상이 가능하다. Kernel에서 원래 제공하던 기능인 isolation을 제공하면서도 성능 향상을 이룰 수 있다.


4. Computer Architecture A Quantitative Approach 읽음
Chapter 5에서 snooping coherence protocol 읽음. 내일은 directory coherence protocol에 대해 읽을 것.


5. 앞으로 공부 & 연구해야 할 것
가상화에 대한 이해가 부족한 것 같다. 가상화 기술이 어떻게 구현되어 있는지, 이슈가 무엇인지 알아야 문제점을 발견할 수 있을 것이다. 가상화에 대해서도 공부해야 할 것 같다.

Advertisements
Posted in 1) Memo
One comment on “20150107
  1. […] 2. MARSS 개발 MemoryRequest와 cacheline에 새로운 정보를 추가해야 한다. MemoryRequest가 cache까지 도달하는 과정을 이전에 기록해두었다(2015/01/07, https://gumdaeng.com/2015/01/07/20150107/). […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

누적 방문자 수
  • 96,405 hits
%d bloggers like this: