Sequencer.cc (6152:705b277e1141) Sequencer.cc (6153:0011560d49b0)
1
2/*
3 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright

--- 32 unchanged lines hidden (view full) ---

41#include "RubyConfig.hh"
42//#include "Tracer.hh"
43#include "AbstractChip.hh"
44#include "Chip.hh"
45#include "Tester.hh"
46#include "SubBlock.hh"
47#include "Protocol.hh"
48#include "Map.hh"
1
2/*
3 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright

--- 32 unchanged lines hidden (view full) ---

41#include "RubyConfig.hh"
42//#include "Tracer.hh"
43#include "AbstractChip.hh"
44#include "Chip.hh"
45#include "Tester.hh"
46#include "SubBlock.hh"
47#include "Protocol.hh"
48#include "Map.hh"
49#include "interface.hh"
50
51Sequencer::Sequencer(AbstractChip* chip_ptr, int version) {
52 m_chip_ptr = chip_ptr;
53 m_version = version;
54
55 m_deadlock_check_scheduled = false;
56 m_outstanding_count = 0;
57

--- 534 unchanged lines hidden (view full) ---

592 g_system_ptr->getProfiler()->swPrefetchLatency(miss_latency, type, respondingMach);
593 return; // Ignore the software prefetch, don't callback the driver
594 }
595
596 // Profile the miss latency for all non-zero demand misses
597 if (miss_latency != 0) {
598 g_system_ptr->getProfiler()->missLatency(miss_latency, type, respondingMach);
599
49
50Sequencer::Sequencer(AbstractChip* chip_ptr, int version) {
51 m_chip_ptr = chip_ptr;
52 m_version = version;
53
54 m_deadlock_check_scheduled = false;
55 m_outstanding_count = 0;
56

--- 534 unchanged lines hidden (view full) ---

591 g_system_ptr->getProfiler()->swPrefetchLatency(miss_latency, type, respondingMach);
592 return; // Ignore the software prefetch, don't callback the driver
593 }
594
595 // Profile the miss latency for all non-zero demand misses
596 if (miss_latency != 0) {
597 g_system_ptr->getProfiler()->missLatency(miss_latency, type, respondingMach);
598
600#if 0
601 uinteger_t tick = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "tick"));
602 uinteger_t tick_cmpr = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "tick_cmpr"));
603 uinteger_t stick = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "stick"));
604 uinteger_t stick_cmpr = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "stick_cmpr"));
605 cout << "END PROC " << m_version << hex << " tick = " << tick << " tick_cmpr = " << tick_cmpr << " stick = " << stick << " stick_cmpr = " << stick_cmpr << " cycle = "<< g_eventQueue_ptr->getTime() << dec << endl;
606#endif
607
608 }
609
610 bool write =
611 (type == CacheRequestType_ST) ||
612 (type == CacheRequestType_ATOMIC);
613
614 if (TSO && write) {
615 m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->callBack(line_address(request.getAddress()), data);
616 } else {
617
618 // Copy the correct bytes out of the cache line into the subblock
619 SubBlock subblock(request_address, request_logical_address, size);
620 subblock.mergeFrom(data); // copy the correct bytes from DataBlock in the SubBlock
621
622 // Scan the store buffer to see if there are any outstanding stores we need to collect
623 if (TSO) {
624 m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->updateSubBlock(subblock);
625 }
626
599 }
600
601 bool write =
602 (type == CacheRequestType_ST) ||
603 (type == CacheRequestType_ATOMIC);
604
605 if (TSO && write) {
606 m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->callBack(line_address(request.getAddress()), data);
607 } else {
608
609 // Copy the correct bytes out of the cache line into the subblock
610 SubBlock subblock(request_address, request_logical_address, size);
611 subblock.mergeFrom(data); // copy the correct bytes from DataBlock in the SubBlock
612
613 // Scan the store buffer to see if there are any outstanding stores we need to collect
614 if (TSO) {
615 m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->updateSubBlock(subblock);
616 }
617
627 // Call into the Driver (Tester or Simics) and let it read and/or modify the sub-block
618 // Call into the Driver and let it read and/or modify the sub-block
628 g_system_ptr->getDriver()->hitCallback(m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version, subblock, type, threadID);
629
630 // If the request was a Store or Atomic, apply the changes in the SubBlock to the DataBlock
631 // (This is only triggered for the non-TSO case)
632 if (write) {
633 assert(!TSO);
634 subblock.mergeTo(data); // copy the correct bytes from SubBlock into the DataBlock
635 }
636 }
637}
638
619 g_system_ptr->getDriver()->hitCallback(m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version, subblock, type, threadID);
620
621 // If the request was a Store or Atomic, apply the changes in the SubBlock to the DataBlock
622 // (This is only triggered for the non-TSO case)
623 if (write) {
624 assert(!TSO);
625 subblock.mergeTo(data); // copy the correct bytes from SubBlock into the DataBlock
626 }
627 }
628}
629
630void Sequencer::readConflictCallback(const Address& address) {
631 // process oldest thread first
632 int thread = -1;
633 Time oldest_time = 0;
634 int smt_threads = RubyConfig::numberofSMTThreads();
635 for(int t=0; t < smt_threads; ++t){
636 if(m_readRequestTable_ptr[t]->exist(address)){
637 CacheMsg & request = m_readRequestTable_ptr[t]->lookup(address);
638 if(thread == -1 || (request.getTime() < oldest_time) ){
639 thread = t;
640 oldest_time = request.getTime();
641 }
642 }
643 }
644 // make sure we found an oldest thread
645 ASSERT(thread != -1);
646
647 CacheMsg & request = m_readRequestTable_ptr[thread]->lookup(address);
648
649 readConflictCallback(address, GenericMachineType_NULL, thread);
650}
651
652void Sequencer::readConflictCallback(const Address& address, GenericMachineType respondingMach, int thread) {
653 assert(address == line_address(address));
654 assert(m_readRequestTable_ptr[thread]->exist(line_address(address)));
655
656 CacheMsg request = m_readRequestTable_ptr[thread]->lookup(address);
657 assert( request.getThreadID() == thread );
658 removeRequest(request);
659
660 assert((request.getType() == CacheRequestType_LD) ||
661 (request.getType() == CacheRequestType_LD_XACT) ||
662 (request.getType() == CacheRequestType_IFETCH)
663 );
664
665 conflictCallback(request, respondingMach, thread);
666}
667
668void Sequencer::writeConflictCallback(const Address& address) {
669 // process oldest thread first
670 int thread = -1;
671 Time oldest_time = 0;
672 int smt_threads = RubyConfig::numberofSMTThreads();
673 for(int t=0; t < smt_threads; ++t){
674 if(m_writeRequestTable_ptr[t]->exist(address)){
675 CacheMsg & request = m_writeRequestTable_ptr[t]->lookup(address);
676 if(thread == -1 || (request.getTime() < oldest_time) ){
677 thread = t;
678 oldest_time = request.getTime();
679 }
680 }
681 }
682 // make sure we found an oldest thread
683 ASSERT(thread != -1);
684
685 CacheMsg & request = m_writeRequestTable_ptr[thread]->lookup(address);
686
687 writeConflictCallback(address, GenericMachineType_NULL, thread);
688}
689
690void Sequencer::writeConflictCallback(const Address& address, GenericMachineType respondingMach, int thread) {
691 assert(address == line_address(address));
692 assert(m_writeRequestTable_ptr[thread]->exist(line_address(address)));
693 CacheMsg request = m_writeRequestTable_ptr[thread]->lookup(address);
694 assert( request.getThreadID() == thread);
695 removeRequest(request);
696
697 assert((request.getType() == CacheRequestType_ST) ||
698 (request.getType() == CacheRequestType_ST_XACT) ||
699 (request.getType() == CacheRequestType_LDX_XACT) ||
700 (request.getType() == CacheRequestType_ATOMIC));
701
702 conflictCallback(request, respondingMach, thread);
703
704}
705
706void Sequencer::conflictCallback(const CacheMsg& request, GenericMachineType respondingMach, int thread) {
707 assert(XACT_MEMORY);
708 int size = request.getSize();
709 Address request_address = request.getAddress();
710 Address request_logical_address = request.getLogicalAddress();
711 Address request_line_address = line_address(request_address);
712 CacheRequestType type = request.getType();
713 int threadID = request.getThreadID();
714 Time issued_time = request.getTime();
715 int logical_proc_no = ((m_chip_ptr->getID() * RubyConfig::numberOfProcsPerChip()) + m_version) * RubyConfig::numberofSMTThreads() + threadID;
716
717 DEBUG_MSG(SEQUENCER_COMP, MedPrio, size);
718
719 assert(g_eventQueue_ptr->getTime() >= issued_time);
720 Time miss_latency = g_eventQueue_ptr->getTime() - issued_time;
721
722 if (PROTOCOL_DEBUG_TRACE) {
723 g_system_ptr->getProfiler()->profileTransition("Seq", (m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version), -1, request.getAddress(), "", "Conflict", "",
724 int_to_string(miss_latency)+" cycles "+GenericMachineType_to_string(respondingMach)+" "+CacheRequestType_to_string(request.getType())+" "+PrefetchBit_to_string(request.getPrefetch()));
725 }
726
727 DEBUG_MSG(SEQUENCER_COMP, MedPrio, request_address);
728 DEBUG_MSG(SEQUENCER_COMP, MedPrio, request.getPrefetch());
729 if (request.getPrefetch() == PrefetchBit_Yes) {
730 DEBUG_MSG(SEQUENCER_COMP, MedPrio, "return");
731 g_system_ptr->getProfiler()->swPrefetchLatency(miss_latency, type, respondingMach);
732 return; // Ignore the software prefetch, don't callback the driver
733 }
734
735 bool write =
736 (type == CacheRequestType_ST) ||
737 (type == CacheRequestType_ST_XACT) ||
738 (type == CacheRequestType_LDX_XACT) ||
739 (type == CacheRequestType_ATOMIC);
740
741 // Copy the correct bytes out of the cache line into the subblock
742 SubBlock subblock(request_address, request_logical_address, size);
743
744 // Call into the Driver
745 g_system_ptr->getDriver()->conflictCallback(m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version, subblock, type, threadID);
746
747 // If the request was a Store or Atomic, apply the changes in the SubBlock to the DataBlock
748 // (This is only triggered for the non-TSO case)
749 if (write) {
750 assert(!TSO);
751 }
752}
753
639void Sequencer::printDebug(){
640 //notify driver of debug
641 g_system_ptr->getDriver()->printDebug();
642}
643
644// Returns true if the sequencer already has a load or store outstanding
645bool
646Sequencer::isReady(const Packet* pkt) const

--- 58 unchanged lines hidden (view full) ---

705 }
706
707 if (TSO) {
708 return m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->isReady();
709 }
710 return true;
711}
712
754void Sequencer::printDebug(){
755 //notify driver of debug
756 g_system_ptr->getDriver()->printDebug();
757}
758
759// Returns true if the sequencer already has a load or store outstanding
760bool
761Sequencer::isReady(const Packet* pkt) const

--- 58 unchanged lines hidden (view full) ---

820 }
821
822 if (TSO) {
823 return m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->isReady();
824 }
825 return true;
826}
827
713// Called by Driver (Simics or Tester).
828// Called by Driver
714void
715Sequencer::makeRequest(const Packet* pkt, void* data)
716{
717 int cpu_number = pkt->req->contextId();
718 la_t logical_addr = pkt->req->getVaddr();
719 pa_t physical_addr = pkt->req->getPaddr();
720 int request_size = pkt->getSize();
721 CacheRequestType type_of_request;

--- 59 unchanged lines hidden (view full) ---

781 data_ptr);
782
783 if (hit && (request.getType() == CacheRequestType_IFETCH || !REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH) ) {
784 DEBUG_MSG(SEQUENCER_COMP, MedPrio, "Fast path hit");
785 hitCallback(request, *data_ptr, GenericMachineType_L1Cache, thread);
786 return true;
787 }
788
829void
830Sequencer::makeRequest(const Packet* pkt, void* data)
831{
832 int cpu_number = pkt->req->contextId();
833 la_t logical_addr = pkt->req->getVaddr();
834 pa_t physical_addr = pkt->req->getPaddr();
835 int request_size = pkt->getSize();
836 CacheRequestType type_of_request;

--- 59 unchanged lines hidden (view full) ---

896 data_ptr);
897
898 if (hit && (request.getType() == CacheRequestType_IFETCH || !REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH) ) {
899 DEBUG_MSG(SEQUENCER_COMP, MedPrio, "Fast path hit");
900 hitCallback(request, *data_ptr, GenericMachineType_L1Cache, thread);
901 return true;
902 }
903
789#if 0
790 uinteger_t tick = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "tick"));
791 uinteger_t tick_cmpr = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "tick_cmpr"));
792 uinteger_t stick = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "stick"));
793 uinteger_t stick_cmpr = SIMICS_read_control_register(m_version, SIMICS_get_register_number(m_version, "stick_cmpr"));
794 cout << "START PROC " << m_version << hex << " tick = " << tick << " tick_cmpr = " << tick_cmpr << " stick = " << stick << " stick_cmpr = " << stick_cmpr << " cycle = "<< g_eventQueue_ptr->getTime() << dec << endl;;
795#endif
796
797 if (TSO && (request.getType() == CacheRequestType_LD || request.getType() == CacheRequestType_IFETCH)) {
798
799 // See if we can satisfy the load entirely from the store buffer
800 SubBlock subblock(line_address(request.getAddress()), request.getSize());
801 if (m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->trySubBlock(subblock)) {
802 DataBlock dummy;
803 hitCallback(request, dummy, GenericMachineType_NULL, thread); // Call with an 'empty' datablock, since the data is in the store buffer
804 return true;

--- 126 unchanged lines hidden (view full) ---

931void Sequencer::checkCoherence(const Address& addr) {
932#ifdef CHECK_COHERENCE
933 g_system_ptr->checkGlobalCoherenceInvariant(addr);
934#endif
935}
936
937bool Sequencer::getRubyMemoryValue(const Address& addr, char* value,
938 unsigned int size_in_bytes ) {
904 if (TSO && (request.getType() == CacheRequestType_LD || request.getType() == CacheRequestType_IFETCH)) {
905
906 // See if we can satisfy the load entirely from the store buffer
907 SubBlock subblock(line_address(request.getAddress()), request.getSize());
908 if (m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->trySubBlock(subblock)) {
909 DataBlock dummy;
910 hitCallback(request, dummy, GenericMachineType_NULL, thread); // Call with an 'empty' datablock, since the data is in the store buffer
911 return true;

--- 126 unchanged lines hidden (view full) ---

1038void Sequencer::checkCoherence(const Address& addr) {
1039#ifdef CHECK_COHERENCE
1040 g_system_ptr->checkGlobalCoherenceInvariant(addr);
1041#endif
1042}
1043
1044bool Sequencer::getRubyMemoryValue(const Address& addr, char* value,
1045 unsigned int size_in_bytes ) {
939 if(g_SIMICS){
1046 if(g_SIMULATING){
940 for(unsigned int i=0; i < size_in_bytes; i++) {
1047 for(unsigned int i=0; i < size_in_bytes; i++) {
941 value[i] = SIMICS_read_physical_memory( m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version,
942 addr.getAddress() + i, 1 );
1048 std::cerr << __FILE__ << "(" << __LINE__ << "): Not implemented. " << std::endl;
1049 value[i] = 0; // _read_physical_memory( m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version,
1050 // addr.getAddress() + i, 1 );
943 }
944 return false; // Do nothing?
945 } else {
946 bool found = false;
947 const Address lineAddr = line_address(addr);
948 DataBlock data;
949 PhysAddress paddr(addr);
950 DataBlock* dataPtr = &data;

--- 50 unchanged lines hidden (view full) ---

1001 return true;
1002 }
1003}
1004
1005bool Sequencer::setRubyMemoryValue(const Address& addr, char *value,
1006 unsigned int size_in_bytes) {
1007 char test_buffer[64];
1008
1051 }
1052 return false; // Do nothing?
1053 } else {
1054 bool found = false;
1055 const Address lineAddr = line_address(addr);
1056 DataBlock data;
1057 PhysAddress paddr(addr);
1058 DataBlock* dataPtr = &data;

--- 50 unchanged lines hidden (view full) ---

1109 return true;
1110 }
1111}
1112
1113bool Sequencer::setRubyMemoryValue(const Address& addr, char *value,
1114 unsigned int size_in_bytes) {
1115 char test_buffer[64];
1116
1009 if(g_SIMICS){
1117 if(g_SIMULATING){
1010 return false; // Do nothing?
1011 } else {
1012 // idea here is that coherent cache should find the
1013 // latest data, the update it
1014 bool found = false;
1015 const Address lineAddr = line_address(addr);
1016 PhysAddress paddr(addr);
1017 DataBlock data;

--- 65 unchanged lines hidden (view full) ---

1083 WARN_EXPR((int) test_buffer[0]);
1084 ERROR_MSG("setRubyMemoryValue failed to set value.");
1085 }
1086 }
1087
1088 return true;
1089 }
1090}
1118 return false; // Do nothing?
1119 } else {
1120 // idea here is that coherent cache should find the
1121 // latest data, the update it
1122 bool found = false;
1123 const Address lineAddr = line_address(addr);
1124 PhysAddress paddr(addr);
1125 DataBlock data;

--- 65 unchanged lines hidden (view full) ---

1191 WARN_EXPR((int) test_buffer[0]);
1192 ERROR_MSG("setRubyMemoryValue failed to set value.");
1193 }
1194 }
1195
1196 return true;
1197 }
1198}
1199