From 2f30950143cc70bc42a3c8a4111d7cf8198ec881 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 11 May 2009 10:38:43 -0700 Subject: ruby: Import ruby and slicc from GEMS We eventually plan to replace the m5 cache hierarchy with the GEMS hierarchy, but for now we will make both live alongside eachother. --- src/mem/ruby/Decomissioning_note | 10 + src/mem/ruby/FakeSimicsDataTypes.hh | 63 + src/mem/ruby/README.debugging | 104 + src/mem/ruby/buffers/MessageBuffer.cc | 363 ++++ src/mem/ruby/buffers/MessageBuffer.hh | 156 ++ src/mem/ruby/buffers/MessageBufferNode.cc | 48 + src/mem/ruby/buffers/MessageBufferNode.hh | 88 + src/mem/ruby/common/Address.cc | 68 + src/mem/ruby/common/Address.hh | 255 +++ src/mem/ruby/common/BigSet.cc | 249 +++ src/mem/ruby/common/BigSet.hh | 125 ++ src/mem/ruby/common/Consumer.hh | 89 + src/mem/ruby/common/DataBlock.cc | 91 + src/mem/ruby/common/DataBlock.hh | 82 + src/mem/ruby/common/Debug.cc | 369 ++++ src/mem/ruby/common/Debug.def | 17 + src/mem/ruby/common/Debug.hh | 291 +++ src/mem/ruby/common/Driver.cc | 39 + src/mem/ruby/common/Driver.hh | 98 + src/mem/ruby/common/Global.cc | 35 + src/mem/ruby/common/Global.hh | 110 + src/mem/ruby/common/Histogram.cc | 185 ++ src/mem/ruby/common/Histogram.hh | 104 + src/mem/ruby/common/Message.cc | 34 + src/mem/ruby/common/NetDest.cc | 259 +++ src/mem/ruby/common/NetDest.hh | 145 ++ src/mem/ruby/common/OptBigSet.cc | 576 +++++ src/mem/ruby/common/OptBigSet.hh | 202 ++ src/mem/ruby/common/Set.cc | 231 ++ src/mem/ruby/common/Set.hh | 149 ++ src/mem/ruby/common/SubBlock.cc | 81 + src/mem/ruby/common/SubBlock.hh | 105 + src/mem/ruby/config/RubyConfig.cc | 193 ++ src/mem/ruby/config/RubyConfig.hh | 157 ++ src/mem/ruby/config/config.include | 323 +++ src/mem/ruby/config/rubyconfig.defaults | 466 ++++ src/mem/ruby/config/tester.defaults | 60 + src/mem/ruby/eventqueue/EventQueue.cc | 120 + src/mem/ruby/eventqueue/EventQueue.hh | 118 + src/mem/ruby/eventqueue/EventQueueNode.cc | 47 + src/mem/ruby/eventqueue/EventQueueNode.hh | 98 + src/mem/ruby/eventqueue/EventQueue_tester.cc | 89 + src/mem/ruby/init.cc | 307 +++ src/mem/ruby/init.hh | 56 + src/mem/ruby/interfaces/OpalInterface.cc | 446 ++++ src/mem/ruby/interfaces/OpalInterface.hh | 214 ++ src/mem/ruby/interfaces/mf_api.hh | 165 ++ src/mem/ruby/network/Network.hh | 148 ++ .../network/garnet-fixed-pipeline/CreditLink_d.hh | 17 + .../garnet-fixed-pipeline/GarnetNetwork_d.cc | 349 +++ .../garnet-fixed-pipeline/GarnetNetwork_d.hh | 142 ++ .../network/garnet-fixed-pipeline/InputUnit_d.cc | 95 + .../network/garnet-fixed-pipeline/InputUnit_d.hh | 172 ++ .../network/garnet-fixed-pipeline/NetworkHeader.hh | 54 + .../garnet-fixed-pipeline/NetworkInterface_d.cc | 351 +++ .../garnet-fixed-pipeline/NetworkInterface_d.hh | 96 + .../network/garnet-fixed-pipeline/NetworkLink_d.cc | 103 + .../network/garnet-fixed-pipeline/NetworkLink_d.hh | 91 + .../network/garnet-fixed-pipeline/OutVcState_d.cc | 46 + .../network/garnet-fixed-pipeline/OutVcState_d.hh | 86 + .../network/garnet-fixed-pipeline/OutputUnit_d.cc | 111 + .../network/garnet-fixed-pipeline/OutputUnit_d.hh | 95 + .../ruby/network/garnet-fixed-pipeline/Router_d.cc | 167 ++ .../ruby/network/garnet-fixed-pipeline/Router_d.hh | 101 + .../network/garnet-fixed-pipeline/RoutingUnit_d.cc | 93 + .../network/garnet-fixed-pipeline/RoutingUnit_d.hh | 61 + .../network/garnet-fixed-pipeline/SWallocator_d.cc | 230 ++ .../network/garnet-fixed-pipeline/SWallocator_d.hh | 82 + .../ruby/network/garnet-fixed-pipeline/Switch_d.cc | 98 + .../ruby/network/garnet-fixed-pipeline/Switch_d.hh | 73 + .../network/garnet-fixed-pipeline/VCallocator_d.cc | 271 +++ .../network/garnet-fixed-pipeline/VCallocator_d.hh | 86 + .../garnet-fixed-pipeline/VirtualChannel_d.cc | 92 + .../garnet-fixed-pipeline/VirtualChannel_d.hh | 119 + .../network/garnet-fixed-pipeline/flitBuffer_d.cc | 88 + .../network/garnet-fixed-pipeline/flitBuffer_d.hh | 87 + .../ruby/network/garnet-fixed-pipeline/flit_d.cc | 134 ++ .../ruby/network/garnet-fixed-pipeline/flit_d.hh | 166 ++ .../garnet-flexible-pipeline/FlexibleConsumer.hh | 50 + .../garnet-flexible-pipeline/GarnetNetwork.cc | 307 +++ .../garnet-flexible-pipeline/GarnetNetwork.hh | 117 + .../network/garnet-flexible-pipeline/InVcState.cc | 75 + .../network/garnet-flexible-pipeline/InVcState.hh | 61 + .../garnet-flexible-pipeline/NetworkConfig.hh | 123 ++ .../garnet-flexible-pipeline/NetworkInterface.cc | 306 +++ .../garnet-flexible-pipeline/NetworkInterface.hh | 98 + .../garnet-flexible-pipeline/NetworkLink.cc | 147 ++ .../garnet-flexible-pipeline/NetworkLink.hh | 88 + .../network/garnet-flexible-pipeline/OutVcState.cc | 60 + .../network/garnet-flexible-pipeline/OutVcState.hh | 55 + .../network/garnet-flexible-pipeline/Router.cc | 389 ++++ .../network/garnet-flexible-pipeline/Router.hh | 98 + .../network/garnet-flexible-pipeline/VCarbiter.cc | 47 + .../network/garnet-flexible-pipeline/VCarbiter.hh | 56 + .../ruby/network/garnet-flexible-pipeline/flit.cc | 113 + .../ruby/network/garnet-flexible-pipeline/flit.hh | 97 + .../network/garnet-flexible-pipeline/flitBuffer.cc | 104 + .../network/garnet-flexible-pipeline/flitBuffer.hh | 78 + .../garnet-flexible-pipeline/netconfig.defaults | 8 + src/mem/ruby/network/orion/NetworkPower.cc | 430 ++++ src/mem/ruby/network/orion/NetworkPower.hh | 32 + src/mem/ruby/network/orion/SIM_port.hh | 172 ++ src/mem/ruby/network/orion/SIM_power.hh | 384 ++++ src/mem/ruby/network/orion/SIM_power_test.hh | 285 +++ src/mem/ruby/network/orion/parm_technology.hh | 474 ++++ src/mem/ruby/network/orion/power_arbiter.cc | 392 ++++ src/mem/ruby/network/orion/power_arbiter.hh | 90 + src/mem/ruby/network/orion/power_array.cc | 2158 ++++++++++++++++++ src/mem/ruby/network/orion/power_array.hh | 394 ++++ src/mem/ruby/network/orion/power_bus.cc | 215 ++ src/mem/ruby/network/orion/power_bus.hh | 64 + src/mem/ruby/network/orion/power_crossbar.cc | 365 ++++ src/mem/ruby/network/orion/power_crossbar.hh | 81 + src/mem/ruby/network/orion/power_ll.cc | 270 +++ src/mem/ruby/network/orion/power_ll.hh | 53 + src/mem/ruby/network/orion/power_router_init.cc | 260 +++ src/mem/ruby/network/orion/power_router_init.hh | 126 ++ src/mem/ruby/network/orion/power_static.cc | 46 + src/mem/ruby/network/orion/power_static.hh | 39 + src/mem/ruby/network/orion/power_utils.cc | 157 ++ src/mem/ruby/network/orion/power_utils.hh | 35 + .../simple/Network_Files/GarnetFileMaker.py | 45 + ...s-16_ProcsPerChip-16_L2Banks-16_Memories-16.txt | 78 + ...cs-16_ProcsPerChip-16_L2Banks-16_Memories-4.txt | 56 + ...cs-16_ProcsPerChip-16_L2Banks-16_Memories-8.txt | 61 + ...cs-16_ProcsPerChip-1_L2Banks-16_Memories-16.txt | 190 ++ ...cs-16_ProcsPerChip-4_L2Banks-16_Memories-16.txt | 90 + ...ocs-16_ProcsPerChip-4_L2Banks-16_Memories-4.txt | 78 + ...ocs-16_ProcsPerChip-4_L2Banks-32_Memories-4.txt | 123 ++ ...ocs-16_ProcsPerChip-4_L2Banks-4_Memories-16.txt | 78 + ...rocs-16_ProcsPerChip-4_L2Banks-4_Memories-4.txt | 66 + ...Procs-1_ProcsPerChip-1_L2Banks-1_Memories-1.txt | 10 + ...ocs-1_ProcsPerChip-1_L2Banks-256_Memories-1.txt | 780 +++++++ ...rocs-1_ProcsPerChip-1_L2Banks-32_Memories-1.txt | 107 + ...rocs-1_ProcsPerChip-1_L2Banks-64_Memories-1.txt | 204 ++ ...Procs-2_ProcsPerChip-1_L2Banks-2_Memories-2.txt | 15 + ...Procs-2_ProcsPerChip-2_L2Banks-2_Memories-2.txt | 15 + ...s-32_ProcsPerChip-32_L2Banks-32_Memories-16.txt | 148 ++ ...cs-32_ProcsPerChip-32_L2Banks-32_Memories-4.txt | 126 ++ ...Procs-4_ProcsPerChip-1_L2Banks-4_Memories-4.txt | 28 + ...Procs-4_ProcsPerChip-4_L2Banks-4_Memories-4.txt | 24 + ...Procs-7_ProcsPerChip-7_L2Banks-7_Memories-7.txt | 139 ++ ...Procs-8_ProcsPerChip-1_L2Banks-8_Memories-8.txt | 66 + ...Procs-8_ProcsPerChip-4_L2Banks-8_Memories-8.txt | 46 + ...ocs-8_ProcsPerChip-8_L2Banks-256_Memories-8.txt | 412 ++++ ...Procs-8_ProcsPerChip-8_L2Banks-8_Memories-8.txt | 44 + .../simple/Network_Files/NetworkFileMaker.py | 44 + ...ocs-8_ProcsPerChip-8_L2Banks-256_Memories-8.txt | 367 ++++ ...s-16_ProcsPerChip-16_L2Banks-16_Memories-16.txt | 74 + ...cs-16_ProcsPerChip-4_L2Banks-16_Memories-16.txt | 101 + src/mem/ruby/network/simple/PerfectSwitch.cc | 319 +++ src/mem/ruby/network/simple/PerfectSwitch.hh | 118 + src/mem/ruby/network/simple/SimpleNetwork.cc | 257 +++ src/mem/ruby/network/simple/SimpleNetwork.hh | 157 ++ src/mem/ruby/network/simple/Switch.cc | 205 ++ src/mem/ruby/network/simple/Switch.hh | 105 + src/mem/ruby/network/simple/Throttle.cc | 291 +++ src/mem/ruby/network/simple/Throttle.hh | 124 ++ src/mem/ruby/network/simple/Topology.cc | 801 +++++++ src/mem/ruby/network/simple/Topology.hh | 126 ++ src/mem/ruby/profiler/AccessTraceForAddress.cc | 126 ++ src/mem/ruby/profiler/AccessTraceForAddress.hh | 104 + src/mem/ruby/profiler/AddressProfiler.cc | 310 +++ src/mem/ruby/profiler/AddressProfiler.hh | 109 + src/mem/ruby/profiler/CacheProfiler.cc | 151 ++ src/mem/ruby/profiler/CacheProfiler.hh | 100 + src/mem/ruby/profiler/Profiler.cc | 2294 ++++++++++++++++++++ src/mem/ruby/profiler/Profiler.hh | 449 ++++ src/mem/ruby/profiler/StoreTrace.cc | 158 ++ src/mem/ruby/profiler/StoreTrace.hh | 109 + src/mem/ruby/profiler/XactProfiler.cc | 263 +++ src/mem/ruby/profiler/XactProfiler.hh | 125 ++ src/mem/ruby/recorder/CacheRecorder.cc | 75 + src/mem/ruby/recorder/CacheRecorder.hh | 87 + src/mem/ruby/recorder/TraceRecord.cc | 132 ++ src/mem/ruby/recorder/TraceRecord.hh | 101 + src/mem/ruby/recorder/Tracer.cc | 126 ++ src/mem/ruby/recorder/Tracer.hh | 94 + src/mem/ruby/simics/commands.cc | 867 ++++++++ src/mem/ruby/simics/commands.hh | 106 + src/mem/ruby/simics/interface.cc | 935 ++++++++ src/mem/ruby/simics/interface.hh | 152 ++ src/mem/ruby/simics/simics_api_dummy.c | 105 + src/mem/ruby/slicc_interface/AbstractCacheEntry.cc | 45 + src/mem/ruby/slicc_interface/AbstractCacheEntry.hh | 81 + src/mem/ruby/slicc_interface/AbstractChip.cc | 47 + src/mem/ruby/slicc_interface/AbstractChip.hh | 126 ++ src/mem/ruby/slicc_interface/AbstractProtocol.hh | 60 + src/mem/ruby/slicc_interface/Message.hh | 91 + src/mem/ruby/slicc_interface/NetworkMessage.hh | 115 + .../slicc_interface/RubySlicc_ComponentMapping.hh | 425 ++++ .../RubySlicc_Profiler_interface.cc | 161 ++ .../RubySlicc_Profiler_interface.hh | 73 + src/mem/ruby/slicc_interface/RubySlicc_Util.hh | 219 ++ src/mem/ruby/slicc_interface/RubySlicc_includes.hh | 9 + src/mem/ruby/system/AbstractBloomFilter.hh | 72 + src/mem/ruby/system/AbstractMemOrCache.hh | 42 + src/mem/ruby/system/AbstractReplacementPolicy.hh | 62 + src/mem/ruby/system/BlockBloomFilter.cc | 147 ++ src/mem/ruby/system/BlockBloomFilter.hh | 83 + src/mem/ruby/system/BulkBloomFilter.cc | 233 ++ src/mem/ruby/system/BulkBloomFilter.hh | 88 + src/mem/ruby/system/CacheMemory.hh | 559 +++++ src/mem/ruby/system/DirectoryMemory.cc | 175 ++ src/mem/ruby/system/DirectoryMemory.hh | 91 + src/mem/ruby/system/GenericBloomFilter.cc | 154 ++ src/mem/ruby/system/GenericBloomFilter.hh | 96 + src/mem/ruby/system/H3BloomFilter.cc | 210 ++ src/mem/ruby/system/H3BloomFilter.hh | 1259 +++++++++++ src/mem/ruby/system/LRUPolicy.hh | 65 + src/mem/ruby/system/LSB_CountingBloomFilter.cc | 141 ++ src/mem/ruby/system/LSB_CountingBloomFilter.hh | 83 + src/mem/ruby/system/MachineID.hh | 89 + src/mem/ruby/system/MemoryControl.cc | 632 ++++++ src/mem/ruby/system/MemoryControl.hh | 176 ++ src/mem/ruby/system/MemoryNode.cc | 37 + src/mem/ruby/system/MemoryNode.hh | 95 + src/mem/ruby/system/MultiBitSelBloomFilter.cc | 191 ++ src/mem/ruby/system/MultiBitSelBloomFilter.hh | 98 + src/mem/ruby/system/MultiGrainBloomFilter.cc | 172 ++ src/mem/ruby/system/MultiGrainBloomFilter.hh | 89 + src/mem/ruby/system/NodeID.hh | 50 + src/mem/ruby/system/NodePersistentTable.cc | 194 ++ src/mem/ruby/system/NodePersistentTable.hh | 99 + src/mem/ruby/system/NonCountingBloomFilter.cc | 145 ++ src/mem/ruby/system/NonCountingBloomFilter.hh | 89 + src/mem/ruby/system/PerfectCacheMemory.hh | 239 ++ src/mem/ruby/system/PersistentArbiter.cc | 165 ++ src/mem/ruby/system/PersistentArbiter.hh | 108 + src/mem/ruby/system/PersistentTable.cc | 195 ++ src/mem/ruby/system/PersistentTable.hh | 99 + src/mem/ruby/system/PseudoLRUPolicy.hh | 110 + src/mem/ruby/system/Sequencer.cc | 1161 ++++++++++ src/mem/ruby/system/Sequencer.hh | 170 ++ src/mem/ruby/system/StoreBuffer.cc | 300 +++ src/mem/ruby/system/StoreBuffer.hh | 120 + src/mem/ruby/system/StoreCache.cc | 178 ++ src/mem/ruby/system/StoreCache.hh | 85 + src/mem/ruby/system/System.cc | 269 +++ src/mem/ruby/system/System.hh | 137 ++ src/mem/ruby/system/TBETable.hh | 165 ++ src/mem/ruby/system/TimerTable.cc | 129 ++ src/mem/ruby/system/TimerTable.hh | 98 + src/mem/ruby/tester/BarrierGenerator.cc | 333 +++ src/mem/ruby/tester/BarrierGenerator.hh | 138 ++ src/mem/ruby/tester/Check.cc | 251 +++ src/mem/ruby/tester/Check.hh | 107 + src/mem/ruby/tester/CheckTable.cc | 128 ++ src/mem/ruby/tester/CheckTable.hh | 93 + src/mem/ruby/tester/DetermGETXGenerator.cc | 151 ++ src/mem/ruby/tester/DetermGETXGenerator.hh | 104 + src/mem/ruby/tester/DetermInvGenerator.cc | 202 ++ src/mem/ruby/tester/DetermInvGenerator.hh | 109 + src/mem/ruby/tester/DetermSeriesGETSGenerator.cc | 149 ++ src/mem/ruby/tester/DetermSeriesGETSGenerator.hh | 106 + src/mem/ruby/tester/DeterministicDriver.cc | 282 +++ src/mem/ruby/tester/DeterministicDriver.hh | 125 ++ src/mem/ruby/tester/Instruction.cc | 51 + src/mem/ruby/tester/Instruction.hh | 57 + src/mem/ruby/tester/RaceyDriver.cc | 139 ++ src/mem/ruby/tester/RaceyDriver.hh | 112 + src/mem/ruby/tester/RequestGenerator.cc | 196 ++ src/mem/ruby/tester/RequestGenerator.hh | 102 + src/mem/ruby/tester/SpecifiedGenerator.cc | 48 + src/mem/ruby/tester/SpecifiedGenerator.hh | 69 + src/mem/ruby/tester/SyntheticDriver.cc | 296 +++ src/mem/ruby/tester/SyntheticDriver.hh | 118 + src/mem/ruby/tester/Tester.cc | 116 + src/mem/ruby/tester/Tester.hh | 93 + src/mem/ruby/tester/XactAbortRequestGenerator.cc | 403 ++++ src/mem/ruby/tester/XactAbortRequestGenerator.hh | 122 ++ src/mem/ruby/tester/XactRequestGenerator.cc | 637 ++++++ src/mem/ruby/tester/XactRequestGenerator.hh | 134 ++ src/mem/ruby/tester/main.cc | 51 + src/mem/ruby/tester/main.hh | 42 + src/mem/ruby/tester/test_framework.cc | 431 ++++ src/mem/ruby/tester/test_framework.hh | 46 + 277 files changed, 50216 insertions(+) create mode 100644 src/mem/ruby/Decomissioning_note create mode 100644 src/mem/ruby/FakeSimicsDataTypes.hh create mode 100644 src/mem/ruby/README.debugging create mode 100644 src/mem/ruby/buffers/MessageBuffer.cc create mode 100644 src/mem/ruby/buffers/MessageBuffer.hh create mode 100644 src/mem/ruby/buffers/MessageBufferNode.cc create mode 100644 src/mem/ruby/buffers/MessageBufferNode.hh create mode 100644 src/mem/ruby/common/Address.cc create mode 100644 src/mem/ruby/common/Address.hh create mode 100644 src/mem/ruby/common/BigSet.cc create mode 100644 src/mem/ruby/common/BigSet.hh create mode 100644 src/mem/ruby/common/Consumer.hh create mode 100644 src/mem/ruby/common/DataBlock.cc create mode 100644 src/mem/ruby/common/DataBlock.hh create mode 100644 src/mem/ruby/common/Debug.cc create mode 100644 src/mem/ruby/common/Debug.def create mode 100644 src/mem/ruby/common/Debug.hh create mode 100644 src/mem/ruby/common/Driver.cc create mode 100644 src/mem/ruby/common/Driver.hh create mode 100644 src/mem/ruby/common/Global.cc create mode 100644 src/mem/ruby/common/Global.hh create mode 100644 src/mem/ruby/common/Histogram.cc create mode 100644 src/mem/ruby/common/Histogram.hh create mode 100644 src/mem/ruby/common/Message.cc create mode 100644 src/mem/ruby/common/NetDest.cc create mode 100644 src/mem/ruby/common/NetDest.hh create mode 100644 src/mem/ruby/common/OptBigSet.cc create mode 100644 src/mem/ruby/common/OptBigSet.hh create mode 100644 src/mem/ruby/common/Set.cc create mode 100644 src/mem/ruby/common/Set.hh create mode 100644 src/mem/ruby/common/SubBlock.cc create mode 100644 src/mem/ruby/common/SubBlock.hh create mode 100644 src/mem/ruby/config/RubyConfig.cc create mode 100644 src/mem/ruby/config/RubyConfig.hh create mode 100644 src/mem/ruby/config/config.include create mode 100644 src/mem/ruby/config/rubyconfig.defaults create mode 100644 src/mem/ruby/config/tester.defaults create mode 100644 src/mem/ruby/eventqueue/EventQueue.cc create mode 100644 src/mem/ruby/eventqueue/EventQueue.hh create mode 100644 src/mem/ruby/eventqueue/EventQueueNode.cc create mode 100644 src/mem/ruby/eventqueue/EventQueueNode.hh create mode 100644 src/mem/ruby/eventqueue/EventQueue_tester.cc create mode 100644 src/mem/ruby/init.cc create mode 100644 src/mem/ruby/init.hh create mode 100644 src/mem/ruby/interfaces/OpalInterface.cc create mode 100644 src/mem/ruby/interfaces/OpalInterface.hh create mode 100644 src/mem/ruby/interfaces/mf_api.hh create mode 100644 src/mem/ruby/network/Network.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/CreditLink_d.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.cc create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.cc create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/NetworkHeader.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.cc create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.cc create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/OutVcState_d.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.cc create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/OutputUnit_d.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/Router_d.cc create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/Router_d.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/RoutingUnit_d.cc create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/RoutingUnit_d.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.cc create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/SWallocator_d.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/Switch_d.cc create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/Switch_d.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.cc create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/VCallocator_d.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/VirtualChannel_d.cc create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/VirtualChannel_d.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/flitBuffer_d.cc create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/flitBuffer_d.hh create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/flit_d.cc create mode 100644 src/mem/ruby/network/garnet-fixed-pipeline/flit_d.hh create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/FlexibleConsumer.hh create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.cc create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/InVcState.cc create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/InVcState.hh create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.cc create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.hh create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/NetworkLink.cc create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/NetworkLink.hh create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/OutVcState.cc create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/OutVcState.hh create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/Router.cc create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/Router.hh create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/VCarbiter.cc create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/VCarbiter.hh create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/flit.cc create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/flit.hh create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/flitBuffer.cc create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/flitBuffer.hh create mode 100644 src/mem/ruby/network/garnet-flexible-pipeline/netconfig.defaults create mode 100644 src/mem/ruby/network/orion/NetworkPower.cc create mode 100644 src/mem/ruby/network/orion/NetworkPower.hh create mode 100644 src/mem/ruby/network/orion/SIM_port.hh create mode 100644 src/mem/ruby/network/orion/SIM_power.hh create mode 100644 src/mem/ruby/network/orion/SIM_power_test.hh create mode 100644 src/mem/ruby/network/orion/parm_technology.hh create mode 100644 src/mem/ruby/network/orion/power_arbiter.cc create mode 100644 src/mem/ruby/network/orion/power_arbiter.hh create mode 100644 src/mem/ruby/network/orion/power_array.cc create mode 100644 src/mem/ruby/network/orion/power_array.hh create mode 100644 src/mem/ruby/network/orion/power_bus.cc create mode 100644 src/mem/ruby/network/orion/power_bus.hh create mode 100644 src/mem/ruby/network/orion/power_crossbar.cc create mode 100644 src/mem/ruby/network/orion/power_crossbar.hh create mode 100644 src/mem/ruby/network/orion/power_ll.cc create mode 100644 src/mem/ruby/network/orion/power_ll.hh create mode 100644 src/mem/ruby/network/orion/power_router_init.cc create mode 100644 src/mem/ruby/network/orion/power_router_init.hh create mode 100644 src/mem/ruby/network/orion/power_static.cc create mode 100644 src/mem/ruby/network/orion/power_static.hh create mode 100644 src/mem/ruby/network/orion/power_utils.cc create mode 100644 src/mem/ruby/network/orion/power_utils.hh create mode 100644 src/mem/ruby/network/simple/Network_Files/GarnetFileMaker.py create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-16_ProcsPerChip-16_L2Banks-16_Memories-16.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-16_ProcsPerChip-16_L2Banks-16_Memories-4.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-16_ProcsPerChip-16_L2Banks-16_Memories-8.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-16_ProcsPerChip-1_L2Banks-16_Memories-16.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-16_ProcsPerChip-4_L2Banks-16_Memories-16.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-16_ProcsPerChip-4_L2Banks-16_Memories-4.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-16_ProcsPerChip-4_L2Banks-32_Memories-4.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-16_ProcsPerChip-4_L2Banks-4_Memories-16.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-16_ProcsPerChip-4_L2Banks-4_Memories-4.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-1_ProcsPerChip-1_L2Banks-1_Memories-1.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-1_ProcsPerChip-1_L2Banks-256_Memories-1.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-1_ProcsPerChip-1_L2Banks-32_Memories-1.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-1_ProcsPerChip-1_L2Banks-64_Memories-1.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-2_ProcsPerChip-1_L2Banks-2_Memories-2.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-2_ProcsPerChip-2_L2Banks-2_Memories-2.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-32_ProcsPerChip-32_L2Banks-32_Memories-16.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-32_ProcsPerChip-32_L2Banks-32_Memories-4.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-4_ProcsPerChip-1_L2Banks-4_Memories-4.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-4_ProcsPerChip-4_L2Banks-4_Memories-4.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-7_ProcsPerChip-7_L2Banks-7_Memories-7.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-8_ProcsPerChip-1_L2Banks-8_Memories-8.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-8_ProcsPerChip-4_L2Banks-8_Memories-8.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-8_ProcsPerChip-8_L2Banks-256_Memories-8.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NUCA_Procs-8_ProcsPerChip-8_L2Banks-8_Memories-8.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/NetworkFileMaker.py create mode 100644 src/mem/ruby/network/simple/Network_Files/TLC_Procs-8_ProcsPerChip-8_L2Banks-256_Memories-8.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/TOKEN_CMP_Procs-16_ProcsPerChip-16_L2Banks-16_Memories-16.txt create mode 100644 src/mem/ruby/network/simple/Network_Files/TOKEN_CMP_Procs-16_ProcsPerChip-4_L2Banks-16_Memories-16.txt create mode 100644 src/mem/ruby/network/simple/PerfectSwitch.cc create mode 100644 src/mem/ruby/network/simple/PerfectSwitch.hh create mode 100644 src/mem/ruby/network/simple/SimpleNetwork.cc create mode 100644 src/mem/ruby/network/simple/SimpleNetwork.hh create mode 100644 src/mem/ruby/network/simple/Switch.cc create mode 100644 src/mem/ruby/network/simple/Switch.hh create mode 100644 src/mem/ruby/network/simple/Throttle.cc create mode 100644 src/mem/ruby/network/simple/Throttle.hh create mode 100644 src/mem/ruby/network/simple/Topology.cc create mode 100644 src/mem/ruby/network/simple/Topology.hh create mode 100644 src/mem/ruby/profiler/AccessTraceForAddress.cc create mode 100644 src/mem/ruby/profiler/AccessTraceForAddress.hh create mode 100644 src/mem/ruby/profiler/AddressProfiler.cc create mode 100644 src/mem/ruby/profiler/AddressProfiler.hh create mode 100644 src/mem/ruby/profiler/CacheProfiler.cc create mode 100644 src/mem/ruby/profiler/CacheProfiler.hh create mode 100644 src/mem/ruby/profiler/Profiler.cc create mode 100644 src/mem/ruby/profiler/Profiler.hh create mode 100644 src/mem/ruby/profiler/StoreTrace.cc create mode 100644 src/mem/ruby/profiler/StoreTrace.hh create mode 100644 src/mem/ruby/profiler/XactProfiler.cc create mode 100644 src/mem/ruby/profiler/XactProfiler.hh create mode 100644 src/mem/ruby/recorder/CacheRecorder.cc create mode 100644 src/mem/ruby/recorder/CacheRecorder.hh create mode 100644 src/mem/ruby/recorder/TraceRecord.cc create mode 100644 src/mem/ruby/recorder/TraceRecord.hh create mode 100644 src/mem/ruby/recorder/Tracer.cc create mode 100644 src/mem/ruby/recorder/Tracer.hh create mode 100644 src/mem/ruby/simics/commands.cc create mode 100644 src/mem/ruby/simics/commands.hh create mode 100644 src/mem/ruby/simics/interface.cc create mode 100644 src/mem/ruby/simics/interface.hh create mode 100644 src/mem/ruby/simics/simics_api_dummy.c create mode 100644 src/mem/ruby/slicc_interface/AbstractCacheEntry.cc create mode 100644 src/mem/ruby/slicc_interface/AbstractCacheEntry.hh create mode 100644 src/mem/ruby/slicc_interface/AbstractChip.cc create mode 100644 src/mem/ruby/slicc_interface/AbstractChip.hh create mode 100644 src/mem/ruby/slicc_interface/AbstractProtocol.hh create mode 100644 src/mem/ruby/slicc_interface/Message.hh create mode 100644 src/mem/ruby/slicc_interface/NetworkMessage.hh create mode 100644 src/mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh create mode 100644 src/mem/ruby/slicc_interface/RubySlicc_Profiler_interface.cc create mode 100644 src/mem/ruby/slicc_interface/RubySlicc_Profiler_interface.hh create mode 100644 src/mem/ruby/slicc_interface/RubySlicc_Util.hh create mode 100644 src/mem/ruby/slicc_interface/RubySlicc_includes.hh create mode 100644 src/mem/ruby/system/AbstractBloomFilter.hh create mode 100644 src/mem/ruby/system/AbstractMemOrCache.hh create mode 100644 src/mem/ruby/system/AbstractReplacementPolicy.hh create mode 100644 src/mem/ruby/system/BlockBloomFilter.cc create mode 100644 src/mem/ruby/system/BlockBloomFilter.hh create mode 100644 src/mem/ruby/system/BulkBloomFilter.cc create mode 100644 src/mem/ruby/system/BulkBloomFilter.hh create mode 100644 src/mem/ruby/system/CacheMemory.hh create mode 100644 src/mem/ruby/system/DirectoryMemory.cc create mode 100644 src/mem/ruby/system/DirectoryMemory.hh create mode 100644 src/mem/ruby/system/GenericBloomFilter.cc create mode 100644 src/mem/ruby/system/GenericBloomFilter.hh create mode 100644 src/mem/ruby/system/H3BloomFilter.cc create mode 100644 src/mem/ruby/system/H3BloomFilter.hh create mode 100644 src/mem/ruby/system/LRUPolicy.hh create mode 100644 src/mem/ruby/system/LSB_CountingBloomFilter.cc create mode 100644 src/mem/ruby/system/LSB_CountingBloomFilter.hh create mode 100644 src/mem/ruby/system/MachineID.hh create mode 100644 src/mem/ruby/system/MemoryControl.cc create mode 100644 src/mem/ruby/system/MemoryControl.hh create mode 100644 src/mem/ruby/system/MemoryNode.cc create mode 100644 src/mem/ruby/system/MemoryNode.hh create mode 100644 src/mem/ruby/system/MultiBitSelBloomFilter.cc create mode 100644 src/mem/ruby/system/MultiBitSelBloomFilter.hh create mode 100644 src/mem/ruby/system/MultiGrainBloomFilter.cc create mode 100644 src/mem/ruby/system/MultiGrainBloomFilter.hh create mode 100644 src/mem/ruby/system/NodeID.hh create mode 100644 src/mem/ruby/system/NodePersistentTable.cc create mode 100644 src/mem/ruby/system/NodePersistentTable.hh create mode 100644 src/mem/ruby/system/NonCountingBloomFilter.cc create mode 100644 src/mem/ruby/system/NonCountingBloomFilter.hh create mode 100644 src/mem/ruby/system/PerfectCacheMemory.hh create mode 100644 src/mem/ruby/system/PersistentArbiter.cc create mode 100644 src/mem/ruby/system/PersistentArbiter.hh create mode 100644 src/mem/ruby/system/PersistentTable.cc create mode 100644 src/mem/ruby/system/PersistentTable.hh create mode 100644 src/mem/ruby/system/PseudoLRUPolicy.hh create mode 100644 src/mem/ruby/system/Sequencer.cc create mode 100644 src/mem/ruby/system/Sequencer.hh create mode 100644 src/mem/ruby/system/StoreBuffer.cc create mode 100644 src/mem/ruby/system/StoreBuffer.hh create mode 100644 src/mem/ruby/system/StoreCache.cc create mode 100644 src/mem/ruby/system/StoreCache.hh create mode 100644 src/mem/ruby/system/System.cc create mode 100644 src/mem/ruby/system/System.hh create mode 100644 src/mem/ruby/system/TBETable.hh create mode 100644 src/mem/ruby/system/TimerTable.cc create mode 100644 src/mem/ruby/system/TimerTable.hh create mode 100644 src/mem/ruby/tester/BarrierGenerator.cc create mode 100644 src/mem/ruby/tester/BarrierGenerator.hh create mode 100644 src/mem/ruby/tester/Check.cc create mode 100644 src/mem/ruby/tester/Check.hh create mode 100644 src/mem/ruby/tester/CheckTable.cc create mode 100644 src/mem/ruby/tester/CheckTable.hh create mode 100644 src/mem/ruby/tester/DetermGETXGenerator.cc create mode 100644 src/mem/ruby/tester/DetermGETXGenerator.hh create mode 100644 src/mem/ruby/tester/DetermInvGenerator.cc create mode 100644 src/mem/ruby/tester/DetermInvGenerator.hh create mode 100644 src/mem/ruby/tester/DetermSeriesGETSGenerator.cc create mode 100644 src/mem/ruby/tester/DetermSeriesGETSGenerator.hh create mode 100644 src/mem/ruby/tester/DeterministicDriver.cc create mode 100644 src/mem/ruby/tester/DeterministicDriver.hh create mode 100644 src/mem/ruby/tester/Instruction.cc create mode 100644 src/mem/ruby/tester/Instruction.hh create mode 100644 src/mem/ruby/tester/RaceyDriver.cc create mode 100644 src/mem/ruby/tester/RaceyDriver.hh create mode 100644 src/mem/ruby/tester/RequestGenerator.cc create mode 100644 src/mem/ruby/tester/RequestGenerator.hh create mode 100644 src/mem/ruby/tester/SpecifiedGenerator.cc create mode 100644 src/mem/ruby/tester/SpecifiedGenerator.hh create mode 100644 src/mem/ruby/tester/SyntheticDriver.cc create mode 100644 src/mem/ruby/tester/SyntheticDriver.hh create mode 100644 src/mem/ruby/tester/Tester.cc create mode 100644 src/mem/ruby/tester/Tester.hh create mode 100644 src/mem/ruby/tester/XactAbortRequestGenerator.cc create mode 100644 src/mem/ruby/tester/XactAbortRequestGenerator.hh create mode 100644 src/mem/ruby/tester/XactRequestGenerator.cc create mode 100644 src/mem/ruby/tester/XactRequestGenerator.hh create mode 100644 src/mem/ruby/tester/main.cc create mode 100644 src/mem/ruby/tester/main.hh create mode 100644 src/mem/ruby/tester/test_framework.cc create mode 100644 src/mem/ruby/tester/test_framework.hh (limited to 'src/mem/ruby') diff --git a/src/mem/ruby/Decomissioning_note b/src/mem/ruby/Decomissioning_note new file mode 100644 index 000000000..9b083d196 --- /dev/null +++ b/src/mem/ruby/Decomissioning_note @@ -0,0 +1,10 @@ + +1. While decomissioning log_tm + + a. I left lots of transaction related stuff ( Xact.... ) in commands.C + Made the minimal changes to compile it properly + + +make[1]: *** No rule to make target `amd64-linux/generated/MI_example/obj/PartialAddressFilter.o', needed by `amd64-linux/generated/MI_example/bin/libruby.so + + diff --git a/src/mem/ruby/FakeSimicsDataTypes.hh b/src/mem/ruby/FakeSimicsDataTypes.hh new file mode 100644 index 000000000..b6fcda95c --- /dev/null +++ b/src/mem/ruby/FakeSimicsDataTypes.hh @@ -0,0 +1,63 @@ +#ifndef FAKE_SIMICS_DATA_TYPES_H +#define FAKE_SIMICS_DATA_TYPES_H + +typedef struct attr_value attr_value_t; + +typedef enum { + Sim_Val_Invalid = 0, + Sim_Val_String = 1, + Sim_Val_Integer = 2, + Sim_Val_Floating = 3, + Sim_Val_List = 4, + Sim_Val_Data = 5, + Sim_Val_Nil = 6, + Sim_Val_Object = 7 +} attr_kind_t; + +typedef struct attr_list attr_list_t; + +struct attr_list { + int size; + struct attr_value *vector; +}; + +struct attr_value { + attr_kind_t kind; + union { + const char *string; /* Sim_Val_String */ + unsigned long long integer; /* Sim_Val_Integer */ + double floating; /* Sim_Val_Floating */ + void *object; /* Sim_Val_Object */ + attr_list_t list; /* Sim_Val_List */ + } u; +}; + +typedef enum { +Sim_Set_Ok, +Sim_Set_Need_Integer, +Sim_Set_Need_Floating, +Sim_Set_Need_String, +Sim_Set_Need_List, +Sim_Set_Need_Data, +Sim_Set_Need_Object, +Sim_Set_Object_Not_Found, +Sim_Set_Interface_Not_Found, +Sim_Set_Illegal_Value, +Sim_Set_Illegal_Type, +Sim_Set_Illegal_Index, +Sim_Set_Attribute_Not_Found, +Sim_Set_Not_Writable, +Sim_Set_Ignored +} set_error_t; + + +typedef attr_value_t (*get_attr_t)(void *ptr, + void *obj, + attr_value_t *idx); + +typedef set_error_t (*set_attr_t)(void *ptr, + void *obj, + attr_value_t *val, + attr_value_t *idx); + +#endif // #ifndef FAKE_SIMICS_DATA_TYPES_H diff --git a/src/mem/ruby/README.debugging b/src/mem/ruby/README.debugging new file mode 100644 index 000000000..48a5e62f0 --- /dev/null +++ b/src/mem/ruby/README.debugging @@ -0,0 +1,104 @@ +# ------ Debugging the Ruby Tester ------ + +You can compile Ruby with debugging turned on. + +cd ruby +[vim or emacs] Makefile + +Change OPT_FLAGS to "-g -O0" (the first OPT_FLAGS line). Make +sure all the other OPT_FLAGS lines are commented out. + +Change DEBUG_FLAGS to "-DRUBY_DEBUG=true". (Just uncomment the +first DEBUG_FLAGS line, and comment out the second DEBUG_FLAGS +line.) + +You can choose which component or components to debug, and the +level of verbosity. For example, + +"x86-linux/generated/MOSI_SMP_bcast/bin/tester.exec -l 100000 -v med -c n" + +gives you debugging information about the network component at +the medium verbosity level. -v selects the verbosity, which may +be low, med, high, or none. -c selects the component or +components. + +"x86-linux/generated/MOSI_SMP_bcast/bin/tester.exec -l 100000 -v med -c nSt" + +debugs the network, the sequencer, and the tester. + +For a list of the components you can debug, just run the tester with +no arguments, and it will display a list of valid components. The +components are defined in ruby/common/Debug.def. + +The protocol debug trace is especially useful for debugging cache coherence protocols. This must be enabled at compile-time by ensuring that PROTOCOL_DEBUG_TRACE is set to true for rubyconfig.defaults (if running in Simics) or tester.defaults. You must specify the time to start tracing. The following starts the protocol trace immediately (at time 1) + +"x86-linux/generated/MOSI_SMP_bcast/bin/tester.exec -l 100000 -s 1" + +Also, if something seems to be wrong and you're not sure where to +start looking, it may help to run the tester for a longer time, +e.g. + +"x86-linux/generated/MOSI_SMP_bcast/bin/tester.exec -l 500000" + +This may help because some problems eventually show up as +deadlock, but the tester has to run for a long time before a +deadlock is detected. + +Once your simulator has succeeded on the tester for a certain +number of cycles, say 1000000, you may want to set the +RANDOMIZATION variable in ruby/config/tester.defaults to "true" +for more thorough testing. However, RANDOMIZATION may not work in +all situations because it overrides some of the ordering in the +network and may break your simulator in ways you don't like. For +example, messages are added to MessageBuffers with random +latency. + +By default the tester driver is a generator that issues random store +and load requests. This driver does a good job of stressing the +cache coherency protocol by issuing racy store requests from multiple +processors to a cache line then checks the stores with a single load. + +Other tester drivers are available. By setting the g_SYNTHETIC_DRIVER +to true in ruby/config/tester.defaults, you enable a tester that generates +racy lock requests for a number of locks indicated by g_synthetic_locks. + +Another tester driver is a series of non-racy deterministic testers. By +setting the g_DETERMINISTIC_DRIVER in ruby/config/tester.defaults to true, +you enable the deterministic tester. The deterministic tester can do +different types of deterministic tests as specified by g_SpecifiedGenerator +string. The deterministic tester works best when RANDOMIZATION is set to +false. To easily track the queues being used with the deterministic tester, +use the following debug flags "-v low -c nq". + +# ------ Debugging Ruby in Simics ------ + +When you're running Simics, the debugging components and +verbosity levels are the same. However, the way you communicate +with Ruby changes. + +See the README.quickstart for information on compiling the Ruby +module and loading it into Simics. Once you've got Simics +running, with the Ruby module loaded, you can set up Ruby +debugging. + +To set the debugging verbosity level, run: + +simics> ruby0.debug-verb med + +To set the debugging components, run: (see common/Debug.def for complete list + of component shortcuts) + +simics> ruby0.debug-filter n + +(NOTE: sometimes simics will interpret a single letter as a +command; e.g. expanding "p" into "print". If simics gives you an +error when setting the debug filter, try setting it like so: +simics> ruby0.debug-filter "n") + +This gives the same kind of debugging information as running the +tester with "-v med -c n". + +You can also send the debugging output to a file (may be a good +idea, since there's a lot of it). To do this, run: + +simics> ruby0.debug-output-file diff --git a/src/mem/ruby/buffers/MessageBuffer.cc b/src/mem/ruby/buffers/MessageBuffer.cc new file mode 100644 index 000000000..ff2547f0f --- /dev/null +++ b/src/mem/ruby/buffers/MessageBuffer.cc @@ -0,0 +1,363 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "MessageBuffer.hh" +#include "RubyConfig.hh" + +MessageBuffer::MessageBuffer() +{ + m_msg_counter = 0; + m_consumer_ptr = NULL; + m_ordering_set = false; + m_strict_fifo = true; + m_size = 0; + m_max_size = -1; + m_last_arrival_time = 0; + m_randomization = true; + m_size_last_time_size_checked = 0; + m_time_last_time_size_checked = 0; + m_time_last_time_enqueue = 0; + m_time_last_time_pop = 0; + m_size_at_cycle_start = 0; + m_msgs_this_cycle = 0; + m_not_avail_count = 0; + m_priority_rank = 0; +} + +MessageBuffer::MessageBuffer(const Chip* chip_ptr) // The chip_ptr is ignored, but could be used for extra debugging +{ + m_msg_counter = 0; + m_consumer_ptr = NULL; + m_ordering_set = false; + m_strict_fifo = true; + m_size = 0; + m_max_size = -1; + m_last_arrival_time = 0; + m_randomization = true; + m_size_last_time_size_checked = 0; + m_time_last_time_size_checked = 0; + m_time_last_time_enqueue = 0; + m_time_last_time_pop = 0; + m_size_at_cycle_start = 0; + m_msgs_this_cycle = 0; + m_not_avail_count = 0; + m_priority_rank = 0; +} + +int MessageBuffer::getSize() +{ + if(m_time_last_time_size_checked == g_eventQueue_ptr->getTime()){ + return m_size_last_time_size_checked; + } else { + m_time_last_time_size_checked = g_eventQueue_ptr->getTime(); + m_size_last_time_size_checked = m_size; + return m_size; + } +} + +bool MessageBuffer::areNSlotsAvailable(int n) +{ + + // fast path when message buffers have infinite size + if(m_max_size == -1) { + return true; + } + + // determine my correct size for the current cycle + // pop operations shouldn't effect the network's visible size until next cycle, + // but enqueue operations effect the visible size immediately + int current_size = max(m_size_at_cycle_start, m_size); + if (m_time_last_time_pop < g_eventQueue_ptr->getTime()) { // no pops this cycle - m_size is correct + current_size = m_size; + } else { + if (m_time_last_time_enqueue < g_eventQueue_ptr->getTime()) { // no enqueues this cycle - m_size_at_cycle_start is correct + current_size = m_size_at_cycle_start; + } else { // both pops and enqueues occured this cycle - add new enqueued msgs to m_size_at_cycle_start + current_size = m_size_at_cycle_start+m_msgs_this_cycle; + } + } + + // now compare the new size with our max size + if(current_size+n <= m_max_size){ + return true; + } else { + DEBUG_MSG(QUEUE_COMP,MedPrio,n); + DEBUG_MSG(QUEUE_COMP,MedPrio,current_size); + DEBUG_MSG(QUEUE_COMP,MedPrio,m_size); + DEBUG_MSG(QUEUE_COMP,MedPrio,m_max_size); + m_not_avail_count++; + return false; + } +} + +const MsgPtr MessageBuffer::getMsgPtrCopy() const +{ + assert(isReady()); + + MsgPtr temp_msg; + temp_msg = *(m_prio_heap.peekMin().m_msgptr.ref()); + assert(temp_msg.ref() != NULL); + return temp_msg; +} + +const Message* MessageBuffer::peekAtHeadOfQueue() const +{ + const Message* msg_ptr; + DEBUG_NEWLINE(QUEUE_COMP,MedPrio); + + DEBUG_MSG(QUEUE_COMP,MedPrio,"Peeking at head of queue " + m_name + " time: " + + int_to_string(g_eventQueue_ptr->getTime()) + "."); + assert(isReady()); + + msg_ptr = m_prio_heap.peekMin().m_msgptr.ref(); + assert(msg_ptr != NULL); + + DEBUG_EXPR(QUEUE_COMP,MedPrio,*msg_ptr); + DEBUG_NEWLINE(QUEUE_COMP,MedPrio); + return msg_ptr; +} + +// FIXME - move me somewhere else +int random_time() +{ + int time = 1; + time += random() & 0x3; // [0...3] + if ((random() & 0x7) == 0) { // 1 in 8 chance + time += 100 + (random() % 0xf); // 100 + [1...15] + } + return time; +} + +void MessageBuffer::enqueue(const MsgPtr& message, Time delta) +{ + DEBUG_NEWLINE(QUEUE_COMP,HighPrio); + DEBUG_MSG(QUEUE_COMP,HighPrio,"enqueue " + m_name + " time: " + + int_to_string(g_eventQueue_ptr->getTime()) + "."); + DEBUG_EXPR(QUEUE_COMP,MedPrio,message); + DEBUG_NEWLINE(QUEUE_COMP,HighPrio); + + m_msg_counter++; + m_size++; + + // record current time incase we have a pop that also adjusts my size + if (m_time_last_time_enqueue < g_eventQueue_ptr->getTime()) { + m_msgs_this_cycle = 0; // first msg this cycle + m_time_last_time_enqueue = g_eventQueue_ptr->getTime(); + } + m_msgs_this_cycle++; + + // ASSERT(m_max_size == -1 || m_size <= m_max_size + 1); + // the plus one is a kluge because of a SLICC issue + + if (!m_ordering_set) { + WARN_EXPR(*this); + WARN_EXPR(m_name); + ERROR_MSG("Ordering property of this queue has not been set"); + } + + // Calculate the arrival time of the message, that is, the first + // cycle the message can be dequeued. + assert(delta>0); + Time current_time = g_eventQueue_ptr->getTime(); + Time arrival_time = 0; + if (!RANDOMIZATION || (m_randomization == false)) { + // No randomization + arrival_time = current_time + delta; + + } else { + // Randomization - ignore delta + if (m_strict_fifo) { + if (m_last_arrival_time < current_time) { + m_last_arrival_time = current_time; + } + arrival_time = m_last_arrival_time + random_time(); + } else { + arrival_time = current_time + random_time(); + } + } + + // Check the arrival time + assert(arrival_time > current_time); + if (m_strict_fifo) { + if (arrival_time >= m_last_arrival_time) { + + } else { + WARN_EXPR(*this); + WARN_EXPR(m_name); + WARN_EXPR(current_time); + WARN_EXPR(delta); + WARN_EXPR(arrival_time); + WARN_EXPR(m_last_arrival_time); + ERROR_MSG("FIFO ordering violated"); + } + } + m_last_arrival_time = arrival_time; + + // compute the delay cycles and set enqueue time + Message* msg_ptr = NULL; + msg_ptr = message.mod_ref(); + assert(msg_ptr != NULL); + assert(g_eventQueue_ptr->getTime() >= msg_ptr->getLastEnqueueTime()); // ensure we aren't dequeued early + msg_ptr->setDelayedCycles((g_eventQueue_ptr->getTime() - msg_ptr->getLastEnqueueTime())+msg_ptr->getDelayedCycles()); + msg_ptr->setLastEnqueueTime(arrival_time); + + // Insert the message into the priority heap + MessageBufferNode thisNode(arrival_time, m_msg_counter, message); + m_prio_heap.insert(thisNode); + + DEBUG_NEWLINE(QUEUE_COMP,HighPrio); + DEBUG_MSG(QUEUE_COMP,HighPrio,"enqueue " + m_name + + " with arrival_time " + int_to_string(arrival_time) + + " cur_time: " + int_to_string(g_eventQueue_ptr->getTime()) + "."); + DEBUG_EXPR(QUEUE_COMP,MedPrio,message); + DEBUG_NEWLINE(QUEUE_COMP,HighPrio); + + // Schedule the wakeup + if (m_consumer_ptr != NULL) { + g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, arrival_time); + } else { + WARN_EXPR(*this); + WARN_EXPR(m_name); + ERROR_MSG("No consumer"); + } +} + +int MessageBuffer::dequeue_getDelayCycles(MsgPtr& message) +{ + int delay_cycles = -1; // null value + + dequeue(message); + + // get the delay cycles + delay_cycles = setAndReturnDelayCycles(message); + + assert(delay_cycles >= 0); + return delay_cycles; +} + +void MessageBuffer::dequeue(MsgPtr& message) +{ + DEBUG_MSG(QUEUE_COMP,MedPrio,"dequeue from " + m_name); + message = m_prio_heap.peekMin().m_msgptr; + + pop(); + DEBUG_EXPR(QUEUE_COMP,MedPrio,message); +} + +int MessageBuffer::dequeue_getDelayCycles() +{ + int delay_cycles = -1; // null value + + // get MsgPtr of the message about to be dequeued + MsgPtr message = m_prio_heap.peekMin().m_msgptr; + + // get the delay cycles + delay_cycles = setAndReturnDelayCycles(message); + + dequeue(); + + assert(delay_cycles >= 0); + return delay_cycles; +} + +void MessageBuffer::pop() +{ + DEBUG_MSG(QUEUE_COMP,MedPrio,"pop from " + m_name); + assert(isReady()); + Time ready_time = m_prio_heap.extractMin().m_time; + // record previous size and time so the current buffer size isn't adjusted until next cycle + if (m_time_last_time_pop < g_eventQueue_ptr->getTime()) { + m_size_at_cycle_start = m_size; + m_time_last_time_pop = g_eventQueue_ptr->getTime(); + } + m_size--; +} + +void MessageBuffer::clear() +{ + while(m_prio_heap.size() > 0){ + m_prio_heap.extractMin(); + } + + ASSERT(m_prio_heap.size() == 0); + + m_msg_counter = 0; + m_size = 0; + m_time_last_time_enqueue = 0; + m_time_last_time_pop = 0; + m_size_at_cycle_start = 0; + m_msgs_this_cycle = 0; +} + +void MessageBuffer::recycle() +{ + // const int RECYCLE_LATENCY = 3; + DEBUG_MSG(QUEUE_COMP,MedPrio,"recycling " + m_name); + assert(isReady()); + MessageBufferNode node = m_prio_heap.extractMin(); + node.m_time = g_eventQueue_ptr->getTime() + RECYCLE_LATENCY; + m_prio_heap.insert(node); + g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, g_eventQueue_ptr->getTime() + RECYCLE_LATENCY); +} + +int MessageBuffer::setAndReturnDelayCycles(MsgPtr& message) +{ + int delay_cycles = -1; // null value + + // get the delay cycles of the message at the top of the queue + Message* msg_ptr = message.ref(); + + // this function should only be called on dequeue + // ensure the msg hasn't been enqueued + assert(msg_ptr->getLastEnqueueTime() <= g_eventQueue_ptr->getTime()); + msg_ptr->setDelayedCycles((g_eventQueue_ptr->getTime() - msg_ptr->getLastEnqueueTime())+msg_ptr->getDelayedCycles()); + delay_cycles = msg_ptr->getDelayedCycles(); + + assert(delay_cycles >= 0); + return delay_cycles; +} + +void MessageBuffer::print(ostream& out) const +{ + out << "[MessageBuffer: "; + if (m_consumer_ptr != NULL) { + out << " consumer-yes "; + } + out << m_prio_heap << "] " << m_name << endl; +} + +void MessageBuffer::printStats(ostream& out) +{ + out << "MessageBuffer: " << m_name << " stats - msgs:" << m_msg_counter << " full:" << m_not_avail_count << endl; +} + diff --git a/src/mem/ruby/buffers/MessageBuffer.hh b/src/mem/ruby/buffers/MessageBuffer.hh new file mode 100644 index 000000000..6851423c3 --- /dev/null +++ b/src/mem/ruby/buffers/MessageBuffer.hh @@ -0,0 +1,156 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + * Description: Unordered buffer of messages that can be inserted such + * that they can be dequeued after a given delta time has expired. + * + */ + +#ifndef MESSAGEBUFFER_H +#define MESSAGEBUFFER_H + +#include "Global.hh" +#include "MessageBufferNode.hh" +#include "Consumer.hh" +#include "EventQueue.hh" +#include "Message.hh" +#include "PrioHeap.hh" +#include "util.hh" + +class Chip; + +class MessageBuffer { +public: + // Constructors + MessageBuffer(); + MessageBuffer(const Chip* chip_ptr); // The chip_ptr is ignored, but could be used for extra debugging + + // Use Default Destructor + // ~MessageBuffer() + + // Public Methods + + static void printConfig(ostream& out) {} + + // TRUE if head of queue timestamp <= SystemTime + bool isReady() const { + return ((m_prio_heap.size() > 0) && + (m_prio_heap.peekMin().m_time <= g_eventQueue_ptr->getTime())); + } + + bool areNSlotsAvailable(int n); + int getPriority() { return m_priority_rank; } + void setPriority(int rank) { m_priority_rank = rank; } + void setConsumer(Consumer* consumer_ptr) { ASSERT(m_consumer_ptr==NULL); m_consumer_ptr = consumer_ptr; } + void setDescription(const string& name) { m_name = name; } + string getDescription() { return m_name;} + + Consumer* getConsumer() { return m_consumer_ptr; } + + const Message* peekAtHeadOfQueue() const; + const Message* peek() const { return peekAtHeadOfQueue(); } + const MsgPtr getMsgPtrCopy() const; + const MsgPtr& peekMsgPtr() const { assert(isReady()); return m_prio_heap.peekMin().m_msgptr; } + const MsgPtr& peekMsgPtrEvenIfNotReady() const {return m_prio_heap.peekMin().m_msgptr; } + + void enqueue(const MsgPtr& message) { enqueue(message, 1); } + void enqueue(const MsgPtr& message, Time delta); + // void enqueueAbsolute(const MsgPtr& message, Time absolute_time); + int dequeue_getDelayCycles(MsgPtr& message); // returns delay cycles of the message + void dequeue(MsgPtr& message); + int dequeue_getDelayCycles(); // returns delay cycles of the message + void dequeue() { pop(); } + void pop(); + void recycle(); + bool isEmpty() const { return m_prio_heap.size() == 0; } + + void setOrdering(bool order) { m_strict_fifo = order; m_ordering_set = true; } + void setSize(int size) {m_max_size = size;} + int getSize(); + void setRandomization(bool random_flag) { m_randomization = random_flag; } + + void clear(); + + void print(ostream& out) const; + void printStats(ostream& out); + void clearStats() { m_not_avail_count = 0; m_msg_counter = 0; } + +private: + // Private Methods + int setAndReturnDelayCycles(MsgPtr& message); + + // Private copy constructor and assignment operator + MessageBuffer(const MessageBuffer& obj); + MessageBuffer& operator=(const MessageBuffer& obj); + + // Data Members (m_ prefix) + Consumer* m_consumer_ptr; // Consumer to signal a wakeup(), can be NULL + PrioHeap m_prio_heap; + string m_name; + + int m_max_size; + int m_size; + + Time m_time_last_time_size_checked; + int m_size_last_time_size_checked; + + // variables used so enqueues appear to happen imediately, while pop happen the next cycle + Time m_time_last_time_enqueue; + Time m_time_last_time_pop; + int m_size_at_cycle_start; + int m_msgs_this_cycle; + + int m_not_avail_count; // count the # of times I didn't have N slots available + int m_msg_counter; + int m_priority_rank; + bool m_strict_fifo; + bool m_ordering_set; + bool m_randomization; + Time m_last_arrival_time; +}; + +// Output operator declaration +//template +ostream& operator<<(ostream& out, const MessageBuffer& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const MessageBuffer& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //MESSAGEBUFFER_H diff --git a/src/mem/ruby/buffers/MessageBufferNode.cc b/src/mem/ruby/buffers/MessageBufferNode.cc new file mode 100644 index 000000000..c84347a38 --- /dev/null +++ b/src/mem/ruby/buffers/MessageBufferNode.cc @@ -0,0 +1,48 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * EventQueueNode.C + * + * Description: See EventQueueNode.h + * + * $Id: MessageBufferNode.C,v 3.1 2001/02/02 16:57:54 sorin Exp $ + * + */ + +#include "MessageBufferNode.hh" + +void MessageBufferNode::print(ostream& out) const +{ + out << "["; + out << m_time << ", "; + out << m_msg_counter << ", "; + out << m_msgptr << "; "; + out << "]"; +} diff --git a/src/mem/ruby/buffers/MessageBufferNode.hh b/src/mem/ruby/buffers/MessageBufferNode.hh new file mode 100644 index 000000000..c562c45eb --- /dev/null +++ b/src/mem/ruby/buffers/MessageBufferNode.hh @@ -0,0 +1,88 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MESSAGEBUFFERNODE_H +#define MESSAGEBUFFERNODE_H + +#include "Global.hh" +#include "Message.hh" + +class MessageBufferNode { +public: + // Constructors + MessageBufferNode() { m_time = 0; m_msg_counter = 0; } + MessageBufferNode(const Time& time, int counter, const MsgPtr& msgptr) + { m_time = time; m_msgptr = msgptr; m_msg_counter = counter; } + // Destructor + //~MessageBufferNode(); + + // Public Methods + void print(ostream& out) const; +private: + // Private Methods + + // Default copy constructor and assignment operator + // MessageBufferNode(const MessageBufferNode& obj); + // MessageBufferNode& operator=(const MessageBufferNode& obj); + + // Data Members (m_ prefix) +public: + Time m_time; + int m_msg_counter; // FIXME, should this be a 64-bit value? + MsgPtr m_msgptr; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const MessageBufferNode& obj); + +// ******************* Definitions ******************* + +inline extern bool node_less_then_eq(const MessageBufferNode& n1, const MessageBufferNode& n2); + +inline extern +bool node_less_then_eq(const MessageBufferNode& n1, const MessageBufferNode& n2) +{ + if (n1.m_time == n2.m_time) { + assert(n1.m_msg_counter != n2.m_msg_counter); + return (n1.m_msg_counter <= n2.m_msg_counter); + } else { + return (n1.m_time <= n2.m_time); + } +} + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const MessageBufferNode& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //MESSAGEBUFFERNODE_H diff --git a/src/mem/ruby/common/Address.cc b/src/mem/ruby/common/Address.cc new file mode 100644 index 000000000..5d38faae0 --- /dev/null +++ b/src/mem/ruby/common/Address.cc @@ -0,0 +1,68 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "Address.hh" + +void Address::output(ostream& out) const +{ + // Note: this outputs addresses in the form "ffff", not "0xffff". + // This code should always be able to write out addresses in a + // format that can be read in by the below input() method. Please + // don't change this without talking to Milo first. + out << hex << m_address << dec; +} + +void Address::input(istream& in) +{ + // Note: this only works with addresses in the form "ffff", not + // "0xffff". This code should always be able to read in addresses + // written out by the above output() method. Please don't change + // this without talking to Milo first. + in >> hex >> m_address >> dec; +} + +Address::Address(const Address& obj) +{ + m_address = obj.m_address; +} + +Address& Address::operator=(const Address& obj) +{ + if (this == &obj) { + // assert(false); + } else { + m_address = obj.m_address; + } + return *this; +} + diff --git a/src/mem/ruby/common/Address.hh b/src/mem/ruby/common/Address.hh new file mode 100644 index 000000000..3c3c5ad30 --- /dev/null +++ b/src/mem/ruby/common/Address.hh @@ -0,0 +1,255 @@ + +/* + * Copyright (c) 1999 by Mark Hill and David Wood for the Wisconsin + * Multifacet Project. ALL RIGHTS RESERVED. + * + * ##HEADER## + * + * This software is furnished under a license and may be used and + * copied only in accordance with the terms of such license and the + * inclusion of the above copyright notice. This software or any + * other copies thereof or any derivative works may not be provided or + * otherwise made available to any other persons. Title to and + * ownership of the software is retained by Mark Hill and David Wood. + * Any use of this software must include the above copyright notice. + * + * THIS SOFTWARE IS PROVIDED "AS IS". THE LICENSOR MAKES NO + * WARRANTIES ABOUT ITS CORRECTNESS OR PERFORMANCE. + * */ + +/* + * $Id$ + */ + +#ifndef ADDRESS_H +#define ADDRESS_H + +#include +#include "Global.hh" +#include "RubyConfig.hh" +#include "NodeID.hh" +#include "MachineID.hh" + +const int ADDRESS_WIDTH = 64; // address width in bytes + +class Address; +typedef Address PhysAddress; +typedef Address VirtAddress; + +class Address { +public: + // Constructors + Address() { m_address = 0; } + explicit Address(physical_address_t address) { m_address = address; } + + Address(const Address& obj); + Address& operator=(const Address& obj); + + // Destructor + // ~Address(); + + // Public Methods + + void setAddress(physical_address_t address) { m_address = address; } + physical_address_t getAddress() const {return m_address;} + // selects bits inclusive + physical_address_t bitSelect(int small, int big) const; + physical_address_t maskLowOrderBits(int number) const; + physical_address_t maskHighOrderBits(int number) const; + physical_address_t shiftLowOrderBits(int number) const; + physical_address_t getLineAddress() const + { return bitSelect(RubyConfig::dataBlockBits(), ADDRESS_WIDTH); } + physical_address_t getOffset() const + { return bitSelect(0, RubyConfig::dataBlockBits()-1); } + + void makeLineAddress() { m_address = maskLowOrderBits(RubyConfig::dataBlockBits()); } + // returns the next stride address based on line address + void makeNextStrideAddress( int stride) { + m_address = maskLowOrderBits(RubyConfig::dataBlockBits()) + + RubyConfig::dataBlockBytes()*stride; + } + void makePageAddress() { m_address = maskLowOrderBits(RubyConfig::pageSizeBits()); } + int getBankSetNum() const; + int getBankSetDist() const; + + Index memoryModuleIndex() const; + + void print(ostream& out) const; + void output(ostream& out) const; + void input(istream& in); + + void setOffset( int offset ){ + // first, zero out the offset bits + makeLineAddress(); + m_address |= (physical_address_t) offset; + } + +private: + // Private Methods + + // Private copy constructor and assignment operator + // Address(const Address& obj); + // Address& operator=(const Address& obj); + + // Data Members (m_ prefix) + physical_address_t m_address; +}; + +inline +Address line_address(const Address& addr) { Address temp(addr); temp.makeLineAddress(); return temp; } + +inline +Address next_stride_address(const Address& addr, int stride) { + Address temp = addr; + temp.makeNextStrideAddress(stride); + temp.setAddress(temp.maskHighOrderBits(ADDRESS_WIDTH-RubyConfig::memorySizeBits())); // surpress wrap-around problem + return temp; +} + +inline +Address page_address(const Address& addr) { Address temp(addr); temp.makePageAddress(); return temp; } + +// Output operator declaration +ostream& operator<<(ostream& out, const Address& obj); +// comparison operator declaration +bool operator==(const Address& obj1, const Address& obj2); +bool operator!=(const Address& obj1, const Address& obj2); +bool operator<(const Address& obj1, const Address& obj2); +/* Address& operator=(const physical_address_t address); */ + +inline +bool operator<(const Address& obj1, const Address& obj2) +{ + return obj1.getAddress() < obj2.getAddress(); +} + +// ******************* Definitions ******************* + +// Output operator definition +inline +ostream& operator<<(ostream& out, const Address& obj) +{ + obj.print(out); + out << flush; + return out; +} + +inline +bool operator==(const Address& obj1, const Address& obj2) +{ + return (obj1.getAddress() == obj2.getAddress()); +} + +inline +bool operator!=(const Address& obj1, const Address& obj2) +{ + return (obj1.getAddress() != obj2.getAddress()); +} + +inline +physical_address_t Address::bitSelect(int small, int big) const // rips bits inclusive +{ + physical_address_t mask; + assert(big >= small); + + if (big >= ADDRESS_WIDTH - 1) { + return (m_address >> small); + } else { + mask = ~((physical_address_t)~0 << (big + 1)); + // FIXME - this is slow to manipulate a 64-bit number using 32-bits + physical_address_t partial = (m_address & mask); + return (partial >> small); + } +} + +inline +physical_address_t Address::maskLowOrderBits(int number) const +{ + physical_address_t mask; + + if (number >= ADDRESS_WIDTH - 1) { + mask = ~0; + } else { + mask = (physical_address_t)~0 << number; + } + return (m_address & mask); +} + +inline +physical_address_t Address::maskHighOrderBits(int number) const +{ + physical_address_t mask; + + if (number >= ADDRESS_WIDTH - 1) { + mask = ~0; + } else { + mask = (physical_address_t)~0 >> number; + } + return (m_address & mask); +} + +inline +physical_address_t Address::shiftLowOrderBits(int number) const +{ + return (m_address >> number); +} + +inline +integer_t Address::memoryModuleIndex() const +{ + integer_t index = bitSelect(RubyConfig::dataBlockBits()+RubyConfig::memoryBits(), ADDRESS_WIDTH); + assert (index >= 0); + if (index >= RubyConfig::memoryModuleBlocks()) { + cerr << " memoryBits: " << RubyConfig::memoryBits() << " memorySizeBits: " << RubyConfig::memorySizeBits() + << " Address: " << "[" << hex << "0x" << m_address << "," << " line 0x" << maskLowOrderBits(RubyConfig::dataBlockBits()) << dec << "]" << flush + << "error: limit exceeded. " << + " dataBlockBits: " << RubyConfig::dataBlockBits() << + " memoryModuleBlocks: " << RubyConfig::memoryModuleBlocks() << + " index: " << index << endl; + } + assert (index < RubyConfig::memoryModuleBlocks()); + return index; + + // Index indexHighPortion = address.bitSelect(MEMORY_SIZE_BITS-1, PAGE_SIZE_BITS+NUMBER_OF_MEMORY_MODULE_BITS); + // Index indexLowPortion = address.bitSelect(DATA_BLOCK_BITS, PAGE_SIZE_BITS-1); + + //Index index = indexLowPortion | (indexHighPortion << (PAGE_SIZE_BITS - DATA_BLOCK_BITS)); + + /* + Round-robin mapping of addresses, at page size granularity + +ADDRESS_WIDTH MEMORY_SIZE_BITS PAGE_SIZE_BITS DATA_BLOCK_BITS + | | | | + \ / \ / \ / \ / 0 + ----------------------------------------------------------------------- + | unused |xxxxxxxxxxxxxxx| |xxxxxxxxxxxxxxx| | + | |xxxxxxxxxxxxxxx| |xxxxxxxxxxxxxxx| | + ----------------------------------------------------------------------- + indexHighPortion indexLowPortion + <-------> + NUMBER_OF_MEMORY_MODULE_BITS + */ +} + +inline +void Address::print(ostream& out) const +{ + out << "[" << hex << "0x" << m_address << "," << " line 0x" << maskLowOrderBits(RubyConfig::dataBlockBits()) << dec << "]" << flush; +} + +class Address; +namespace __gnu_cxx { + template <> struct hash
+ { + size_t operator()(const Address &s) const { return (size_t) s.getAddress(); } + }; +} +namespace std { + template <> struct equal_to
+ { + bool operator()(const Address& s1, const Address& s2) const { return s1 == s2; } + }; +} + +#endif //ADDRESS_H + diff --git a/src/mem/ruby/common/BigSet.cc b/src/mem/ruby/common/BigSet.cc new file mode 100644 index 000000000..e16284f15 --- /dev/null +++ b/src/mem/ruby/common/BigSet.cc @@ -0,0 +1,249 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Set.hh" +#include "RubyConfig.hh" + +Set::Set() +{ + setSize(RubyConfig::numberOfProcessors()); +} + +Set::Set(int size) +{ + setSize(size); +} + +void Set::add(NodeID index) +{ + m_bits[index] = Present; +} + +void Set::addSet(const Set& set) +{ + assert(m_bits.size() == set.getSize()); + for (int i=0; i> 1); // Shift the random number to look at the next bit + } +} + +void Set::remove(NodeID index) +{ + m_bits[index] = NotPresent; +} + +void Set::removeSet(const Set& set) +{ + assert(m_bits.size() == set.getSize()); + for (int i=0; i 0); + for (int i=0; i m_bits; // This is an vector of uint8 to reduce the size of the set +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const Set& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const Set& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //SET_H + diff --git a/src/mem/ruby/common/Consumer.hh b/src/mem/ruby/common/Consumer.hh new file mode 100644 index 000000000..bd51af7ba --- /dev/null +++ b/src/mem/ruby/common/Consumer.hh @@ -0,0 +1,89 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + * Description: This is the virtual base class of all classes that can + * be the targets of wakeup events. There is only two methods, + * wakeup() and print() and no data members. + * + */ + +#ifndef CONSUMER_H +#define CONSUMER_H + +#include "Global.hh" +#include "EventQueue.hh" + +class MessageBuffer; + +class Consumer { +public: + // Constructors + Consumer() { m_last_scheduled_wakeup = 0; m_last_wakeup = 0; m_out_link_vec.setSize(0); } + + // Destructor + virtual ~Consumer() { } + + // Public Methods - pure virtual methods + void triggerWakeup() { Time time = g_eventQueue_ptr->getTime(); if (m_last_wakeup != time) { wakeup(); m_last_wakeup = time; }} + virtual void wakeup() = 0; + virtual void print(ostream& out) const = 0; + const Time& getLastScheduledWakeup() const { return m_last_scheduled_wakeup; } + void setLastScheduledWakeup(const Time& time) { m_last_scheduled_wakeup = time; } + Vector< Vector > getOutBuffers() { return m_out_link_vec; } + +protected: + Vector< Vector > m_out_link_vec; + +private: + // Private Methods + + // Data Members (m_ prefix) + Time m_last_scheduled_wakeup; + Time m_last_wakeup; +}; + +// Output operator declaration +inline extern +ostream& operator<<(ostream& out, const Consumer& obj); + +// ******************* Definitions ******************* + +// Output operator definition +inline extern +ostream& operator<<(ostream& out, const Consumer& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //CONSUMER_H diff --git a/src/mem/ruby/common/DataBlock.cc b/src/mem/ruby/common/DataBlock.cc new file mode 100644 index 000000000..c4d6d7a33 --- /dev/null +++ b/src/mem/ruby/common/DataBlock.cc @@ -0,0 +1,91 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "DataBlock.hh" + +DataBlock::DataBlock() +{ + if (DATA_BLOCK || XACT_MEMORY) { + m_data.setSize(RubyConfig::dataBlockBytes()); + } + clear(); +} + +DataBlock::~DataBlock() +{ + +} + +void DataBlock::clear() +{ + int size = m_data.size(); + for (int i = 0; i < size; i++) { + m_data[i] = 0; + } +} + +bool DataBlock::equal(const DataBlock& obj) const +{ + bool value = true; + int size = m_data.size(); + for (int i = 0; i < size; i++) { + value = value && (m_data[i] == obj.m_data[i]); + } + return value; +} + +void DataBlock::print(ostream& out) const +{ + int size = m_data.size(); + for (int i = 0; i < size; i+=4) { + out << hex << *((uint32*)(&(m_data[i]))) << " "; + } + out << dec << "]" << flush; +} + +uint8 DataBlock::getByte(int whichByte) const +{ + if (DATA_BLOCK || XACT_MEMORY) { + return m_data[whichByte]; + } else { + return 0; + } +} + +void DataBlock::setByte(int whichByte, uint8 data) +{ + if (DATA_BLOCK || XACT_MEMORY) { + m_data[whichByte] = data; + } +} + diff --git a/src/mem/ruby/common/DataBlock.hh b/src/mem/ruby/common/DataBlock.hh new file mode 100644 index 000000000..aae364078 --- /dev/null +++ b/src/mem/ruby/common/DataBlock.hh @@ -0,0 +1,82 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DATABLOCK_H +#define DATABLOCK_H + +#include "Global.hh" +#include "RubyConfig.hh" +#include "Vector.hh" + +class DataBlock { +public: + // Constructors + DataBlock(); + + // Destructor + ~DataBlock(); + + // Public Methods + void clear(); + uint8 getByte(int whichByte) const; + void setByte(int whichByte, uint8 data); + bool equal(const DataBlock& obj) const; + void print(ostream& out) const; + +private: + // Private Methods + + // Data Members (m_ prefix) + Vector m_data; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const DataBlock& obj); + +bool operator==(const DataBlock& obj1, const DataBlock& obj2); + + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const DataBlock& obj) +{ + obj.print(out); + out << flush; + return out; +} + +extern inline +bool operator==(const DataBlock& obj1,const DataBlock& obj2) +{ + return (obj1.equal(obj2)); +} + +#endif //DATABLOCK_H diff --git a/src/mem/ruby/common/Debug.cc b/src/mem/ruby/common/Debug.cc new file mode 100644 index 000000000..f0319ceb8 --- /dev/null +++ b/src/mem/ruby/common/Debug.cc @@ -0,0 +1,369 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + */ + +#include +#include + +#include "Global.hh" +#include "Debug.hh" +#include "EventQueue.hh" + +class Debug; +extern Debug* g_debug_ptr; +std::ostream * debug_cout_ptr; + +// component character list +const char DEFINE_COMP_CHAR[] = +{ +#undef DEFINE_COMP +#define DEFINE_COMP(component, character, description) character, +#include "Debug.def" +}; + +// component description list +const char* DEFINE_COMP_DESCRIPTION[] = +{ +#undef DEFINE_COMP +#define DEFINE_COMP(component, character, description) description, +#include "Debug.def" +}; + +extern "C" void changeDebugVerbosity(VerbosityLevel vb); +extern "C" void changeDebugFilter(int filter); + +void changeDebugVerbosity(VerbosityLevel vb) +{ + g_debug_ptr->setVerbosity(vb); +} + +void changeDebugFilter(int filter) +{ + g_debug_ptr->setFilter(filter); +} + +Debug::Debug( const char *filterString, const char *verboseString, + Time filterStartTime, const char *filename ) +{ + m_verbosityLevel = No_Verb; + clearFilter(); + debug_cout_ptr = &cout; + + m_starting_cycle = filterStartTime; + setFilterString( filterString ); + setVerbosityString( verboseString ); + setDebugOutputFile( filename ); +} + +Debug::~Debug() +{ +} + +void Debug::printVerbosity(ostream& out) const +{ + switch (getVerbosity()) { + case No_Verb: + out << "verbosity = No_Verb" << endl; + break; + case Low_Verb: + out << "verbosity = Low_Verb" << endl; + break; + case Med_Verb: + out << "verbosity = Med_Verb" << endl; + break; + case High_Verb: + out << "verbosity = High_Verb" << endl; + break; + default: + out << "verbosity = unknown" << endl; + } +} + +bool Debug::validDebug(int module, PriorityLevel priority) +{ + int local_module = (1 << module); + if(m_filter & local_module) { + if (g_eventQueue_ptr == NULL || + g_eventQueue_ptr->getTime() >= m_starting_cycle) { + switch(m_verbosityLevel) { + case No_Verb: + return false; + break; + case Low_Verb: + if(priority == HighPrio) { + return true; + }else{ + return false; + } + break; + case Med_Verb: + if(priority == HighPrio || priority == MedPrio ) { + return true; + }else{ + return false; + } + break; + case High_Verb: + return true; + break; + } + } + } + return false; +} + +void Debug::setDebugTime(Time t) +{ + m_starting_cycle = t; +} + +void Debug::setVerbosity(VerbosityLevel vb) +{ + m_verbosityLevel = vb; +} + +void Debug::setFilter(int filter) +{ + m_filter = filter; +} + +bool Debug::checkVerbosityString(const char *verb_str) +{ + if (verb_str == NULL) { + cerr << "Error: unrecognized verbosity (use none, low, med, high): NULL" << endl; + return true; // error + } else if ( (string(verb_str) == "none") || + (string(verb_str) == "low") || + (string(verb_str) == "med") || + (string(verb_str) == "high") ) { + return false; + } + cerr << "Error: unrecognized verbosity (use none, low, med, high): NULL" << endl; + return true; // error +} + +bool Debug::setVerbosityString(const char *verb_str) +{ + bool check_fails = checkVerbosityString(verb_str); + if (check_fails) { + return true; // error + } + if (string(verb_str) == "none") { + setVerbosity(No_Verb); + } else if (string(verb_str) == "low") { + setVerbosity(Low_Verb); + } else if (string(verb_str) == "med") { + setVerbosity(Med_Verb); + } else if (string(verb_str) == "high") { + setVerbosity(High_Verb); + } else { + cerr << "Error: unrecognized verbosity (use none, low, med, high): " << verb_str << endl; + return true; // error + } + return false; // no error +} + +bool Debug::checkFilter(char ch) +{ + for (int i=0; i +#include + +extern std::ostream * debug_cout_ptr; + +// component enumeration +enum DebugComponents +{ +#undef DEFINE_COMP +#define DEFINE_COMP(component, character, description) component, +#include "Debug.def" + NUMBER_OF_COMPS +}; + +enum PriorityLevel {HighPrio, MedPrio, LowPrio}; +enum VerbosityLevel {No_Verb, Low_Verb, Med_Verb, High_Verb}; + +class Debug { +public: + // Constructors + Debug( const char *filterString, const char *verboseString, + Time filterStartTime, const char *filename ); + + // Destructor + ~Debug(); + + // Public Methods + bool validDebug(int module, PriorityLevel priority); + void printVerbosity(ostream& out) const; + void setVerbosity(VerbosityLevel vb); + static bool checkVerbosityString(const char *verb_str); + bool setVerbosityString(const char *); + VerbosityLevel getVerbosity() const { return m_verbosityLevel; } + void setFilter(int); + static bool checkFilter( char); + static bool checkFilterString(const char *); + bool setFilterString(const char *); + void setDebugTime(Time); + Time getDebugTime() const { return m_starting_cycle; } + bool addFilter(char); + void clearFilter(); + void allFilter(); + void print(ostream& out) const; + /* old school debugging "vararg": sends messages to screen and log */ + void debugMsg( const char *fmt, ... ); + + void setDebugOutputFile (const char * filename); + void closeDebugOutputFile (); + static void usageInstructions(void); + +private: + // Private Methods + + // Private copy constructor and assignment operator + Debug(const Debug& obj); + Debug& operator=(const Debug& obj); + + // Data Members (m_ prefix) + VerbosityLevel m_verbosityLevel; + int m_filter; + Time m_starting_cycle; + + std::fstream m_fout; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const Debug& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const Debug& obj) +{ + obj.print(out); + out << flush; + return out; +} + +const bool ERROR_MESSAGE_FLAG = true; +const bool WARNING_MESSAGE_FLAG = true; + +#ifdef RUBY_NO_ASSERT +const bool ASSERT_FLAG = false; +#else +const bool ASSERT_FLAG = true; +#endif + +#undef assert +#define assert(EXPR) ASSERT(EXPR) +#undef ASSERT +#define ASSERT(EXPR)\ +{\ + if (ASSERT_FLAG) {\ + if (!(EXPR)) {\ + cerr << "failed assertion '"\ + << #EXPR << "' at fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << endl << flush;\ + (* debug_cout_ptr) << "failed assertion '"\ + << #EXPR << "' at fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << endl << flush;\ + if(isatty(STDIN_FILENO)) {\ + cerr << "At this point you might want to attach a debug to ";\ + cerr << "the running and get to the" << endl;\ + cerr << "crash site; otherwise press enter to continue" << endl;\ + cerr << "PID: " << getpid();\ + cerr << endl << flush; \ + char c; \ + cin.get(c); \ + }\ + abort();\ + }\ + }\ +} + +#define BREAK(X)\ +{\ + cerr << "breakpoint '"\ + << #X << "' reached at fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << endl << flush;\ + if(isatty(STDIN_FILENO)) {\ + cerr << "press enter to continue" << endl;\ + cerr << "PID: " << getpid();\ + cerr << endl << flush; \ + char c; \ + cin.get(c); \ + }\ +} + +#define ERROR_MSG(MESSAGE)\ +{\ + if (ERROR_MESSAGE_FLAG) {\ + cerr << "Fatal Error: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": "\ + << (MESSAGE) << endl << flush;\ + (* debug_cout_ptr) << "Fatal Error: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": "\ + << (MESSAGE) << endl << flush;\ + abort();\ + }\ +} + +#define WARN_MSG(MESSAGE)\ +{\ + if (WARNING_MESSAGE_FLAG) {\ + cerr << "Warning: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": "\ + << (MESSAGE) << endl << flush;\ + (* debug_cout_ptr) << "Warning: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": "\ + << (MESSAGE) << endl << flush;\ + }\ +} + +#define WARN_EXPR(EXPR)\ +{\ + if (WARNING_MESSAGE_FLAG) {\ + cerr << "Warning: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": "\ + << #EXPR << " is "\ + << (EXPR) << endl << flush;\ + (* debug_cout_ptr) << "Warning: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": "\ + << #EXPR << " is "\ + << (EXPR) << endl << flush;\ + }\ +} + +#define DEBUG_MSG(module, priority, MESSAGE)\ +{\ + if (RUBY_DEBUG) {\ + if (g_debug_ptr->validDebug(module, priority)) {\ + (* debug_cout_ptr) << "Debug: in fn "\ + << __PRETTY_FUNCTION__\ + << " in " << __FILE__ << ":"\ + << __LINE__ << ": "\ + << (MESSAGE) << endl << flush;\ + }\ + }\ +} + +#define DEBUG_EXPR(module, priority, EXPR)\ +{\ + if (RUBY_DEBUG) {\ + if (g_debug_ptr->validDebug(module, priority)) {\ + (* debug_cout_ptr) << "Debug: in fn "\ + << __PRETTY_FUNCTION__\ + << " in " << __FILE__ << ":"\ + << __LINE__ << ": "\ + << #EXPR << " is "\ + << (EXPR) << endl << flush;\ + }\ + }\ +} + +#define DEBUG_NEWLINE(module, priority)\ +{\ + if (RUBY_DEBUG) {\ + if (g_debug_ptr->validDebug(module, priority)) {\ + (* debug_cout_ptr) << endl << flush;\ + }\ + }\ +} + +#define DEBUG_SLICC(priority, LINE, MESSAGE)\ +{\ + if (RUBY_DEBUG) {\ + if (g_debug_ptr->validDebug(SLICC_COMP, priority)) {\ + (* debug_cout_ptr) << (LINE) << (MESSAGE) << endl << flush;\ + }\ + }\ +} + +#define DEBUG_OUT( rest... ) \ +{\ + if (RUBY_DEBUG) {\ + cout << "Debug: in fn "\ + << __PRETTY_FUNCTION__\ + << " in " << __FILE__ << ":"\ + << __LINE__ << ": "; \ + g_debug_ptr->debugMsg(rest); \ + }\ +} + +#define ERROR_OUT( rest... ) \ +{\ + if (ERROR_MESSAGE_FLAG) {\ + cout << "error: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": ";\ + g_debug_ptr->debugMsg(rest); \ + }\ +} + +#endif //DEBUG_H + diff --git a/src/mem/ruby/common/Driver.cc b/src/mem/ruby/common/Driver.cc new file mode 100644 index 000000000..019ac6403 --- /dev/null +++ b/src/mem/ruby/common/Driver.cc @@ -0,0 +1,39 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Driver.hh" + +Driver::Driver() +{ +} + +// still need to be defined for subclasses +Driver::~Driver() +{ +} diff --git a/src/mem/ruby/common/Driver.hh b/src/mem/ruby/common/Driver.hh new file mode 100644 index 000000000..911cb742b --- /dev/null +++ b/src/mem/ruby/common/Driver.hh @@ -0,0 +1,98 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DRIVER_H +#define DRIVER_H + +#include "Global.hh" +#include "Consumer.hh" +#include "NodeID.hh" +#include "CacheRequestType.hh" + +class System; +class SubBlock; +class Address; +class MachineID; +class SimicsHypervisor; + +class Driver { +public: + // Constructors + Driver(); + + // Destructor + virtual ~Driver() = 0; + + // Public Methods + virtual void get_network_config() {} + virtual void hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread) = 0; // Called by sequencer + virtual void conflictCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread) { assert(0); } // Called by sequencer + virtual integer_t getInstructionCount(int procID) const { return 1; } + virtual integer_t getCycleCount(int procID) const { return 1; } + virtual SimicsHypervisor * getHypervisor() { return NULL; } + virtual void notifySendNack( int procID, const Address & addr, uint64 remote_timestamp, const MachineID & remote_id) { assert(0); }; //Called by Sequencer + virtual void notifyReceiveNack( int procID, const Address & addr, uint64 remote_timestamp, const MachineID & remote_id) { assert(0); }; //Called by Sequencer + virtual void notifyReceiveNackFinal( int procID, const Address & addr) { assert(0); }; // Called by Sequencer + virtual void notifyTrapStart( int procID, const Address & handlerPC, int threadID, int smtThread ) { assert(0); } //called by Sequencer + virtual void notifyTrapComplete( int procID, const Address & newPC, int smtThread ) {assert(0); } // called by Sequencer + virtual int getOpalTransactionLevel(int procID, int thread) const { + cout << "Driver.hh getOpalTransactionLevel() " << endl; + return 0; } //called by Sequencer + virtual void addThreadDependency(int procID, int requestor_thread, int conflict_thread) const { assert(0);} + virtual uint64 getOpalTime(int procID) const{ return 0; } //called by Sequencer + virtual uint64 getOpalTimestamp(int procID, int thread) const{ + cout << "Driver.hh getOpalTimestamp " << endl; + return 0; } // called by Sequencer + virtual int inTransaction(int procID, int thread ) const{ + cout << "Driver.hh inTransaction " << endl; +return false; } //called by Sequencer + virtual void printDebug(){} //called by Sequencer + + virtual void printStats(ostream& out) const = 0; + virtual void clearStats() = 0; + + virtual void printConfig(ostream& out) const = 0; + + //virtual void abortCallback(NodeID proc){} + + virtual integer_t readPhysicalMemory(int procID, physical_address_t address, + int len ){ ASSERT(0); return 0; } + + virtual void writePhysicalMemory( int procID, physical_address_t address, + integer_t value, int len ){ ASSERT(0); } + +protected: + // accessible by subclasses + +private: + // inaccessible by subclasses + +}; + +#endif //DRIVER_H diff --git a/src/mem/ruby/common/Global.cc b/src/mem/ruby/common/Global.cc new file mode 100644 index 000000000..e60cd4fd3 --- /dev/null +++ b/src/mem/ruby/common/Global.cc @@ -0,0 +1,35 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Global.hh" + +EventQueue* g_eventQueue_ptr = NULL; +System* g_system_ptr = NULL; +Debug* g_debug_ptr = NULL; + diff --git a/src/mem/ruby/common/Global.hh b/src/mem/ruby/common/Global.hh new file mode 100644 index 000000000..eaec05d46 --- /dev/null +++ b/src/mem/ruby/common/Global.hh @@ -0,0 +1,110 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + * */ + +#ifndef GLOBAL_H +#define GLOBAL_H + +#ifdef SINGLE_LEVEL_CACHE +const bool TWO_LEVEL_CACHE = false; +#define L1I_CACHE_MEMBER_VARIABLE m_L1Cache_cacheMemory_vec[m_version] // currently all protocols require L1s == nodes +#define L1D_CACHE_MEMBER_VARIABLE m_L1Cache_cacheMemory_vec[m_version] // " +#define L2_CACHE_MEMBER_VARIABLE m_L1Cache_cacheMemory_vec[m_version] // " +#define L2_CACHE_VARIABLE m_L1Cache_cacheMemory_vec +#else +const bool TWO_LEVEL_CACHE = true; +#ifdef IS_CMP +#define L1I_CACHE_MEMBER_VARIABLE m_L1Cache_L1IcacheMemory_vec[m_version] +#define L1D_CACHE_MEMBER_VARIABLE m_L1Cache_L1DcacheMemory_vec[m_version] +#define L2_CACHE_MEMBER_VARIABLE m_L2Cache_L2cacheMemory_vec[m_version] +#define L2_CACHE_VARIABLE m_L2Cache_L2cacheMemory_vec +#else // not IS_CMP +#define L1I_CACHE_MEMBER_VARIABLE m_L1Cache_L1IcacheMemory_vec[m_version] // currently all protocols require L1s == nodes +#define L1D_CACHE_MEMBER_VARIABLE m_L1Cache_L1DcacheMemory_vec[m_version] // " +// #define L2_CACHE_MEMBER_VARIABLE m_L1Cache_L2cacheMemory_vec[m_version] // old exclusive caches don't support L2s != nodes +#define L2_CACHE_MEMBER_VARIABLE m_L1Cache_cacheMemory_vec[m_version] // old exclusive caches don't support L2s != nodes +#define L2_CACHE_VARIABLE m_L1Cache_L2cacheMemory_vec +#endif // IS_CMP +#endif //SINGLE_LEVEL_CACHE + +#define DIRECTORY_MEMBER_VARIABLE m_Directory_directory_vec[m_version] +#define TBE_TABLE_MEMBER_VARIABLE m_L1Cache_TBEs_vec[m_version] + +typedef unsigned char uint8; +typedef unsigned int uint32; +typedef unsigned long long uint64; + +typedef signed char int8; +typedef int int32; +typedef long long int64; + +typedef long long integer_t; +typedef unsigned long long uinteger_t; + +typedef int64 Time; +typedef uint64 physical_address_t; +typedef uint64 la_t; +typedef uint64 pa_t; +typedef integer_t simtime_t; + +// external includes for all classes +#include "std-includes.hh" +#include "Debug.hh" + +// simple type declarations +typedef Time LogicalTime; +typedef int64 Index; // what the address bit ripper returns +typedef int word; // one word of a cache line +typedef unsigned int uint; +typedef int SwitchID; +typedef int LinkID; + +class EventQueue; +extern EventQueue* g_eventQueue_ptr; + +class System; +extern System* g_system_ptr; + +class Debug; +extern Debug* g_debug_ptr; + +// FIXME: this is required by the contructor of Directory_Entry.h. It can't go +// into slicc_util.h because it opens a can of ugly worms +extern inline int max_tokens() +{ + return 1024; +} + + +#endif //GLOBAL_H + diff --git a/src/mem/ruby/common/Histogram.cc b/src/mem/ruby/common/Histogram.cc new file mode 100644 index 000000000..9c5e8e623 --- /dev/null +++ b/src/mem/ruby/common/Histogram.cc @@ -0,0 +1,185 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + */ + +#include "Histogram.hh" + +Histogram::Histogram(int binsize, int bins) +{ + m_binsize = binsize; + m_bins = bins; + clear(); +} + +Histogram::~Histogram() +{ +} + +void Histogram::clear(int binsize, int bins) +{ + m_binsize = binsize; + clear(bins); +} + +void Histogram::clear(int bins) +{ + m_bins = bins; + m_largest_bin = 0; + m_max = 0; + m_data.setSize(m_bins); + for (int i = 0; i < m_bins; i++) { + m_data[i] = 0; + } + m_count = 0; + m_max = 0; + + m_sumSamples = 0; + m_sumSquaredSamples = 0; +} + + +void Histogram::add(int64 value) +{ + assert(value >= 0); + m_max = max(m_max, value); + m_count++; + + m_sumSamples += value; + m_sumSquaredSamples += (value*value); + + int index; + if (m_binsize == -1) { + // This is a log base 2 histogram + if (value == 0) { + index = 0; + } else { + index = int(log(double(value))/log(2.0))+1; + if (index >= m_data.size()) { + index = m_data.size()-1; + } + } + } else { + // This is a linear histogram + while (m_max >= (m_bins * m_binsize)) { + for (int i = 0; i < m_bins/2; i++) { + m_data[i] = m_data[i*2] + m_data[i*2 + 1]; + } + for (int i = m_bins/2; i < m_bins; i++) { + m_data[i] = 0; + } + m_binsize *= 2; + } + index = value/m_binsize; + } + assert(index >= 0); + m_data[index]++; + m_largest_bin = max(m_largest_bin, index); +} + +void Histogram::add(const Histogram& hist) +{ + assert(hist.getBins() == m_bins); + assert(hist.getBinSize() == -1); // assume log histogram + assert(m_binsize == -1); + + for (int j = 0; j < hist.getData(0); j++) { + add(0); + } + + for (int i = 1; i < m_bins; i++) { + for (int j = 0; j < hist.getData(i); j++) { + add(1<<(i-1)); // account for the + 1 index + } + } + +} + +// Computation of standard deviation of samples a1, a2, ... aN +// variance = [SUM {ai^2} - (SUM {ai})^2/N]/(N-1) +// std deviation equals square root of variance +double Histogram::getStandardDeviation() const +{ + double variance; + if(m_count > 1){ + variance = (double)(m_sumSquaredSamples - m_sumSamples*m_sumSamples/m_count)/(m_count - 1); + } else { + return 0; + } + return sqrt(variance); +} + +void Histogram::print(ostream& out) const +{ + printWithMultiplier(out, 1.0); +} + +void Histogram::printPercent(ostream& out) const +{ + if (m_count == 0) { + printWithMultiplier(out, 0.0); + } else { + printWithMultiplier(out, 100.0/double(m_count)); + } +} + +void Histogram::printWithMultiplier(ostream& out, double multiplier) const +{ + if (m_binsize == -1) { + out << "[binsize: log2 "; + } else { + out << "[binsize: " << m_binsize << " "; + } + out << "max: " << m_max << " "; + out << "count: " << m_count << " "; + // out << "total: " << m_sumSamples << " "; + if (m_count == 0) { + out << "average: NaN |"; + out << "standard deviation: NaN |"; + } else { + out << "average: " << setw(5) << ((double) m_sumSamples)/m_count << " | "; + out << "standard deviation: " << getStandardDeviation() << " |"; + } + for (int i = 0; i < m_bins && i <= m_largest_bin; i++) { + if (multiplier == 1.0) { + out << " " << m_data[i]; + } else { + out << " " << double(m_data[i]) * multiplier; + } + } + out << " ]"; +} + +bool node_less_then_eq(const Histogram* n1, const Histogram* n2) +{ + return (n1->size() > n2->size()); +} diff --git a/src/mem/ruby/common/Histogram.hh b/src/mem/ruby/common/Histogram.hh new file mode 100644 index 000000000..e48efc35f --- /dev/null +++ b/src/mem/ruby/common/Histogram.hh @@ -0,0 +1,104 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + * Description: The histogram class implements a simple histogram + * + */ + +#ifndef HISTOGRAM_H +#define HISTOGRAM_H + +#include "Global.hh" +#include "Vector.hh" + +class Histogram { +public: + // Constructors + Histogram(int binsize = 1, int bins = 50); + + // Destructor + ~Histogram(); + + // Public Methods + + void add(int64 value); + void add(const Histogram& hist); + void clear() { clear(m_bins); } + void clear(int bins); + void clear(int binsize, int bins); + int64 size() const { return m_count; } + int getBins() const { return m_bins; } + int getBinSize() const { return m_binsize; } + int64 getTotal() const { return m_sumSamples; } + int64 getData(int index) const { return m_data[index]; } + + void printWithMultiplier(ostream& out, double multiplier) const; + void printPercent(ostream& out) const; + void print(ostream& out) const; +private: + // Private Methods + + // Private copy constructor and assignment operator + // Histogram(const Histogram& obj); + // Histogram& operator=(const Histogram& obj); + + // Data Members (m_ prefix) + Vector m_data; + int64 m_max; // the maximum value seen so far + int64 m_count; // the number of elements added + int m_binsize; // the size of each bucket + int m_bins; // the number of buckets + int m_largest_bin; // the largest bin used + + int64 m_sumSamples; // the sum of all samples + int64 m_sumSquaredSamples; // the sum of the square of all samples + + double getStandardDeviation() const; +}; + +bool node_less_then_eq(const Histogram* n1, const Histogram* n2); + +// Output operator declaration +ostream& operator<<(ostream& out, const Histogram& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const Histogram& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //HISTOGRAM_H diff --git a/src/mem/ruby/common/Message.cc b/src/mem/ruby/common/Message.cc new file mode 100644 index 000000000..baad8ac9b --- /dev/null +++ b/src/mem/ruby/common/Message.cc @@ -0,0 +1,34 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "Message.hh" diff --git a/src/mem/ruby/common/NetDest.cc b/src/mem/ruby/common/NetDest.cc new file mode 100644 index 000000000..79a6078e9 --- /dev/null +++ b/src/mem/ruby/common/NetDest.cc @@ -0,0 +1,259 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * NetDest.C + * + * Description: See NetDest.h + * + * $Id$ + * + */ + +#include "NetDest.hh" +#include "RubyConfig.hh" +#include "Protocol.hh" + +NetDest::NetDest() +{ + setSize(); +} + +void NetDest::add(MachineID newElement) +{ + m_bits[vecIndex(newElement)].add(bitIndex(newElement.num)); +} + +void NetDest::addNetDest(const NetDest& netDest) +{ + assert(m_bits.size() == netDest.getSize()); + for (int i = 0; i < m_bits.size(); i++) { + m_bits[i].addSet(netDest.m_bits[i]); + } +} + +void NetDest::addRandom() +{ + int i = random()%m_bits.size(); + m_bits[i].addRandom(); +} + +void NetDest::setNetDest(MachineType machine, const Set& set) +{ + // assure that there is only one set of destinations for this machine + assert(MachineType_base_level((MachineType)(machine+1)) - MachineType_base_level(machine) == 1); + m_bits[MachineType_base_level(machine)] = set; +} + +void NetDest::remove(MachineID oldElement) +{ + m_bits[vecIndex(oldElement)].remove(bitIndex(oldElement.num)); +} + +void NetDest::removeNetDest(const NetDest& netDest) +{ + assert(m_bits.size() == netDest.getSize()); + for (int i = 0; i < m_bits.size(); i++) { + m_bits[i].removeSet(netDest.m_bits[i]); + + } +} + +void NetDest::clear() +{ + for (int i = 0; i < m_bits.size(); i++) { + m_bits[i].clear(); + } +} + +void NetDest::broadcast() +{ + for (MachineType machine = MachineType_FIRST; machine < MachineType_NUM; ++machine) { + broadcast(machine); + } +} + +void NetDest::broadcast(MachineType machineType) { + + for (int i = 0; i < MachineType_base_count(machineType); i++) { + MachineID mach = {machineType, i}; + add(mach); + } +} + +//For Princeton Network +Vector NetDest::getAllDest() { + Vector dest; + dest.clear(); + for (int i=0; i 0); + for (int i=0; i getAllDest(); + + NodeID smallestElement() const; + MachineID smallestElement(MachineType machine) const; + + void setSize(); + int getSize() const { return m_bits.size(); } + + // get element for a index + NodeID elementAt(MachineID index); + + void print(ostream& out) const; + +private: + + // Private Methods + // returns a value >= MachineType_base_level("this machine") and < MachineType_base_level("next highest machine") + int vecIndex(MachineID m) const { + int vec_index = MachineType_base_level(m.type); + assert(vec_index < m_bits.size()); + return vec_index; + } + + NodeID bitIndex(NodeID index) const { + return index; + } + + // Data Members (m_ prefix) + Vector < Set > m_bits; // a Vector of bit vectors - i.e. Sets + +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const NetDest& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const NetDest& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //NETDEST_H + diff --git a/src/mem/ruby/common/OptBigSet.cc b/src/mem/ruby/common/OptBigSet.cc new file mode 100644 index 000000000..51214e936 --- /dev/null +++ b/src/mem/ruby/common/OptBigSet.cc @@ -0,0 +1,576 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Set.C + * + * Description: See Set.h + * + * $Id: BigSet.C 1.9 05/01/19 13:12:25-06:00 mikem@maya.cs.wisc.edu $ + * + */ + +// modified (rewritten) 05/20/05 by Dan Gibson to accomimdate FASTER >32 bit +// set sizes + +#include "Set.hh" +#include "RubyConfig.hh" + +#if __amd64__ || __LP64__ +#define __64BITS__ +#else +#define __32BITS__ +#endif + +Set::Set() +{ + m_p_nArray = NULL; + setSize(RubyConfig::numberOfProcessors()); +} + +// copy constructor +Set::Set(const Set& obj) { + m_p_nArray = NULL; + setSize(obj.m_nSize); + + // copy from the host to this array + for(int i=0; i0); + setSize(size); +} + +Set::~Set() { + if( (m_p_nArray != (&m_p_nArray_Static[0])) && (m_p_nArray != NULL)) + delete [] m_p_nArray; + m_p_nArray = NULL; +} + + +// /* +// * This function should set the bit corresponding to index +// * to 1. +// */ + +// void Set::add(NodeID index) +// { +// assert(index= 0); + +// #ifdef __32BITS__ +// m_p_nArray[index>>5] |= (1 << (index & 0x01F)); +// #else +// m_p_nArray[index>>6] |= (((unsigned long) 1) << (index & 0x03F)); +// #endif // __32BITS__ + +// } + +/* + * This function should set all the bits in the current set + * that are already set in the parameter set + */ +void Set::addSet(const Set& set) +{ + assert(getSize()==set.getSize()); + for(int i=0; i> 1; + } + } +#else + long mask = 0x7FFFFFFFFFFFFFFF; + + // the number of populated spaces in the higest-order array slot is: + // m_nSize % 64, so the uppermost 64 - m_nSize%64 bits should be + // cleared + + if((m_nSize % 64) != 0) { + for(int j=0; j<64-(m_nSize&0x03F); j++) { + m_p_nArray[m_nArrayLen-1] &= mask; + mask = mask >> 1; + } + } +#endif // __32BITS__ + +} + +// /* +// * This function unsets the bit associated with index +// */ +// void Set::remove(NodeID index) +// { +// assert(index=0); + +// #ifdef __32BITS__ +// m_p_nArray[index>>5] &= ~(0x00000001 << (index & 0x01F)); +// #else +// m_p_nArray[index>>6] &= ~(((unsigned long) 0x0000000000000001) << (index & 0x03F)); +// #endif // __32BITS__ + +// } + + +/* + * This function clears bits that are =1 in the parameter set + */ +void Set::removeSet(const Set& set) +{ + + assert(m_nSize==set.m_nSize); + for(int i=0; i> 1; + } + } +#else + long mask = 0x7FFFFFFFFFFFFFFF; + + // the number of populated spaces in the higest-order array slot is: + // m_nSize % 64, so the uppermost 64 - m_nSize%64 bits should be + // cleared + + if((m_nSize % 64) != 0) { + for(int j=0; j<64-(m_nSize&0x03F); j++) { + m_p_nArray[m_nArrayLen-1] &= mask; + mask = mask >> 1; + } + } +#endif // __32BITS__ + +} + +/* + * This function returns the population count of 1's in the set + */ +int Set::count() const +{ + int counter = 0; + long mask; + for( int i=0; i 0); + long x; + for( int i=0; i> 1; + } +#else + for( int j=0; j<64; j++) { + if(x & 0x0000000000000001) { + return 64*i+j; + } + + x = x >> 1; + } +#endif // __32BITS__ + + ERROR_MSG("No smallest element of an empty set."); + } + } + + ERROR_MSG("No smallest element of an empty set."); + + return 0; +} + +/* + * this function returns true iff all bits are set + */ +bool Set::isBroadcast() const +{ + // check the fully-loaded words by equal to 0xffffffff + // only the last word may not be fully loaded, it is not + // fully loaded iff m_nSize % 32 or 64 !=0 => fully loaded iff + // m_nSize % 32 or 64 == 0 + +#ifdef __32BITS__ + for(int i=0; i< (((m_nSize % 32)==0) ? m_nArrayLen : m_nArrayLen-1); i++) { + if(m_p_nArray[i]!=-1) { + return false; + } + } + + // now check the last word, which may not be fully loaded + long mask = 1; + for(int j=0; j< (m_nSize % 32); j++) { + if((mask & m_p_nArray[m_nArrayLen-1])==0) { + return false; + } + mask = mask << 1; + } +#else + for(int i=0; i< (((m_nSize % 64)==0) ? m_nArrayLen : m_nArrayLen-1); i++) { + if(m_p_nArray[i]!=-1) { + return false; + } + } + + // now check the last word, which may not be fully loaded + long mask = 1; + for(int j=0; j< (m_nSize % 64); j++) { + if((mask & m_p_nArray[m_nArrayLen-1])==0) { + return false; + } + mask = mask << 1; + } + +#endif // __32BITS__ + + return true; +} + +/* + * this function returns true iff no bits are set + */ +bool Set::isEmpty() const +{ + + // here we can simply check if all = 0, since we ensure + // that "extra slots" are all zero + for(int i=0; i< m_nArrayLen ; i++) { + if(m_p_nArray[i]!=0) { + return false; + } + } + + return true; +} + +// returns the logical OR of "this" set and orSet +Set Set::OR(const Set& orSet) const +{ + Set result(m_nSize); + assert(m_nSize == orSet.m_nSize); + for(int i=0; i< m_nArrayLen; i++) { + result.m_p_nArray[i] = m_p_nArray[i] | orSet.m_p_nArray[i]; + } + + return result; + +} + +// returns the logical AND of "this" set and andSet +Set Set::AND(const Set& andSet) const +{ + Set result(m_nSize); + assert(m_nSize == andSet.m_nSize); + + for(int i=0; i< m_nArrayLen; i++) { + result.m_p_nArray[i] = m_p_nArray[i] & andSet.m_p_nArray[i]; + } + + return result; +} + +// // Returns true if the intersection of the two sets is non-empty +// bool Set::intersectionIsNotEmpty(const Set& other_set) const +// { +// assert(m_nSize == other_set.m_nSize); +// for(int i=0; i< m_nArrayLen; i++) { +// if(m_p_nArray[i] & other_set.m_p_nArray[i]) { +// return true; +// } +// } + +// return false; + +// } + +// // Returns true if the intersection of the two sets is empty +// bool Set::intersectionIsEmpty(const Set& other_set) const +// { +// assert(m_nSize == other_set.m_nSize); +// for(int i=0; i< m_nArrayLen; i++) { +// if(m_p_nArray[i] & other_set.m_p_nArray[i]) { +// return false; +// } +// } + +// return true; + +// } + +/* + * Returns false if a bit is set in the parameter set that is + * NOT set in this set + */ +bool Set::isSuperset(const Set& test) const +{ + assert(m_nSize == test.m_nSize); + + for(int i=0;i>5] & (0x00000001 << (element & 0x01F)))!=0); +// #else +// result = ((m_p_nArray[element>>6] & (((unsigned long) 0x0000000000000001) << (element & 0x03F)))!=0); +// #endif // __32BITS__ + +// return result; +// } + +/* + * "Supposed" to return the node id of the (n+1)th set + * bit, IE n=0 => returns nodeid of first set bit, BUT + * since BigSet.C behaves strangely, this implementation + * will behave strangely just for reverse compatability. + * + * Was originally implemented for the flight data recorder + * FDR + */ + +// NodeID Set::elementAt(int n) const +// { +// if(isElement(n)) return (NodeID) true; +// else return 0; + +// /* +// int match = -1; +// for(int i=0;i=0; i--) { +#ifdef __32BITS__ + sprintf(buff,"%08X ",m_p_nArray[i]); +#else + sprintf(buff,"0x %016llX ",m_p_nArray[i]); +#endif // __32BITS__ + out << buff; + } + out << " ]"; + +} + + diff --git a/src/mem/ruby/common/OptBigSet.hh b/src/mem/ruby/common/OptBigSet.hh new file mode 100644 index 000000000..a57a07e13 --- /dev/null +++ b/src/mem/ruby/common/OptBigSet.hh @@ -0,0 +1,202 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Set.h + * + * Description: + * + * $Id: BigSet.h 1.6 05/01/19 13:12:25-06:00 mikem@maya.cs.wisc.edu $ + * + */ + +// modified by Dan Gibson on 05/20/05 to accomidate FASTER +// >32 set lengths, using an array of ints w/ 32 bits/int + +// NOTE: Never include this file directly, this should only be +// included from Set.h + +#ifndef SET_H +#define SET_H + +#include "Global.hh" +#include "Vector.hh" +#include "NodeID.hh" +#include "RubyConfig.hh" + +// gibson 05/20/05 +// enum PresenceBit {NotPresent, Present}; + +class Set { +public: + // Constructors + // creates and empty set + Set(); + Set (int size); + + // used during the replay mechanism + // Set(const char *str); + + Set(const Set& obj); + Set& operator=(const Set& obj); + + // Destructor + ~Set(); + + // Public Methods + + inline void add(NodeID index) + { +#ifdef __32BITS__ + m_p_nArray[index>>5] |= (1 << (index & 0x01F)); +#else + m_p_nArray[index>>6] |= (((unsigned long) 1) << (index & 0x03F)); +#endif // __32BITS__ + } + + void addSet(const Set& set); + void addRandom(); + + inline void remove(NodeID index) + { +#ifdef __32BITS__ + m_p_nArray[index>>5] &= ~(0x00000001 << (index & 0x01F)); +#else + m_p_nArray[index>>6] &= ~(((unsigned long) 0x0000000000000001) << (index & 0x03F)); +#endif // __32BITS__ + } + + + void removeSet(const Set& set); + + inline void clear() { for(int i=0; i>5] & (0x00000001 << (element & 0x01F)))!=0); +#else + return ((m_p_nArray[element>>6] & (((unsigned long) 0x0000000000000001) << (element & 0x03F)))!=0); +#endif // __32BITS__ + + } + + bool isBroadcast() const; + bool isEmpty() const; + + NodeID smallestElement() const; + + // int size() const; + void setSize (int size); + + // get element for a index + inline NodeID elementAt(int index) const + { + if(isElement(index)) return (NodeID) true; + else return 0; + } + + // gibson 05/20/05 + int getSize() const { return m_nSize; } + + // DEPRECATED METHODS + void addToSet(NodeID newElement) { add(newElement); } // Deprecated + void removeFromSet(NodeID newElement) { remove(newElement); } // Deprecated + void clearSet() { clear(); } // Deprecated + void setBroadcast() { broadcast(); } // Deprecated + bool presentInSet(NodeID element) const { return isElement(element); } // Deprecated + + void print(ostream& out) const; +private: + // Private Methods + + // Data Members (m_ prefix) + // gibson 05/20/05 + // Vector m_bits; // This is an vector of uint8 to reduce the size of the set + + int m_nSize; // the number of bits in this set + int m_nArrayLen; // the number of 32-bit words that are held in the array + + // Changed 5/24/05 for static allocation of array + // note that "long" corresponds to 32 bits on a 32-bit machine, + // 64 bits if the -m64 parameter is passed to g++, which it is + // for an AMD opteron under our configuration + + long * m_p_nArray; // an word array to hold the bits in the set + long m_p_nArray_Static[NUMBER_WORDS_PER_SET]; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const Set& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const Set& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //SET_H + diff --git a/src/mem/ruby/common/Set.cc b/src/mem/ruby/common/Set.cc new file mode 100644 index 000000000..1f5b49f90 --- /dev/null +++ b/src/mem/ruby/common/Set.cc @@ -0,0 +1,231 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Set.C + * + * Description: See Set.h + * + * $Id$ + * + */ + +#include "Set.hh" +#include "RubyConfig.hh" + +#ifdef OPTBIGSET +#include "OptBigSet.cc" +#else + +#ifdef BIGSET +#include "BigSet.cc" // code to supports sets larger than 32 +#else + +Set::Set() +{ + setSize(RubyConfig::numberOfChips()); +} + +Set::Set(int size) +{ + setSize(size); +} + +bool Set::isEqual(const Set& set) +{ + return (m_bits == set.m_bits); +} + +void Set::add(NodeID index) +{ + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range + assert(index < m_size); + m_bits |= (1 << index); + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range +} + +void Set::addSet(const Set& set) +{ + assert(m_size == set.m_size); + m_bits |= set.m_bits; + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range +} + +void Set::addRandom() +{ + m_bits |= random(); + m_bits &= m_mask; + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range +} + +void Set::remove(NodeID index) +{ + assert(index < m_size); + m_bits &= ~(1 << index); + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range +} + +void Set::removeSet(const Set& set) +{ + assert(m_size == set.m_size); + m_bits &= ~(set.m_bits); + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range +} + +void Set::clear() +{ + m_bits = 0; +} + +void Set::broadcast() +{ + m_bits = m_mask; +} + +int Set::count() const +{ + int counter = 0; + for (int i=0; i 0); + int counter = 0; + for (int i=0; i 0); + int offset = m_address.getOffset(); + for(int i=0; isetByte(i, data.getByte(offset+i)); + } +} + +void SubBlock::internalMergeTo(DataBlock& data) const +{ + int size = getSize(); + assert(size > 0); + int offset = m_address.getOffset(); + for(int i=0; igetByte(i)); // This will detect crossing a cache line boundary + } +} + +void SubBlock::print(ostream& out) const +{ + out << "[" << m_address << ", " << getSize() << ", " << m_data << "]"; +} + + + diff --git a/src/mem/ruby/common/SubBlock.hh b/src/mem/ruby/common/SubBlock.hh new file mode 100644 index 000000000..43f91e191 --- /dev/null +++ b/src/mem/ruby/common/SubBlock.hh @@ -0,0 +1,105 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + */ + +#ifndef SubBlock_H +#define SubBlock_H + +#include "Global.hh" +#include "Address.hh" +#include "RubyConfig.hh" +#include "DataBlock.hh" +#include "Vector.hh" + +class SubBlock { +public: + // Constructors + SubBlock() { } + SubBlock(const Address& addr, int size); + SubBlock(const Address& addr, const Address& logicalAddress, int size); + + // Destructor + ~SubBlock() { } + + // Public Methods + const Address& getAddress() const { return m_address; } + const Address& getLogicalAddress() const { return m_logicalAddress; } + void setAddress(const Address& addr) { m_address = addr; } + void setLogicalAddress(const Address& addr) { m_logicalAddress = addr; } + + int getSize() const { return m_data.size(); } + void setSize(int size) { m_data.setSize(size); } + uint8 getByte(int offset) const { return m_data[offset]; } + void setByte(int offset, uint8 data) { m_data[offset] = data; } + + // Shorthands + uint8 readByte() const { return getByte(0); } + void writeByte(uint8 data) { setByte(0, data); } + + // Merging to and from DataBlocks - We only need to worry about + // updates when we are using DataBlocks + void mergeTo(DataBlock& data) const { if (DATA_BLOCK) { internalMergeTo(data); } } + void mergeFrom(const DataBlock& data) { if (DATA_BLOCK) { internalMergeFrom(data); } } + + void print(ostream& out) const; +private: + // Private Methods + // SubBlock(const SubBlock& obj); + // SubBlock& operator=(const SubBlock& obj); + // bool bytePresent(const Address& addr) { return ((addr.getAddress() >= m_address.getAddress()) && (addr.getAddress() < (m_address.getAddress()+getSize()))); } + // uint8 getByte(const Address& addr) { return m_data[addr.getAddress() - m_address.getAddress()]; } + + void internalMergeTo(DataBlock& data) const; + void internalMergeFrom(const DataBlock& data); + + // Data Members (m_ prefix) + Address m_address; + Address m_logicalAddress; + Vector m_data; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const SubBlock& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const SubBlock& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //SubBlock_H diff --git a/src/mem/ruby/config/RubyConfig.cc b/src/mem/ruby/config/RubyConfig.cc new file mode 100644 index 000000000..fe4e3be8f --- /dev/null +++ b/src/mem/ruby/config/RubyConfig.cc @@ -0,0 +1,193 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * RubyConfig.C + * + * Description: See RubyConfig.h + * + * $Id$ + * + */ + +#include "RubyConfig.hh" +#include "protocol_name.hh" +#include "util.hh" +#include "interface.hh" +#include "Protocol.hh" + +#define CHECK_POWER_OF_2(N) { if (!is_power_of_2(N)) { ERROR_MSG(#N " must be a power of 2."); }} +#define CHECK_ZERO(N) { if (N != 0) { ERROR_MSG(#N " must be zero at initialization."); }} +#define CHECK_NON_ZERO(N) { if (N == 0) { ERROR_MSG(#N " must be non-zero."); }} + + +void RubyConfig::init() +{ + // MemoryControl: + CHECK_NON_ZERO(MEM_BUS_CYCLE_MULTIPLIER); + CHECK_NON_ZERO(BANKS_PER_RANK); + CHECK_NON_ZERO(RANKS_PER_DIMM); + CHECK_NON_ZERO(DIMMS_PER_CHANNEL); + CHECK_NON_ZERO(BANK_QUEUE_SIZE); + CHECK_NON_ZERO(BANK_BUSY_TIME); + CHECK_NON_ZERO(MEM_CTL_LATENCY); + CHECK_NON_ZERO(REFRESH_PERIOD); + CHECK_NON_ZERO(BASIC_BUS_BUSY_TIME); + + CHECK_POWER_OF_2(BANKS_PER_RANK); + CHECK_POWER_OF_2(RANKS_PER_DIMM); + CHECK_POWER_OF_2(DIMMS_PER_CHANNEL); + + CHECK_NON_ZERO(g_MEMORY_SIZE_BYTES); + CHECK_NON_ZERO(g_DATA_BLOCK_BYTES); + CHECK_NON_ZERO(g_PAGE_SIZE_BYTES); + CHECK_NON_ZERO(g_NUM_PROCESSORS); + CHECK_NON_ZERO(g_PROCS_PER_CHIP); + if(g_NUM_SMT_THREADS == 0){ //defaults to single-threaded + g_NUM_SMT_THREADS = 1; + } + if (g_NUM_L2_BANKS == 0) { // defaults to number of ruby nodes + g_NUM_L2_BANKS = g_NUM_PROCESSORS; + } + if (g_NUM_MEMORIES == 0) { // defaults to number of ruby nodes + g_NUM_MEMORIES = g_NUM_PROCESSORS; + } + + CHECK_ZERO(g_MEMORY_SIZE_BITS); + CHECK_ZERO(g_DATA_BLOCK_BITS); + CHECK_ZERO(g_PAGE_SIZE_BITS); + CHECK_ZERO(g_NUM_PROCESSORS_BITS); + CHECK_ZERO(g_NUM_CHIP_BITS); + CHECK_ZERO(g_NUM_L2_BANKS_BITS); + CHECK_ZERO(g_NUM_MEMORIES_BITS); + CHECK_ZERO(g_PROCS_PER_CHIP_BITS); + CHECK_ZERO(g_NUM_L2_BANKS_PER_CHIP); + CHECK_ZERO(g_NUM_L2_BANKS_PER_CHIP_BITS); + CHECK_ZERO(g_NUM_MEMORIES_BITS); + CHECK_ZERO(g_MEMORY_MODULE_BLOCKS); + CHECK_ZERO(g_MEMORY_MODULE_BITS); + CHECK_ZERO(g_NUM_MEMORIES_PER_CHIP); + + CHECK_POWER_OF_2(g_MEMORY_SIZE_BYTES); + CHECK_POWER_OF_2(g_DATA_BLOCK_BYTES); + CHECK_POWER_OF_2(g_NUM_PROCESSORS); + CHECK_POWER_OF_2(g_NUM_L2_BANKS); + CHECK_POWER_OF_2(g_NUM_MEMORIES); + CHECK_POWER_OF_2(g_PROCS_PER_CHIP); + + ASSERT(g_NUM_PROCESSORS >= g_PROCS_PER_CHIP); // obviously can't have less processors than procs/chip + g_NUM_CHIPS = g_NUM_PROCESSORS/g_PROCS_PER_CHIP; + ASSERT(g_NUM_L2_BANKS >= g_NUM_CHIPS); // cannot have a single L2cache across multiple chips + + g_NUM_L2_BANKS_PER_CHIP = g_NUM_L2_BANKS/g_NUM_CHIPS; + + ASSERT(L2_CACHE_NUM_SETS_BITS > log_int(g_NUM_L2_BANKS_PER_CHIP)); // cannot have less than one set per bank + L2_CACHE_NUM_SETS_BITS = L2_CACHE_NUM_SETS_BITS - log_int(g_NUM_L2_BANKS_PER_CHIP); + + if (g_NUM_CHIPS > g_NUM_MEMORIES) { + g_NUM_MEMORIES_PER_CHIP = 1; // some chips have a memory, others don't + } else { + g_NUM_MEMORIES_PER_CHIP = g_NUM_MEMORIES/g_NUM_CHIPS; + } + + g_NUM_CHIP_BITS = log_int(g_NUM_CHIPS); + g_MEMORY_SIZE_BITS = log_int(g_MEMORY_SIZE_BYTES); + g_DATA_BLOCK_BITS = log_int(g_DATA_BLOCK_BYTES); + g_PAGE_SIZE_BITS = log_int(g_PAGE_SIZE_BYTES); + g_NUM_PROCESSORS_BITS = log_int(g_NUM_PROCESSORS); + g_NUM_L2_BANKS_BITS = log_int(g_NUM_L2_BANKS); + g_NUM_L2_BANKS_PER_CHIP_BITS = log_int(g_NUM_L2_BANKS_PER_CHIP); + g_NUM_MEMORIES_BITS = log_int(g_NUM_MEMORIES); + g_PROCS_PER_CHIP_BITS = log_int(g_PROCS_PER_CHIP); + + g_MEMORY_MODULE_BITS = g_MEMORY_SIZE_BITS - g_DATA_BLOCK_BITS - g_NUM_MEMORIES_BITS; + g_MEMORY_MODULE_BLOCKS = (int64(1) << g_MEMORY_MODULE_BITS); + + if ((!Protocol::m_CMP) && (g_PROCS_PER_CHIP > 1)) { + ERROR_MSG("Non-CMP protocol should set g_PROCS_PER_CHIP to 1"); + } + + // Randomize the execution + srandom(g_RANDOM_SEED); +} + +int RubyConfig::L1CacheNumToL2Base(NodeID L1CacheNum) +{ + return L1CacheNum/g_PROCS_PER_CHIP; +} + +static void print_parameters(ostream& out) +{ + +#define PARAM(NAME) { out << #NAME << ": " << NAME << endl; } +#define PARAM_UINT(NAME) { out << #NAME << ": " << NAME << endl; } +#define PARAM_ULONG(NAME) { out << #NAME << ": " << NAME << endl; } +#define PARAM_BOOL(NAME) { out << #NAME << ": " << bool_to_string(NAME) << endl; } +#define PARAM_DOUBLE(NAME) { out << #NAME << ": " << NAME << endl; } +#define PARAM_STRING(NAME) { assert(NAME != NULL); out << #NAME << ": " << string(NAME) << endl; } +#define PARAM_ARRAY(PTYPE, NAME, ARRAY_SIZE) \ + { \ + out << #NAME << ": ("; \ + for (int i = 0; i < ARRAY_SIZE; i++) { \ + if (i != 0) { \ + out << ", "; \ + } \ + out << NAME[i]; \ + } \ + out << ")" << endl; \ + } \ + + +#include CONFIG_VAR_FILENAME +#undef PARAM +#undef PARAM_UINT +#undef PARAM_ULONG +#undef PARAM_BOOL +#undef PARAM_DOUBLE +#undef PARAM_STRING +#undef PARAM_ARRAY +} + +void RubyConfig::printConfiguration(ostream& out) { + out << "Ruby Configuration" << endl; + out << "------------------" << endl; + + out << "protocol: " << CURRENT_PROTOCOL << endl; + SIMICS_print_version(out); + out << "compiled_at: " << __TIME__ << ", " << __DATE__ << endl; + out << "RUBY_DEBUG: " << bool_to_string(RUBY_DEBUG) << endl; + + char buffer[100]; + gethostname(buffer, 50); + out << "hostname: " << buffer << endl; + + print_parameters(out); +} + + diff --git a/src/mem/ruby/config/RubyConfig.hh b/src/mem/ruby/config/RubyConfig.hh new file mode 100644 index 000000000..b2cc745bc --- /dev/null +++ b/src/mem/ruby/config/RubyConfig.hh @@ -0,0 +1,157 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * RubyConfig.h + * + * Description: This class has only static members and class methods, + * and thus should never need to be instantiated. + * + * $Id$ + * + */ + +#ifndef RUBYCONFIG_H +#define RUBYCONFIG_H + +#include "Global.hh" +#define CONFIG_VAR_FILENAME "config.include" +#include "vardecl.hh" +#include "NodeID.hh" + +#define MEMORY_LATENCY RubyConfig::memoryResponseLatency() +#define ABORT_DELAY m_chip_ptr->getTransactionManager(m_version)->getAbortDelay() + +// Set paramterization +/* + * This defines the number of longs (32-bits on 32 bit machines, + * 64-bit on 64-bit AMD machines) to use to hold the set... + * the default is 4, allowing 128 or 256 different members + * of the set. + * + * This should never need to be changed for correctness reasons, + * though increasing it will increase performance for larger + * set sizes at the cost of a (much) larger memory footprint + * + */ +const int NUMBER_WORDS_PER_SET = 4; + +class RubyConfig { +public: + + // CACHE BLOCK CONFIG VARIBLES + static int dataBlockBits() { return g_DATA_BLOCK_BITS; } + static int dataBlockBytes() { return g_DATA_BLOCK_BYTES; } + + // SUPPORTED PHYSICAL MEMORY CONFIG VARIABLES + static int pageSizeBits() { return g_PAGE_SIZE_BITS; } + static int pageSizeBytes() { return g_PAGE_SIZE_BYTES; } + static int memorySizeBits() { return g_MEMORY_SIZE_BITS; } + static int64 memorySizeBytes() { return g_MEMORY_SIZE_BYTES; } + static int memoryModuleBits() { return g_MEMORY_MODULE_BITS; } + static int64 memoryModuleBlocks() { return g_MEMORY_MODULE_BLOCKS; } + + // returns number of SMT threads per physical processor + static int numberofSMTThreads() { return g_NUM_SMT_THREADS; } + // defines the number of simics processors (power of 2) + static int numberOfProcessors() { return g_NUM_PROCESSORS; } + static int procsPerChipBits() { return g_PROCS_PER_CHIP_BITS; } + static int numberOfProcsPerChip() { return g_PROCS_PER_CHIP; } + static int numberOfChips() { return g_NUM_CHIPS; } + + // MACHINE INSTANIATION CONFIG VARIABLES + // ------------------------------------- + // L1 CACHE MACHINES + // defines the number of L1banks - idependent of ruby chips (power of 2) + // NOTE - no protocols currently supports L1s != processors, just a placeholder + static int L1CacheBits() { return g_NUM_PROCESSORS_BITS; } + static int numberOfL1Cache() { return g_NUM_PROCESSORS; } + static int L1CachePerChipBits() { return procsPerChipBits() ; } // L1s != processors not currently supported + static int numberOfL1CachePerChip() { return numberOfProcsPerChip(); } // L1s != processors not currently supported + static int numberOfL1CachePerChip(NodeID myNodeID) { return numberOfL1CachePerChip(); } + static int L1CacheTransitionsPerCycle() { return L1CACHE_TRANSITIONS_PER_RUBY_CYCLE; } + + // L2 CACHE MACHINES + // defines the number of L2banks/L2Caches - idependent of ruby chips (power of 2) + static int L2CacheBits() { return g_NUM_L2_BANKS_BITS; } + static int numberOfL2Cache() { return g_NUM_L2_BANKS; } + static int L1CacheNumToL2Base(NodeID L1RubyNodeID); + static int L2CachePerChipBits() { return g_NUM_L2_BANKS_PER_CHIP_BITS; } + static int numberOfL2CachePerChip() { return g_NUM_L2_BANKS_PER_CHIP; } + static int numberOfL2CachePerChip(NodeID myNodeID) { return numberOfL2CachePerChip(); } + static int L2CacheTransitionsPerCycle() { return L2CACHE_TRANSITIONS_PER_RUBY_CYCLE; } + + // DIRECTORY/MEMORY MACHINES + // defines the number of ruby memories - idependent of ruby chips (power of 2) + static int memoryBits() { return g_NUM_MEMORIES_BITS; } + static int numberOfDirectory() { return numberOfMemories(); } + static int numberOfMemories() { return g_NUM_MEMORIES; } + static int numberOfDirectoryPerChip() { return g_NUM_MEMORIES_PER_CHIP; } + static int numberOfDirectoryPerChip(NodeID myNodeID) { return g_NUM_MEMORIES_PER_CHIP; } + static int DirectoryTransitionsPerCycle() { return DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE; } + + // PERSISTENT ARBITER MACHINES + static int numberOfPersistentArbiter() { return numberOfMemories(); } + static int numberOfPersistentArbiterPerChip() {return numberOfDirectoryPerChip(); } + static int numberOfPersistentArbiterPerChip(NodeID myNodeID) {return numberOfDirectoryPerChip(myNodeID); } + static int PersistentArbiterTransitionsPerCycle() { return L2CACHE_TRANSITIONS_PER_RUBY_CYCLE; } + + // ---- END MACHINE SPECIFIC VARIABLES ---- + + // VARIABLE MEMORY RESPONSE LATENCY + // *** NOTE *** This is where variation is added to the simulation + // see Alameldeen et al. HPCA 2003 for further details + static int memoryResponseLatency() { return MEMORY_RESPONSE_LATENCY_MINUS_2+(random() % 5); } + + static void init(); + static void printConfiguration(ostream& out); + + // Memory Controller + static int memBusCycleMultiplier () { return MEM_BUS_CYCLE_MULTIPLIER; } + static int banksPerRank () { return BANKS_PER_RANK; } + static int ranksPerDimm () { return RANKS_PER_DIMM; } + static int dimmsPerChannel () { return DIMMS_PER_CHANNEL; } + static int bankBit0 () { return BANK_BIT_0; } + static int rankBit0 () { return RANK_BIT_0; } + static int dimmBit0 () { return DIMM_BIT_0; } + static int bankQueueSize () { return BANK_QUEUE_SIZE; } + static int bankBusyTime () { return BANK_BUSY_TIME; } + static int rankRankDelay () { return RANK_RANK_DELAY; } + static int readWriteDelay () { return READ_WRITE_DELAY; } + static int basicBusBusyTime () { return BASIC_BUS_BUSY_TIME; } + static int memCtlLatency () { return MEM_CTL_LATENCY; } + static int refreshPeriod () { return REFRESH_PERIOD; } + static int tFaw () { return TFAW; } + static int memRandomArbitrate () { return MEM_RANDOM_ARBITRATE; } + static int memFixedDelay () { return MEM_FIXED_DELAY; } + +private: +}; + +#endif //RUBYCONFIG_H diff --git a/src/mem/ruby/config/config.include b/src/mem/ruby/config/config.include new file mode 100644 index 000000000..f853fb72b --- /dev/null +++ b/src/mem/ruby/config/config.include @@ -0,0 +1,323 @@ +// +// This file has been modified by Kevin Moore and Dan Nussbaum of the +// Scalable Systems Research Group at Sun Microsystems Laboratories +// (http://research.sun.com/scalable/) to support the Adaptive +// Transactional Memory Test Platform (ATMTP). For information about +// ATMTP, see the GEMS website: http://www.cs.wisc.edu/gems/. +// +// Please send email to atmtp-interest@sun.com with feedback, questions, or +// to request future announcements about ATMTP. +// +// ---------------------------------------------------------------------- +// +// File modification date: 2008-02-23 +// +// ---------------------------------------------------------------------- +// +// ATMTP is distributed as part of the GEMS software toolset and is +// available for use and modification under the terms of version 2 of the +// GNU General Public License. The GNU General Public License is contained +// in the file $GEMS/LICENSE. +// +// Multifacet GEMS is free software; you can redistribute it and/or modify +// it under the terms of version 2 of the GNU General Public License as +// published by the Free Software Foundation. +// +// Multifacet GEMS is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with the Multifacet GEMS; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA +// +// ---------------------------------------------------------------------- +// + +// see rubyconfig.defaults for some explanations + +PARAM( g_RANDOM_SEED ); + +// Maximum number of cycles a request is can be outstanding before the +// Sequencer of StoreBuffer declares we're in deadlock/livelock +PARAM( g_DEADLOCK_THRESHOLD ); +PARAM_BOOL( RANDOMIZATION ); +PARAM_BOOL( g_SYNTHETIC_DRIVER ); +PARAM_BOOL( g_DETERMINISTIC_DRIVER ); + +// FOR MOESI_CMP_token +PARAM_BOOL( g_FILTERING_ENABLED ); +PARAM_BOOL( g_DISTRIBUTED_PERSISTENT_ENABLED ); +PARAM_BOOL( g_DYNAMIC_TIMEOUT_ENABLED ); +PARAM( g_RETRY_THRESHOLD ); +PARAM( g_FIXED_TIMEOUT_LATENCY ); + +PARAM( g_trace_warmup_length ); +PARAM_DOUBLE( g_bash_bandwidth_adaptive_threshold ); + +PARAM( g_tester_length ); +PARAM( g_synthetic_locks ); +PARAM( g_deterministic_addrs ); +// Specified Generator: See SpecifiedGeneratorType in external.sm for valid values +PARAM_STRING( g_SpecifiedGenerator ); +PARAM( g_callback_counter ); +PARAM( g_NUM_COMPLETIONS_BEFORE_PASS ); + +PARAM( g_NUM_SMT_THREADS ); + +PARAM( g_think_time ); +PARAM( g_hold_time ); +PARAM( g_wait_time ); + +// For debugging purposes, one can enable a trace of all the protocol +// state machine changes. Unfortunately, the code to generate the +// trace is protocol specific. To enable the code for some of the +// standard protocols, +// 1. change "PROTOCOL_DEBUG_TRACE = true" +// 2. enable debug in Makefile +// 3. use the "--start 1" command line parameter or +// "g_debug_ptr->setDebugTime(1)" to beging the following to set the +// debug begin time +// +// this use to be ruby/common/Global.h + +PARAM_BOOL( PROTOCOL_DEBUG_TRACE ); +// a string for filtering debugging output (for all g_debug vars see Debug.h) +PARAM_STRING( DEBUG_FILTER_STRING ); +// filters debugging messages based on priority (low, med, high) +PARAM_STRING( DEBUG_VERBOSITY_STRING ); +// filters debugging messages based on a ruby time +PARAM_ULONG( DEBUG_START_TIME ); +// sends debugging messages to a output filename +PARAM_STRING( DEBUG_OUTPUT_FILENAME ); + +// defines relative (integer) clock multipliers between ruby, opal, and simics +PARAM( SIMICS_RUBY_MULTIPLIER ); +PARAM( OPAL_RUBY_MULTIPLIER ); + +PARAM_BOOL( TRANSACTION_TRACE_ENABLED ); +PARAM_BOOL( USER_MODE_DATA_ONLY ); +PARAM_BOOL( PROFILE_HOT_LINES ); + +// PROFILE_ALL_INSTRUCTIONS is used if you want Ruby to profile all instructions executed +// The following need to be true for this to work correctly: +// 1. Disable istc and dstc for this simulation run +// 2. Add the following line to the object "sim" in the checkpoint you run from: +// instruction_profile_line_size: 4 +// This is used to have simics report back all instruction requests + +// For more details on how to find out how to interpret the output physical instruction +// address, please read the document in the simics-howto directory +PARAM_BOOL( PROFILE_ALL_INSTRUCTIONS ); + +// Set the following variable to true if you want a complete trace of +// PCs (physical address of program counters, with executing processor IDs) +// to be printed to stdout. Make sure to direct the simics output to a file. +// Otherwise, the run will take a really long time! +// A long run may write a file that can exceed the OS limit on file length +PARAM_BOOL( PRINT_INSTRUCTION_TRACE ); +PARAM( g_DEBUG_CYCLE ); + +// Don't allow any datablocks to enter the STC +PARAM_BOOL( BLOCK_STC ); + +// Make the entire memory system perfect +PARAM_BOOL( PERFECT_MEMORY_SYSTEM ); +PARAM( PERFECT_MEMORY_SYSTEM_LATENCY ); + +PARAM_BOOL( DATA_BLOCK ); // Define NO_DATA_BLOCK to make the DataBlock take zero space + +PARAM_BOOL( REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH ); + +// ********************************************* +// CACHE & MEMORY PARAMETERS +// ********************************************* + +PARAM_BOOL( g_SIMICS ); + +PARAM( L1_CACHE_ASSOC ); +PARAM( L1_CACHE_NUM_SETS_BITS ); +PARAM( L2_CACHE_ASSOC ); +PARAM( L2_CACHE_NUM_SETS_BITS ); + +PARAM_ULONG( g_MEMORY_SIZE_BYTES ); +PARAM( g_DATA_BLOCK_BYTES ); +// The following page size parameter is used by the stride prefetcher +PARAM( g_PAGE_SIZE_BYTES ); +PARAM_STRING( g_REPLACEMENT_POLICY ); + +PARAM( g_NUM_PROCESSORS ); +PARAM( g_NUM_L2_BANKS ); +PARAM( g_NUM_MEMORIES ); +PARAM( g_PROCS_PER_CHIP ); + +// The following group of parameters are calculated. They must +// _always_ be left at zero. +PARAM( g_NUM_CHIPS ); +PARAM( g_NUM_CHIP_BITS ); +PARAM( g_MEMORY_SIZE_BITS ); +PARAM( g_DATA_BLOCK_BITS ); +PARAM( g_PAGE_SIZE_BITS ); +PARAM( g_NUM_PROCESSORS_BITS ); +PARAM( g_PROCS_PER_CHIP_BITS ); +PARAM( g_NUM_L2_BANKS_BITS ); +PARAM( g_NUM_L2_BANKS_PER_CHIP_BITS ); +PARAM( g_NUM_L2_BANKS_PER_CHIP ); +PARAM( g_NUM_MEMORIES_BITS ); +PARAM( g_NUM_MEMORIES_PER_CHIP ); +PARAM( g_MEMORY_MODULE_BITS ); +PARAM_ULONG( g_MEMORY_MODULE_BLOCKS ); + +// determines the mapping between L2 banks and sets within L2 banks +PARAM_BOOL( MAP_L2BANKS_TO_LOWEST_BITS ); + +// TIMING PARAMETERS +PARAM( DIRECTORY_CACHE_LATENCY ); + +PARAM( NULL_LATENCY ); +PARAM( ISSUE_LATENCY ); +PARAM( CACHE_RESPONSE_LATENCY ); +PARAM( L2_RESPONSE_LATENCY ); +PARAM( L2_TAG_LATENCY ); +PARAM( L1_RESPONSE_LATENCY ); +PARAM( MEMORY_RESPONSE_LATENCY_MINUS_2 ); +PARAM( DIRECTORY_LATENCY ); +PARAM( NETWORK_LINK_LATENCY ); +PARAM( COPY_HEAD_LATENCY ); +PARAM( ON_CHIP_LINK_LATENCY ); +PARAM( RECYCLE_LATENCY ); +PARAM( L2_RECYCLE_LATENCY ); +PARAM( TIMER_LATENCY ); +PARAM( TBE_RESPONSE_LATENCY ); +PARAM_BOOL( PERIODIC_TIMER_WAKEUPS ); + +// constants used by TM protocols +PARAM_BOOL( PROFILE_EXCEPTIONS ); +PARAM_BOOL( PROFILE_XACT ); +PARAM_BOOL( PROFILE_NONXACT ); +PARAM_BOOL( XACT_DEBUG ); +PARAM ( XACT_DEBUG_LEVEL ); +PARAM_BOOL( XACT_MEMORY ); +PARAM_BOOL( XACT_ENABLE_TOURMALINE ); +PARAM( XACT_NUM_CURRENT ); +PARAM( XACT_LAST_UPDATE ); +PARAM_BOOL( XACT_ISOLATION_CHECK ); +PARAM_BOOL( PERFECT_FILTER ); +PARAM_STRING( READ_WRITE_FILTER ); +PARAM_BOOL( PERFECT_VIRTUAL_FILTER ); +PARAM_STRING( VIRTUAL_READ_WRITE_FILTER ); +PARAM_BOOL( PERFECT_SUMMARY_FILTER ); +PARAM_STRING( SUMMARY_READ_WRITE_FILTER ); +PARAM_BOOL( XACT_EAGER_CD ); +PARAM_BOOL( XACT_LAZY_VM ); +PARAM_STRING( XACT_CONFLICT_RES ); +PARAM_BOOL( XACT_VISUALIZER ); +PARAM( XACT_COMMIT_TOKEN_LATENCY ) ; +PARAM_BOOL( XACT_NO_BACKOFF ); +PARAM ( XACT_LOG_BUFFER_SIZE ); +PARAM ( XACT_STORE_PREDICTOR_HISTORY); +PARAM ( XACT_STORE_PREDICTOR_ENTRIES); +PARAM ( XACT_STORE_PREDICTOR_THRESHOLD); +PARAM ( XACT_FIRST_ACCESS_COST ); +PARAM ( XACT_FIRST_PAGE_ACCESS_COST ); +PARAM_BOOL( ENABLE_MAGIC_WAITING ); +PARAM_BOOL( ENABLE_WATCHPOINT ); +PARAM_BOOL( XACT_ENABLE_VIRTUALIZATION_LOGTM_SE ); + +// ATMTP +PARAM_BOOL( ATMTP_ENABLED ); +PARAM_BOOL( ATMTP_ABORT_ON_NON_XACT_INST ); +PARAM_BOOL( ATMTP_ALLOW_SAVE_RESTORE_IN_XACT ); +PARAM( ATMTP_XACT_MAX_STORES ); +PARAM( ATMTP_DEBUG_LEVEL ); + +// constants used by CMP protocols +PARAM( L1_REQUEST_LATENCY ); +PARAM( L2_REQUEST_LATENCY ); +PARAM_BOOL( SINGLE_ACCESS_L2_BANKS ); // hack to simulate multi-cycle L2 bank accesses + +// Ruby cycles between when a sequencer issues a miss it arrives at +// the L1 cache controller +PARAM( SEQUENCER_TO_CONTROLLER_LATENCY ); + +// Number of transitions each controller state machines can complete per cycle +PARAM( L1CACHE_TRANSITIONS_PER_RUBY_CYCLE ); +PARAM( L2CACHE_TRANSITIONS_PER_RUBY_CYCLE ); +PARAM( DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE ); + +// Maximum number of requests (including prefetches) outstanding from +// the sequencer (Note: this also include items buffered in the store +// buffer) +PARAM( g_SEQUENCER_OUTSTANDING_REQUESTS ); + +// Number of TBEs available for demand misses, prefetches, and replacements +PARAM( NUMBER_OF_TBES ); +PARAM( NUMBER_OF_L1_TBES ); +PARAM( NUMBER_OF_L2_TBES ); + +// NOTE: Finite buffering allows us to simulate a wormhole routed network +// with idealized flow control. All message buffers within the network (i.e. +// the switch's input and output buffers) are set to the size specified below +// by the PROTOCOL_BUFFER_SIZE +PARAM_BOOL( FINITE_BUFFERING ); +PARAM( FINITE_BUFFER_SIZE ); // Zero is unbounded buffers +// Number of requests buffered between the sequencer and the L1 conroller +// This can be more accurately simulated in Opal, therefore it's set to an +// infinite number +// Only effects the simualtion when FINITE_BUFFERING is enabled +PARAM( PROCESSOR_BUFFER_SIZE ); +// The PROTOCOL_BUFFER_SIZE limits the size of all other buffers connecting to +// Controllers. Controlls the number of request issued by the L2 HW Prefetcher +PARAM( PROTOCOL_BUFFER_SIZE ); + +// Enable the TSO (Total Store Order) memory model +PARAM_BOOL( TSO ); // Note: This also disables the "write" STCs + +// NETWORK PARAMETERS + +// Network Topology: See TopologyType in external.sm for valid values +PARAM_STRING( g_NETWORK_TOPOLOGY ); + +// Cache Design specifies file prefix for topology +PARAM_STRING( g_CACHE_DESIGN ); + +PARAM( g_endpoint_bandwidth ); +PARAM_BOOL( g_adaptive_routing ); +PARAM( NUMBER_OF_VIRTUAL_NETWORKS ); +PARAM( FAN_OUT_DEGREE ); +PARAM_BOOL( g_PRINT_TOPOLOGY ); + +// transactional memory +PARAM( XACT_LENGTH ); +PARAM( XACT_SIZE ); +PARAM( ABORT_RETRY_TIME ); + +// Princeton Network (Garnet) +PARAM_BOOL( g_GARNET_NETWORK ); +PARAM_BOOL( g_DETAIL_NETWORK ); +PARAM_BOOL( g_NETWORK_TESTING ); +PARAM( g_FLIT_SIZE ); +PARAM( g_NUM_PIPE_STAGES ); +PARAM( g_VCS_PER_CLASS ); +PARAM( g_BUFFER_SIZE ); + +// MemoryControl: +PARAM( MEM_BUS_CYCLE_MULTIPLIER ); +PARAM( BANKS_PER_RANK ); +PARAM( RANKS_PER_DIMM ); +PARAM( DIMMS_PER_CHANNEL ); +PARAM( BANK_BIT_0 ); +PARAM( RANK_BIT_0 ); +PARAM( DIMM_BIT_0 ); +PARAM( BANK_QUEUE_SIZE ); +PARAM( BANK_BUSY_TIME ); +PARAM( RANK_RANK_DELAY ); +PARAM( READ_WRITE_DELAY ); +PARAM( BASIC_BUS_BUSY_TIME ); +PARAM( MEM_CTL_LATENCY ); +PARAM( REFRESH_PERIOD ); +PARAM( TFAW ); +PARAM( MEM_RANDOM_ARBITRATE ); +PARAM( MEM_FIXED_DELAY ); + diff --git a/src/mem/ruby/config/rubyconfig.defaults b/src/mem/ruby/config/rubyconfig.defaults new file mode 100644 index 000000000..3b86b4645 --- /dev/null +++ b/src/mem/ruby/config/rubyconfig.defaults @@ -0,0 +1,466 @@ +// +// This file has been modified by Kevin Moore and Dan Nussbaum of the +// Scalable Systems Research Group at Sun Microsystems Laboratories +// (http://research.sun.com/scalable/) to support the Adaptive +// Transactional Memory Test Platform (ATMTP). For information about +// ATMTP, see the GEMS website: http://www.cs.wisc.edu/gems/. +// +// Please send email to atmtp-interest@sun.com with feedback, questions, or +// to request future announcements about ATMTP. +// +// ---------------------------------------------------------------------- +// +// File modification date: 2008-02-23 +// +// ---------------------------------------------------------------------- +// +// ATMTP is distributed as part of the GEMS software toolset and is +// available for use and modification under the terms of version 2 of the +// GNU General Public License. The GNU General Public License is contained +// in the file $GEMS/LICENSE. +// +// Multifacet GEMS is free software; you can redistribute it and/or modify +// it under the terms of version 2 of the GNU General Public License as +// published by the Free Software Foundation. +// +// Multifacet GEMS is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with the Multifacet GEMS; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA +// +// ---------------------------------------------------------------------- +// + +g_RANDOM_SEED: 1 +g_SIMICS: true + +g_DEADLOCK_THRESHOLD: 500000 + +// determines how many Simics cycles advance for every Ruby cycle +// (does not apply when running Opal) +SIMICS_RUBY_MULTIPLIER: 4 + +// corresponding parameter when using Opal+Ruby+Simics +OPAL_RUBY_MULTIPLIER: 1 + + +// Ruby cycles between when a sequencer issues a request and it arrives at +// the L1 cache controller +// +// ** important ** this parameter determines the L2 hit latency when +// using the SMP protocols with a combined L1/L2 controller (-cache.sm) +// +SEQUENCER_TO_CONTROLLER_LATENCY: 4 + + +// When set to false, the L1 cache structures are probed for a hit in Sequencer.C +// If a request hits, it is *not* issued to the cache controller +// When set to true, all processor data requests issue to cache controller +// +// ** important ** this parameter must be set to false for proper L1/L2 hit timing +// for the SMP protocols with combined L1/L2 controllers (-cache.sm) +// +REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH: false + + +// When running with Opal in SMT configurations, this indicates the number of threads per physical processor +g_NUM_SMT_THREADS: 1 + + +// Maximum number of requests (including SW prefetches) outstanding from +// the sequencer (Note: this also include items buffered in the store +// buffer) +g_SEQUENCER_OUTSTANDING_REQUESTS: 16 + + +PROTOCOL_DEBUG_TRACE: true +DEBUG_FILTER_STRING: none +DEBUG_VERBOSITY_STRING: none +DEBUG_START_TIME: 0 +DEBUG_OUTPUT_FILENAME: none + + +TRANSACTION_TRACE_ENABLED: false +USER_MODE_DATA_ONLY: false +PROFILE_HOT_LINES: false + +PROFILE_ALL_INSTRUCTIONS: false +PRINT_INSTRUCTION_TRACE: false +g_DEBUG_CYCLE: 0 +BLOCK_STC: false +PERFECT_MEMORY_SYSTEM: false +PERFECT_MEMORY_SYSTEM_LATENCY: 0 +DATA_BLOCK: false + + +// ********************************************* +// CACHE & MEMORY PARAMETERS +// ********************************************* + + +L1_CACHE_ASSOC: 4 +L1_CACHE_NUM_SETS_BITS: 8 +L2_CACHE_ASSOC: 4 +L2_CACHE_NUM_SETS_BITS: 16 + +// 32 bits = 4 GB address space +g_MEMORY_SIZE_BYTES: 4294967296 +g_DATA_BLOCK_BYTES: 64 +g_PAGE_SIZE_BYTES: 4096 +g_REPLACEMENT_POLICY: PSEDUO_LRU // currently, only other option is LRU + +g_PROCS_PER_CHIP: 1 + + +// set automatically +g_NUM_PROCESSORS: 0 +g_NUM_L2_BANKS: 0 +g_NUM_MEMORIES: 0 + +// The following group of parameters are calculated. They must +// _always_ be left at zero. +g_NUM_CHIPS: 0 +g_NUM_CHIP_BITS: 0 +g_MEMORY_SIZE_BITS: 0 +g_DATA_BLOCK_BITS: 0 +g_PAGE_SIZE_BITS: 0 +g_NUM_PROCESSORS_BITS: 0 +g_PROCS_PER_CHIP_BITS: 0 +g_NUM_L2_BANKS_BITS: 0 +g_NUM_L2_BANKS_PER_CHIP: 0 +g_NUM_L2_BANKS_PER_CHIP_BITS: 0 +g_NUM_MEMORIES_BITS: 0 +g_NUM_MEMORIES_PER_CHIP: 0 +g_MEMORY_MODULE_BITS: 0 +g_MEMORY_MODULE_BLOCKS: 0 + + +// For certain CMP protocols, determines whether the lowest bits of a block address +// are used to index to a L2 cache bank or into the sets of a +// single bank +// lowest highest +// true: g_DATA_BLOCK_BITS | g_NUM_L2_BANKS_PER_CHIP_BITS | L2_CACHE_NUM_SETS_BITS +// false: g_DATA_BLOCK_BITS | L2_CACHE_NUM_SETS_BITS | g_NUM_L2_BANKS_PER_CHIP_BITS +MAP_L2BANKS_TO_LOWEST_BITS: false + + + +// TIMING PARAMETERS -- many of these are protocol specific. See SLICC files +// to determine where they apply + +MEMORY_RESPONSE_LATENCY_MINUS_2: 158 // determines memory response latency +DIRECTORY_CACHE_LATENCY: 6 +NULL_LATENCY: 1 +ISSUE_LATENCY: 2 +CACHE_RESPONSE_LATENCY: 12 +L1_RESPONSE_LATENCY: 3 +L2_RESPONSE_LATENCY: 6 +L2_TAG_LATENCY: 6 +DIRECTORY_LATENCY: 80 +NETWORK_LINK_LATENCY: 1 +COPY_HEAD_LATENCY: 4 +ON_CHIP_LINK_LATENCY: 1 +RECYCLE_LATENCY: 10 +L2_RECYCLE_LATENCY: 5 +TIMER_LATENCY: 10000 +TBE_RESPONSE_LATENCY: 1 +PERIODIC_TIMER_WAKEUPS: true + + +// constants used by CMP protocols +// cache bank access times +L1_REQUEST_LATENCY: 2 +L2_REQUEST_LATENCY: 4 + + + + +// Number of transitions each controller state machines can complete per cycle +// i.e. the number of ports to each controller +// L1cache is the sum of the L1I and L1D cache ports +L1CACHE_TRANSITIONS_PER_RUBY_CYCLE: 32 +// Note: if SINGLE_ACCESS_L2_BANKS is enabled, this will probably enforce a +// much greater constraint on the concurrency of a L2 cache bank +L2CACHE_TRANSITIONS_PER_RUBY_CYCLE: 32 +DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE: 32 + + +// Number of TBEs available for demand misses, ALL prefetches, and replacements +// used by one-level protocols +NUMBER_OF_TBES: 128 +// two-level protocols +NUMBER_OF_L1_TBES: 32 +NUMBER_OF_L2_TBES: 32 + +// TSO is deprecated +TSO: false + + +// ** INTERCONECT PARAMETERS ** +// +g_PRINT_TOPOLOGY: true +g_NETWORK_TOPOLOGY: HIERARCHICAL_SWITCH +g_CACHE_DESIGN: NUCA // specifies file prefix for FILE_SPECIFIED topology +FAN_OUT_DEGREE: 4 // for HIERARCHICAL SWITCH topology + +g_adaptive_routing: true +NUMBER_OF_VIRTUAL_NETWORKS: 4 + +// bandwidth unit is 1/1000 byte per cycle. the following parameter is multiplied by +// topology specific link weights +g_endpoint_bandwidth: 10000 + + +// ** finite buffering parameters +// +// note: Finite buffering allows us to simulate a realistic virtual cut-through +// routed network with idealized flow control. this feature is NOT heavily tested +FINITE_BUFFERING: false +// All message buffers within the network (i.e. the switch's input and +// output buffers) are set to the size specified below by the FINITE_BUFFER_SIZE +FINITE_BUFFER_SIZE: 3 +// g_SEQUENCER_OUTSTANDING_REQUESTS (above) controlls the number of demand requests +// issued by the sequencer. The PROCESSOR_BUFFER_SIZE controlls the +// number of requests in the mandatory queue +// Only effects the simualtion when FINITE_BUFFERING is enabled +PROCESSOR_BUFFER_SIZE: 10 +// The PROTOCOL_BUFFER_SIZE limits the size of all other buffers connecting to +// Controllers. Controlls the number of request issued by the L2 HW Prefetcher +PROTOCOL_BUFFER_SIZE: 32 +// ** end finite buffering parameters + + +// (deprecated) +// Allows on a single accesses to a multi-cycle L2 bank. +// Ensures the cache array is only accessed once for every L2_REQUEST_LATENCY +// number of cycles. However the TBE table can be accessed in parallel. +SINGLE_ACCESS_L2_BANKS: true + + +// constants used by TM protocols +PROFILE_EXCEPTIONS: false +PROFILE_XACT: true +PROFILE_NONXACT: false +XACT_DEBUG: true +XACT_DEBUG_LEVEL: 1 +//XACT_MEMORY: true // set to true for TM protocols. set it HERE for lazy systems to register the proper SIMICS interfaces +XACT_MEMORY: false +XACT_ENABLE_TOURMALINE: false // perfect memory system +XACT_NUM_CURRENT: 0 // must be 0 +XACT_LAST_UPDATE: 0 // must be 0 +XACT_ISOLATION_CHECK: false // Checks whether each memory access preserves transaction isolation +PERFECT_FILTER: true // If true, use perfect physical read/write filters +READ_WRITE_FILTER: Perfect_ +PERFECT_VIRTUAL_FILTER: true // If true, use perfect virtual read/write filters +VIRTUAL_READ_WRITE_FILTER: Perfect_ +PERFECT_SUMMARY_FILTER: true // If true, use perfect summary read/write filters +SUMMARY_READ_WRITE_FILTER: Perfect_ +XACT_EAGER_CD: true +XACT_LAZY_VM: false +XACT_CONFLICT_RES: BASE +XACT_COMMIT_TOKEN_LATENCY: 0 +XACT_VISUALIZER: false +XACT_NO_BACKOFF: false +XACT_LOG_BUFFER_SIZE: 0 +XACT_STORE_PREDICTOR_ENTRIES: 256 +XACT_STORE_PREDICTOR_HISTORY: 256 +XACT_STORE_PREDICTOR_THRESHOLD: 4 +XACT_FIRST_ACCESS_COST: 0 +XACT_FIRST_PAGE_ACCESS_COST: 0 +ENABLE_MAGIC_WAITING: false +ENABLE_WATCHPOINT: false +XACT_ENABLE_VIRTUALIZATION_LOGTM_SE: false +// g_NETWORK_TOPOLOGY: FILE_SPECIFIED +// NUMBER_OF_VIRTUAL_NETWORKS: 5 +// L2_REQUEST_LATENCY: 15 +// SEQUENCER_TO_CONTROLLER_LATENCY: 3 +// L2_RESPONSE_LATENCY: 20 +// L2_TAG_LATENCY: 6 +// MEMORY_RESPONSE_LATENCY_MINUS_2: 448 +// RECYCLE_LATENCY: 1 +// g_MEMORY_SIZE_BYTES: 268435456 +// REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH: true + +// ATMTP +ATMTP_ENABLED: false +ATMTP_ABORT_ON_NON_XACT_INST: false +ATMTP_ALLOW_SAVE_RESTORE_IN_XACT: false +ATMTP_XACT_MAX_STORES: 32 +ATMTP_DEBUG_LEVEL: 0 + +// MOESI_CMP_token parameters (some might be deprecated) +g_FILTERING_ENABLED: false +g_DISTRIBUTED_PERSISTENT_ENABLED: true +g_RETRY_THRESHOLD: 1 +g_DYNAMIC_TIMEOUT_ENABLED: true +g_FIXED_TIMEOUT_LATENCY: 300 + + +// tester parameters (overridden by testerconfig.defaults) +// +// injects random message delays to excite protocol races +RANDOMIZATION: false +g_SYNTHETIC_DRIVER: false +g_DETERMINISTIC_DRIVER: false +g_trace_warmup_length: 1000000 +g_bash_bandwidth_adaptive_threshold: 0.75 + +g_tester_length: 0 +// # of synthetic locks == 16 * 128 +g_synthetic_locks: 2048 +g_deterministic_addrs: 1 +g_SpecifiedGenerator: DetermInvGenerator +g_callback_counter: 0 +g_NUM_COMPLETIONS_BEFORE_PASS: 0 +// parameters used by locking synthetic tester +g_think_time: 5 +g_hold_time: 5 +g_wait_time: 5 + +// Princeton Network (Garnet) +g_GARNET_NETWORK: false +g_DETAIL_NETWORK: false +g_NETWORK_TESTING: false +g_FLIT_SIZE: 16 +g_NUM_PIPE_STAGES: 4 +g_VCS_PER_CLASS: 4 +g_BUFFER_SIZE: 4 + +/////////////////////////////////////////////////////////////////////////////// +// +// MemoryControl: + +// Basic cycle time of the memory controller. This defines the period which is +// used as the memory channel clock period, the address bus bit time, and the +// memory controller cycle time. +// Assuming a 200 MHz memory channel (DDR-400, which has 400 bits/sec data), +// and a 2 GHz Ruby clock: +MEM_BUS_CYCLE_MULTIPLIER: 10 + +// How many internal banks in each DRAM chip: +BANKS_PER_RANK: 8 + +// How many sets of DRAM chips per DIMM. +RANKS_PER_DIMM: 2 + +// How many DIMMs per channel. (Currently the only thing that +// matters is the number of ranks per channel, i.e. the product +// of this parameter and RANKS_PER_DIMM. But if and when this is +// expanded to do FB-DIMMs, the distinction between the two +// will matter.) +DIMMS_PER_CHANNEL: 2 + +// Which bits to use to find the bank, rank, and DIMM numbers. +// You could choose to have the bank bits, rank bits, and DIMM bits +// in any order; here they are in that order. +// For these defaults, we assume this format for addresses: +// Offset within line: [5:0] +// Memory controller #: [7:6] +// Bank: [10:8] +// Rank: [11] +// DIMM: [12] +// Row addr / Col addr: [top:13] +// If you get these bits wrong, then some banks won't see any +// requests; you need to check for this in the .stats output. +BANK_BIT_0: 8 +RANK_BIT_0: 11 +DIMM_BIT_0: 12 + +// Number of entries max in each bank queues; set to whatever you want. +// If it is too small, you will see in the .stats file a lot of delay +// time spent in the common input queue. +BANK_QUEUE_SIZE: 12 + +// Bank cycle time (tRC) measured in memory cycles: +BANK_BUSY_TIME: 11 + +// This is how many memory address cycles to delay between reads to +// different ranks of DRAMs to allow for clock skew: +RANK_RANK_DELAY: 1 + +// This is how many memory address cycles to delay between a read +// and a write. This is based on two things: (1) the data bus is +// used one cycle earlier in the operation; (2) a round-trip wire +// delay from the controller to the DIMM that did the reading. +READ_WRITE_DELAY: 2 + +// Basic address and data bus occupancy. If you are assuming a +// 16-byte-wide data bus (pairs of DIMMs side-by-side), then +// the data bus occupancy matches the address bus occupancy at +// two cycles. But if the channel is only 8 bytes wide, you +// need to increase this bus occupancy time to 4 cycles. +BASIC_BUS_BUSY_TIME: 2 + +// Latency to returning read request or writeback acknowledgement. +// Measured in memory address cycles. +// This equals tRCD + CL + AL + (four bit times) +// + (round trip on channel) +// + (memory control internal delays) +// It's going to be an approximation, so pick what you like. +// Note: The fact that latency is a constant, and does not depend on two +// low-order address bits, implies that our memory controller either: +// (a) tells the DRAM to read the critical word first, and sends the +// critical word first back to the CPU, or (b) waits until it has +// seen all four bit times on the data wires before sending anything +// back. Either is plausible. If (a), remove the "four bit times" +// term from the calculation above. +MEM_CTL_LATENCY: 12 + +// refresh_period is the number of memory cycles between refresh +// of row x in bank n and refresh of row x+1 in bank n. For DDR-400, +// this is typically 7.8 usec for commercial systems; after 8192 such +// refreshes, this will have refreshed the whole chip in 64 msec. If +// we have a 5 nsec memory clock, 7800 / 5 = 1560 cycles. The memory +// controller will divide this by the total number of banks, and kick +// off a refresh to *somebody* every time that amount is counted +// down to zero. (There will be some rounding error there, but it +// should have minimal effect.) +REFRESH_PERIOD: 1560 + +// tFAW is a DRAM chip parameter which restricts the number of +// activates that can be done within a certain window of time. +// The window is specified here in terms of number of memory +// controller cycles. At most four activates may be done during +// any such sliding window. If this number is set to be no more +// than 4 * BASIC_BUS_BUSY_TIME, it will have no effect. +// It is typical in real systems for tFAW to have no effect, but +// it may be useful in throttling power. Set to zero to ignore. +TFAW: 0 + +// By default, the memory controller uses round-robin to arbitrate +// between ready bank queues for use of the address bus. If you +// wish to add randomness to the system, set this parameter to +// one instead, and it will restart the round-robin pointer at a +// random bank number each cycle. If you want additional +// nondeterminism, set the parameter to some integer n >= 2, and +// it will in addition add a n% chance each cycle that a ready bank +// will be delayed an additional cycle. Note that if you are +// in MEM_FIXED_DELAY mode (see below), MEM_RANDOM_ARBITRATE=1 will +// have no effect, but MEM_RANDOM_ARBITRATE=2 or more will. +MEM_RANDOM_ARBITRATE: 0 + +// The following parameter, if nonzero, will disable the memory +// controller and instead give every request a fixed latency. The +// nonzero value specified here is measured in memory cycles and is +// just added to MEM_CTL_LATENCY. It will also show up in the stats +// file as a contributor to memory_delays_stalled_at_head_of_bank_queue. +MEM_FIXED_DELAY: 0 + +// If instead of DDR-400, you wanted DDR-800, the channel gets faster +// but the basic operation of the DRAM core is unchanged. +// Busy times appear to double just because they are measured +// in smaller clock cycles. The performance advantage comes because +// the bus busy times don't actually quite double. +// You would use something like these values: +// +// MEM_BUS_CYCLE_MULTIPLIER: 5 +// BANK_BUSY_TIME: 22 +// RANK_RANK_DELAY: 2 +// READ_WRITE_DELAY: 3 +// BASIC_BUS_BUSY_TIME: 3 +// MEM_CTL_LATENCY: 20 +// REFRESH_PERIOD: 3120 diff --git a/src/mem/ruby/config/tester.defaults b/src/mem/ruby/config/tester.defaults new file mode 100644 index 000000000..ea83a1443 --- /dev/null +++ b/src/mem/ruby/config/tester.defaults @@ -0,0 +1,60 @@ + +// +// This file contains tester specific changes to the rubyconfig.defaults +// parameter values. +// +// Please: - Add new variables only to rubyconfig.defaults file. +// - Change them here only when necessary. + +g_SIMICS: false +DATA_BLOCK: true +RANDOMIZATION: true +g_SYNTHETIC_DRIVER: true +g_DETERMINISTIC_DRIVER: false +g_DEADLOCK_THRESHOLD: 500000 +g_SpecifiedGenerator: DetermGETXGenerator + +PROTOCOL_DEBUG_TRACE: true + +// +// Generic cache parameters +// + +// Cache sizes are smaller for the random tester to increase the amount +// of false sharing. +L1_CACHE_ASSOC: 2 +L1_CACHE_NUM_SETS_BITS: 2 +L2_CACHE_ASSOC: 2 +L2_CACHE_NUM_SETS_BITS: 5 + +g_MEMORY_SIZE_BYTES: 1048576 + +// XACT MEMORY +XACT_LENGTH: 2000 +XACT_SIZE: 1000 +ABORT_RETRY_TIME: 400 +XACT_ISOLATION_CHECK: true +L2CACHE_TRANSITIONS_PER_RUBY_CYCLE: 1000 +DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE: 1000 +PERFECT_FILTER: true // If true, use perfect read/write filters +READ_WRITE_FILTER: Perfect_ + +//g_NETWORK_TOPOLOGY: FILE_SPECIFIED +RECYCLE_LATENCY: 1 +//NUMBER_OF_VIRTUAL_NETWORKS: 5 +//g_NUM_MEMORIES: 16 +L2CACHE_TRANSITIONS_PER_RUBY_CYCLE: 1000 +DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE: 1000 +//g_PROCS_PER_CHIP: 16 +//g_NUM_L2_BANKS: 16 +//g_endpoint_bandwidth: 10000 +//g_NUM_PROCESSORS: 16 +//g_NUM_SMT_THREADS: 1 +//g_GARNET_NETWORK: true +//g_DETAIL_NETWORK: true +//g_NETWORK_TESTING: false +//g_FLIT_SIZE: 32 +//g_NUM_PIPE_STAGES: 5 +//g_VCS_PER_CLASS: 2 +//g_BUFFER_SIZE: 4 + diff --git a/src/mem/ruby/eventqueue/EventQueue.cc b/src/mem/ruby/eventqueue/EventQueue.cc new file mode 100644 index 000000000..0eef53530 --- /dev/null +++ b/src/mem/ruby/eventqueue/EventQueue.cc @@ -0,0 +1,120 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "EventQueue.hh" +#include "RubyConfig.hh" +#include "Consumer.hh" +#include "Profiler.hh" +#include "System.hh" +#include "PrioHeap.hh" +#include "EventQueueNode.hh" + +// Class public method definitions + +EventQueue::EventQueue() +{ + m_prio_heap_ptr = NULL; + init(); +} + +EventQueue::~EventQueue() +{ + delete m_prio_heap_ptr; +} + +void EventQueue::init() +{ + m_globalTime = 1; + m_timeOfLastRecovery = 1; + m_prio_heap_ptr = new PrioHeap; + m_prio_heap_ptr->init(); +} + +bool EventQueue::isEmpty() const +{ + return (m_prio_heap_ptr->size() == 0); +} + +void EventQueue::scheduleEventAbsolute(Consumer* consumer, Time timeAbs) +{ + // Check to see if this is a redundant wakeup + // Time time = timeDelta + m_globalTime; + ASSERT(consumer != NULL); + if (consumer->getLastScheduledWakeup() != timeAbs) { + // This wakeup is not redundant + EventQueueNode thisNode; + thisNode.m_consumer_ptr = consumer; + assert(timeAbs > m_globalTime); + thisNode.m_time = timeAbs; + m_prio_heap_ptr->insert(thisNode); + consumer->setLastScheduledWakeup(timeAbs); + } +} + +void EventQueue::triggerEvents(Time t) +{ + EventQueueNode thisNode; + + while(m_prio_heap_ptr->size() > 0 && m_prio_heap_ptr->peekMin().m_time <= t) { + m_globalTime = m_prio_heap_ptr->peekMin().m_time; + thisNode = m_prio_heap_ptr->extractMin(); + assert(thisNode.m_consumer_ptr != NULL); + DEBUG_EXPR(EVENTQUEUE_COMP,MedPrio,*(thisNode.m_consumer_ptr)); + DEBUG_EXPR(EVENTQUEUE_COMP,MedPrio,thisNode.m_time); + thisNode.m_consumer_ptr->triggerWakeup(); + } + m_globalTime = t; +} + +void EventQueue::triggerAllEvents() +{ + // FIXME - avoid repeated code + EventQueueNode thisNode; + + while(m_prio_heap_ptr->size() > 0) { + m_globalTime = m_prio_heap_ptr->peekMin().m_time; + thisNode = m_prio_heap_ptr->extractMin(); + assert(thisNode.m_consumer_ptr != NULL); + DEBUG_EXPR(EVENTQUEUE_COMP,MedPrio,*(thisNode.m_consumer_ptr)); + DEBUG_EXPR(EVENTQUEUE_COMP,MedPrio,thisNode.m_time); + thisNode.m_consumer_ptr->triggerWakeup(); + } +} + +// Class private method definitions + +void +EventQueue::print(ostream& out) const +{ + out << "[Event Queue: " << *m_prio_heap_ptr << "]"; +} diff --git a/src/mem/ruby/eventqueue/EventQueue.hh b/src/mem/ruby/eventqueue/EventQueue.hh new file mode 100644 index 000000000..476e0d24a --- /dev/null +++ b/src/mem/ruby/eventqueue/EventQueue.hh @@ -0,0 +1,118 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + * Description: The EventQueue class implements an event queue which + * can be trigger events, allowing our simulation to be event driven. + * + * Currently, the only event we support is a Consumer being signaled + * by calling the consumer's wakeup() routine. Adding the event to + * the queue does not require a virtual function call, though calling + * wakeup() is a virtual function call. + * + * The method triggerEvents() is called with a global time. All + * events which are before or at this time are triggered in timestamp + * order. No ordering is enforced for events scheduled to occur at + * the same time. Events scheduled to wakeup the same consumer at the + * same time are combined into a single event. + * + * The method scheduleConsumerWakeup() is called with a global time + * and a consumer pointer. The event queue will call the wakeup() + * method of the consumer at the appropriate time. + * + * This implementation of EventQueue uses a dynamically sized array + * managed as a heap. The algorithms used has O(lg n) for insert and + * O(lg n) for extract minimum element. (Based on chapter 7 of Cormen, + * Leiserson, and Rivest.) The array is dynamically sized and is + * automatically doubled in size when necessary. + * + */ + +#ifndef EVENTQUEUE_H +#define EVENTQUEUE_H + +#include "Global.hh" +#include "Vector.hh" + +class Consumer; +template class PrioHeap; +class EventQueueNode; + +class EventQueue { +public: + // Constructors + EventQueue(); + + // Destructor + ~EventQueue(); + + // Public Methods + + Time getTime() const { return m_globalTime; } + void scheduleEvent(Consumer* consumer, Time timeDelta) { scheduleEventAbsolute(consumer, timeDelta + m_globalTime); } + void scheduleEventAbsolute(Consumer* consumer, Time timeAbs); + void triggerEvents(Time t); // called to handle all events <= time t + void triggerAllEvents(); + void print(ostream& out) const; + bool isEmpty() const; + + Time getTimeOfLastRecovery() {return m_timeOfLastRecovery;} + void setTimeOfLastRecovery(Time t) {m_timeOfLastRecovery = t;} + + // Private Methods +private: + // Private copy constructor and assignment operator + void init(); + EventQueue(const EventQueue& obj); + EventQueue& operator=(const EventQueue& obj); + + // Data Members (m_ prefix) + PrioHeap* m_prio_heap_ptr; + Time m_globalTime; + Time m_timeOfLastRecovery; +}; + +// Output operator declaration +inline extern +ostream& operator<<(ostream& out, const EventQueue& obj); + +// ******************* Definitions ******************* + +// Output operator definition +inline extern +ostream& operator<<(ostream& out, const EventQueue& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //EVENTQUEUE_H diff --git a/src/mem/ruby/eventqueue/EventQueueNode.cc b/src/mem/ruby/eventqueue/EventQueueNode.cc new file mode 100644 index 000000000..b0027506b --- /dev/null +++ b/src/mem/ruby/eventqueue/EventQueueNode.cc @@ -0,0 +1,47 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + */ + +#include "EventQueueNode.hh" + +void EventQueueNode::print(ostream& out) const +{ + out << "["; + out << "Time=" << m_time; + if (m_consumer_ptr != NULL) { + out << " Consumer=" << m_consumer_ptr; + } else { + out << " Consumer=NULL"; + } + out << "]"; +} diff --git a/src/mem/ruby/eventqueue/EventQueueNode.hh b/src/mem/ruby/eventqueue/EventQueueNode.hh new file mode 100644 index 000000000..eff7ff37e --- /dev/null +++ b/src/mem/ruby/eventqueue/EventQueueNode.hh @@ -0,0 +1,98 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + */ + +#ifndef EVENTQUEUENODE_H +#define EVENTQUEUENODE_H + +#include "Global.hh" +class Consumer; + +class EventQueueNode { +public: + // Constructors + EventQueueNode() { m_time = 0; m_consumer_ptr = NULL; } + + // Destructor + //~EventQueueNode(); + + // Public Methods + void print(ostream& out) const; + + // Assignment operator and copy constructor since the default + // constructors confuse purify when long longs are present. + EventQueueNode& operator=(const EventQueueNode& obj) { + m_time = obj.m_time; + m_consumer_ptr = obj.m_consumer_ptr; + return *this; + } + + EventQueueNode(const EventQueueNode& obj) { + m_time = obj.m_time; + m_consumer_ptr = obj.m_consumer_ptr; + } +private: + // Private Methods + + // Default copy constructor and assignment operator + // EventQueueNode(const EventQueueNode& obj); + + // Data Members (m_ prefix) +public: + Time m_time; + Consumer* m_consumer_ptr; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const EventQueueNode& obj); + +// ******************* Definitions ******************* + +inline extern bool node_less_then_eq(const EventQueueNode& n1, const EventQueueNode& n2); + +inline extern +bool node_less_then_eq(const EventQueueNode& n1, const EventQueueNode& n2) +{ + return (n1.m_time <= n2.m_time); +} + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const EventQueueNode& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //EVENTQUEUENODE_H diff --git a/src/mem/ruby/eventqueue/EventQueue_tester.cc b/src/mem/ruby/eventqueue/EventQueue_tester.cc new file mode 100644 index 000000000..5e54aa7e0 --- /dev/null +++ b/src/mem/ruby/eventqueue/EventQueue_tester.cc @@ -0,0 +1,89 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + */ + +#include "EventQueue.hh" +#include "Consumer.hh" + +//static int global_counter = 0; + +class TestConsumer1 : public Consumer { +public: + TestConsumer1(int description) { m_description = description; } + ~TestConsumer1() { } + void wakeup() { cout << "Wakeup#1: " << m_description << endl; } + // void wakeup() { global_counter++; } + void print(ostream& out) const { out << "1:" << m_description << endl; } + +private: + int m_description; +}; + +class TestConsumer2 : public Consumer { +public: + TestConsumer2(int description) { m_description = description; } + ~TestConsumer2() { } + void wakeup() { cout << "Wakeup#2: " << m_description << endl; } + // void wakeup() { global_counter++; } + void print(ostream& out) const { out << "2:" << m_description << endl; } +private: + int m_description; +}; + +int main() +{ + EventQueue q; + const int SIZE = 200; + const int MAX_TIME = 10000; + int numbers[SIZE]; + Consumer* consumers[SIZE]; + + for (int i=0; i +#include +#include + +// Maurice +// extern "C" { +// #include "simics/api.hh" +// }; + +#include "FakeSimicsDataTypes.hh" + +#include "confio.hh" +#include "initvar.hh" + +// A generated file containing the default parameters in string form +// The defaults are stored in the variable global_default_param +#include "default_param.hh" + +attr_value_t ruby_session_get( void *id, void *obj, + attr_value_t *idx ) { + attr_value_t ret; + + // all session attributes default to return invalid + ret.kind = Sim_Val_Invalid; + return ret; +} + +set_error_t ruby_session_set( void *id, void *obj, + attr_value_t *val, attr_value_t *idx ) { + const char *command = (const char *) id; + // Add new ruby commands to this function + +#if 0 // Eventually add these commands back in + if (!strcmp(command, "dump-stats" ) ) { + char* filename = (char*) val->u.string; + if(strcmp(filename, "")){ + ruby_dump_stats(filename); + } else { + ruby_dump_stats(NULL); + } + return Sim_Set_Ok; + } else if (!strcmp(command, "dump-short-stats" ) ) { + char* filename = (char*) val->u.string; + if(strcmp(filename, "")){ + ruby_dump_short_stats(filename); + } else { + ruby_dump_short_stats(NULL); + } + return Sim_Set_Ok; + } else if (!strcmp(command, "periodic-stats-file" ) ) { + char* filename = (char*) val->u.string; + ruby_set_periodic_stats_file(filename); + return Sim_Set_Ok; + } else if (!strcmp(command, "periodic-stats-interval" ) ) { + int interval = val->u.integer; + ruby_set_periodic_stats_interval(interval); + return Sim_Set_Ok; + } else if (!strcmp(command, "clear-stats" ) ) { + ruby_clear_stats(); + return Sim_Set_Ok; + } else if (!strcmp(command, "debug-verb" ) ) { + char* new_verbosity = (char*) val->u.string; + ruby_change_debug_verbosity(new_verbosity); + return Sim_Set_Ok; + } else if (!strcmp(command, "debug-filter" ) ) { + char* new_debug_filter = (char*) val->u.string; + ruby_change_debug_filter(new_debug_filter); + return Sim_Set_Ok; + } else if (!strcmp(command, "debug-output-file" ) ) { + char* new_filename = (char*) val->u.string; + ruby_set_debug_output_file(new_filename); + return Sim_Set_Ok; + } else if (!strcmp(command, "debug-start-time" ) ) { + char* new_start_time = (char*) val->u.string; + ruby_set_debug_start_time(new_start_time); + return Sim_Set_Ok; + } else if (!strcmp(command, "load-caches" ) ) { + char* filename = (char*) val->u.string; + ruby_load_caches(filename); + return Sim_Set_Ok; + } else if (!strcmp(command, "save-caches" ) ) { + char* filename = (char*) val->u.string; + ruby_save_caches(filename); + return Sim_Set_Ok; + } else if (!strcmp(command, "dump-cache" ) ) { + int cpuNumber = val->u.integer; + ruby_dump_cache(cpuNumber); + return Sim_Set_Ok; + } else if (!strcmp(command, "dump-cache-data" ) ) { + int cpuNumber = val->u.list.vector[0].u.integer; + char *filename = (char*) val->u.list.vector[1].u.string; + ruby_dump_cache_data( cpuNumber, filename ); + return Sim_Set_Ok; + } else if (!strcmp(command, "tracer-output-file" ) ) { + char* new_filename = (char*) val->u.string; + ruby_set_tracer_output_file(new_filename); + return Sim_Set_Ok; + } else if (!strcmp(command, "xact-visualizer-file" ) ) { + char* new_filename = (char*) val->u.string; + ruby_xact_visualizer_file(new_filename); + return Sim_Set_Ok; + } + fprintf( stderr, "error: unrecognized command: %s\n", command ); +#endif + return Sim_Set_Illegal_Value; +} + +static initvar_t *ruby_initvar_obj = NULL; + +//*************************************************************************** +static void init_generate_values( void ) +{ + /* update generated values, based on input configuration */ +} + +//*************************************************************************** +void init_variables( void ) +{ + // allocate the "variable initialization" package + ruby_initvar_obj = new initvar_t( "ruby", "../../../ruby/", + global_default_param, + &init_simulator, + &init_generate_values, + &ruby_session_get, + &ruby_session_set ); +} + +void init_simulator() +{ + // Set things to NULL to make sure we don't de-reference them + // without a seg. fault. + g_system_ptr = NULL; + g_debug_ptr = NULL; + g_eventQueue_ptr = NULL; + + cout << "Ruby Timing Mode" << endl; +#ifndef MULTIFACET_NO_OPT_WARN + cerr << "Warning: optimizations not enabled." << endl; +#endif + + if (g_SIMICS) { + // LUKE - if we don't set the default SMT threads in condor scripts, + // set it now + if(g_NUM_SMT_THREADS == 0){ + g_NUM_SMT_THREADS = 1; + } + if(g_NUM_PROCESSORS == 0){ + //only set to default if value not set in condor scripts + // Account for SMT systems also + g_NUM_PROCESSORS = SIMICS_number_processors()/g_NUM_SMT_THREADS; + } + } + + RubyConfig::init(); + + g_debug_ptr = new Debug( DEBUG_FILTER_STRING, + DEBUG_VERBOSITY_STRING, + DEBUG_START_TIME, + DEBUG_OUTPUT_FILENAME ); + + cout << "Creating event queue..." << endl; + g_eventQueue_ptr = new EventQueue; + cout << "Creating event queue done" << endl; + + cout << "Creating system..." << endl; + cout << " Processors: " << RubyConfig::numberOfProcessors() << endl; + + g_system_ptr = new System; + cout << "Creating system done" << endl; + + // if opal is loaded, its static interface object (inst) will be non-null, + // and the opal object needs to be notified that ruby is now loaded. + // "1" indicates a load and should be replaced with an enumerated type. + if (OpalInterface::inst != NULL) { + OpalInterface::inst->notify( 1 ); + } + +#ifdef CONTIGUOUS_ADDRESSES + if(g_SIMICS) { + cout << "Establishing Contiguous Address Space Mappings..." << flush; + g_p_ca_translator = new ContiguousAddressTranslator(); + assert(g_p_ca_translator!=NULL); + if(g_p_ca_translator->AddressesAreContiguous()) { + cout << "Physical Memory Addresses are already contiguous." << endl; + delete g_p_ca_translator; + g_p_ca_translator = NULL; + } else { + cout << "Done." << endl; + } + } else { + g_p_ca_translator = NULL; + } +#endif // #ifdef CONTIGUOUS_ADDRESSES + + cout << "Ruby initialization complete" << endl; +} + +void init_opal_interface( mf_ruby_api_t *api ) +{ + OpalInterface::installInterface( api ); +} + +int init_use_snoop() +{ + if (g_SIMICS) { + // The "snoop interface" defined by simics allows ruby to see store + // data values (from simics). If DATA_BLOCK is defined, we are tracking + // data, so we need to install the snoop interface. + return ((DATA_BLOCK == true) || (XACT_MEMORY)); + } else { + return (0); + } +} + +void destroy_simulator() +{ + cout << "Deleting system..." << endl; + delete g_system_ptr; + cout << "Deleting system done" << endl; + + cout << "Deleting event queue..." << endl; + delete g_eventQueue_ptr; + cout << "Deleting event queue done" << endl; + + delete g_debug_ptr; +} + +/*-------------------------------------------------------------------------+ + | DG: These are the external load and unload hooks that will be called by | + | M5 in phase 1 integration, and possibly afterwards, too. | + +-------------------------------------------------------------------------*/ + +extern "C" +int OnLoadRuby() { + init_variables(); + return 0; +} + +extern "C" +int OnInitRuby() { + init_simulator(); + return 0; +} + +extern "C" +int OnUnloadRuby() { + destroy_simulator(); + return 0; +} + diff --git a/src/mem/ruby/init.hh b/src/mem/ruby/init.hh new file mode 100644 index 000000000..36d975b3e --- /dev/null +++ b/src/mem/ruby/init.hh @@ -0,0 +1,56 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * init.h + * + * Description: + * + * $Id$ + * + */ + +#ifndef INIT_H +#define INIT_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern void init_variables(); +extern void init_simulator(); +extern void init_opal_interface( mf_ruby_api_t *api ); +extern int init_use_snoop(); +extern void destroy_simulator(); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif //INIT_H diff --git a/src/mem/ruby/interfaces/OpalInterface.cc b/src/mem/ruby/interfaces/OpalInterface.cc new file mode 100644 index 000000000..362c7bcb6 --- /dev/null +++ b/src/mem/ruby/interfaces/OpalInterface.cc @@ -0,0 +1,446 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + */ + +/*------------------------------------------------------------------------*/ +/* Includes */ +/*------------------------------------------------------------------------*/ + +#include "OpalInterface.hh" +#include "interface.hh" +#include "System.hh" +#include "SubBlock.hh" +#include "mf_api.hh" +#include "Chip.hh" +#include "RubyConfig.hh" +//#include "XactIsolationChecker.hh" //gem5:Arka for decomissioning ruby/log_tm +// #include "TransactionInterfaceManager.hh" +//#include "TransactionVersionManager.hh" //gem5:Arka for decomissioning ruby/log_tm +#include "Sequencer.hh" + +/*------------------------------------------------------------------------*/ +/* Forward declarations */ +/*------------------------------------------------------------------------*/ + +static CacheRequestType get_request_type( OpalMemop_t opaltype ); +static OpalMemop_t get_opal_request_type( CacheRequestType type ); + +/// The static opalinterface instance +OpalInterface *OpalInterface::inst = NULL; + +/*------------------------------------------------------------------------*/ +/* Constructor(s) / destructor */ +/*------------------------------------------------------------------------*/ + +//************************************************************************** +OpalInterface::OpalInterface(System* sys_ptr) { + clearStats(); + ASSERT( inst == NULL ); + inst = this; + m_opal_intf = NULL; +} + +/*------------------------------------------------------------------------*/ +/* Public methods */ +/*------------------------------------------------------------------------*/ + +//************************************************************************** +void OpalInterface::printConfig(ostream& out) const { + out << "Opal_ruby_multiplier: " << OPAL_RUBY_MULTIPLIER << endl; + out << endl; +} + +void OpalInterface::printStats(ostream& out) const { + out << endl; + out << "Opal Interface Stats" << endl; + out << "----------------------" << endl; + out << endl; +} + +//************************************************************************** +void OpalInterface::clearStats() { +} + +//************************************************************************** +integer_t OpalInterface::getInstructionCount(int procID) const { + return ((*m_opal_intf->getInstructionCount)(procID)); +} + +//************************************************************************* +uint64 OpalInterface::getOpalTime(int procID) const { + return ((*m_opal_intf->getOpalTime)(procID)); +} + +/************ For WATTCH power stats ************************************/ +//************************************************************************* +void OpalInterface::incrementL2Access(int procID) const{ + ((*m_opal_intf->incrementL2Access)(procID)); +} + +//************************************************************************* +void OpalInterface::incrementPrefetcherAccess(int procID, int num_prefetches, int isinstr) const{ + ((*m_opal_intf->incrementPrefetcherAccess)(procID, num_prefetches, isinstr)); +} +/******************** END WATTCH power stats ****************************/ + +// Notifies Opal of an L2 miss +//************************************************************************* +void OpalInterface::notifyL2Miss(int procID, physical_address_t physicalAddr, OpalMemop_t type, int tagexists) const{ + ((*m_opal_intf->notifyL2Miss)(procID, physicalAddr, type, tagexists)); +} + +/****************************************************************** + * void hitCallback(int cpuNumber) + * Called by Sequencer. Calls opal. + ******************************************************************/ + +//************************************************************************** +void OpalInterface::hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread) { + // notify opal that the transaction has completed + (*m_opal_intf->hitCallback)( proc, data.getAddress().getAddress(), get_opal_request_type(type), thread ); +} + +//************************************************************************** +// Useful functions if Ruby needs to read/write physical memory when running with Opal +integer_t OpalInterface::readPhysicalMemory(int procID, + physical_address_t address, + int len ){ + return SIMICS_read_physical_memory(procID, address, len); +} + +//************************************************************************** +void OpalInterface::writePhysicalMemory( int procID, + physical_address_t address, + integer_t value, + int len ){ + SIMICS_write_physical_memory(procID, address, value, len); +} + +//*************************************************************** +// notifies Opal to print debug info +void OpalInterface::printDebug(){ + (*m_opal_intf->printDebug)(); +} + +//*************************************************************** + +/****************************************************************** + * Called by opal's memory operations (memop.C) + * May call Sequencer. + ******************************************************************/ + +//**************************************************************************** +int OpalInterface::getNumberOutstanding( int cpuNumber ){ + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + + return targetSequencer_ptr->getNumberOutstanding(); +} + +//**************************************************************************** +int OpalInterface::getNumberOutstandingDemand( int cpuNumber ){ + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + + return targetSequencer_ptr->getNumberOutstandingDemand(); +} + +//**************************************************************************** +int OpalInterface::getNumberOutstandingPrefetch( int cpuNumber ){ + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + + return targetSequencer_ptr->getNumberOutstandingPrefetch(); +} + +//************************************************************************** +int OpalInterface::isReady( int cpuNumber, la_t logicalAddr, pa_t physicalAddr, OpalMemop_t typeOfRequest, int thread ) { + // Send request to sequencer + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + + // FIXME - some of these fields have bogus values sinced isReady() + // doesn't need them. However, it would be cleaner if all of these + // fields were exact. + + return (targetSequencer_ptr->isReady(CacheMsg(Address( physicalAddr ), + Address( physicalAddr ), + get_request_type(typeOfRequest), + Address(0), + AccessModeType_UserMode, // User/supervisor mode + 0, // Size in bytes of request + PrefetchBit_No, // Not a prefetch + 0, // Version number + Address(logicalAddr), // Virtual Address + thread, // SMT thread + 0, // TM specific - timestamp of memory request + false // TM specific - whether request is part of escape action + ) + )); +} + +// FIXME: duplicated code should be avoided +//************************************************************************** +void OpalInterface::makeRequest(int cpuNumber, la_t logicalAddr, pa_t physicalAddr, + int requestSize, OpalMemop_t typeOfRequest, + la_t virtualPC, int isPriv, int thread) { + // Issue the request to the sequencer. + // set access type (user/supervisor) + AccessModeType access_mode; + if (isPriv) { + access_mode = AccessModeType_SupervisorMode; + } else { + access_mode = AccessModeType_UserMode; + } + + // Send request to sequencer + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + + targetSequencer_ptr->makeRequest(CacheMsg(Address( physicalAddr ), + Address( physicalAddr ), + get_request_type(typeOfRequest), + Address(virtualPC), + access_mode, // User/supervisor mode + requestSize, // Size in bytes of request + PrefetchBit_No, // Not a prefetch + 0, // Version number + Address(logicalAddr), // Virtual Address + thread, // SMT thread + 0, // TM specific - timestamp of memory request + false // TM specific - whether request is part of escape action + ) + ); +} + + +//************************************************************************** +void OpalInterface::makePrefetch(int cpuNumber, la_t logicalAddr, pa_t physicalAddr, + int requestSize, OpalMemop_t typeOfRequest, + la_t virtualPC, int isPriv, int thread) { + DEBUG_MSG(SEQUENCER_COMP,MedPrio,"Making prefetch request"); + + // Issue the request to the sequencer. + // set access type (user/supervisor) + AccessModeType access_mode; + if (isPriv) { + access_mode = AccessModeType_SupervisorMode; + } else { + access_mode = AccessModeType_UserMode; + } + + // make the prefetch + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + targetSequencer_ptr->makeRequest(CacheMsg(Address( physicalAddr ), + Address( physicalAddr ), + get_request_type(typeOfRequest), + Address(virtualPC), + access_mode, + requestSize, + PrefetchBit_Yes, // True means this is a prefetch + 0, // Version number + Address(logicalAddr), // Virtual Address + thread, // SMT thread + 0, // TM specific - timestamp of memory request + false // TM specific - whether request is part of escape action + ) + ); + return; +} + +//************************************************************************** +int OpalInterface::staleDataRequest( int cpuNumber, pa_t physicalAddr, + int requestSize, int8 *buffer ) { + // Find sequencer + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + assert(targetSequencer_ptr != NULL); + + // query the cache for stale data values (if any) + bool hit = false; + //hit = targetSequencer_ptr->staleDataAccess( Address(physicalAddr), + // requestSize, buffer ); + + return hit; +} + +//************************************************************************** +void OpalInterface::notify( int status ) { + if (OpalInterface::inst == NULL) { + if (status == 1) { + // notify system that opal is now loaded + g_system_ptr->opalLoadNotify(); + } else { + return; + } + } + + // opal interface must be allocated now + ASSERT( OpalInterface::inst != NULL ); + if ( status == 0 ) { + + } else if ( status == 1 ) { + // install notification: query opal for its interface + OpalInterface::inst->queryOpalInterface(); + if ( OpalInterface::inst->m_opal_intf != NULL ) { + cout << "OpalInterface: installation successful." << endl; + // test: (*(OpalInterface::inst->m_opal_intf->hitCallback))( 0, 0xFFULL ); + } + } else if ( status == 2 ) { + // unload notification + // NOTE: this is not tested, as we can't unload ruby or opal right now. + OpalInterface::inst->removeOpalInterface(); + } +} + +// advance ruby time +//************************************************************************** +int OpalInterface::s_advance_counter = 0; + +void OpalInterface::advanceTime( void ) { + s_advance_counter++; + if (s_advance_counter == OPAL_RUBY_MULTIPLIER) { + Time time = g_eventQueue_ptr->getTime() + 1; + DEBUG_EXPR(NODE_COMP, HighPrio, time); + g_eventQueue_ptr->triggerEvents(time); + s_advance_counter = 0; + } +} + +// return ruby's time +//************************************************************************** +unsigned long long OpalInterface::getTime( void ) { + return (g_eventQueue_ptr->getTime()); +} + +// print's Ruby outstanding request table +void OpalInterface::printProgress(int cpuNumber){ + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + assert(targetSequencer_ptr != NULL); + + targetSequencer_ptr->printProgress(cout); +} + +// Non-method helper function +//************************************************************************** +static CacheRequestType get_request_type( OpalMemop_t opaltype ) { + CacheRequestType type; + + if (opaltype == OPAL_LOAD) { + type = CacheRequestType_LD; + } else if (opaltype == OPAL_STORE){ + type = CacheRequestType_ST; + } else if (opaltype == OPAL_IFETCH){ + type = CacheRequestType_IFETCH; + } else if (opaltype == OPAL_ATOMIC){ + type = CacheRequestType_ATOMIC; + } else { + ERROR_MSG("Error: Strange memory transaction type: not a LD or a ST"); + } + return type; +} + +//************************************************************************** +static OpalMemop_t get_opal_request_type( CacheRequestType type ) { + OpalMemop_t opal_type; + + if(type == CacheRequestType_LD){ + opal_type = OPAL_LOAD; + } + else if( type == CacheRequestType_ST){ + opal_type = OPAL_STORE; + } + else if( type == CacheRequestType_IFETCH){ + opal_type = OPAL_IFETCH; + } + else if( type == CacheRequestType_ATOMIC){ + opal_type = OPAL_ATOMIC; + } + else{ + ERROR_MSG("Error: Strange memory transaction type: not a LD or a ST"); + } + + //cout << "get_opal_request_type() CacheRequestType[ " << type << " ] opal_type[ " << opal_type << " ] " << endl; + return opal_type; +} + +//************************************************************************** +void OpalInterface::removeOpalInterface( void ) { + cout << "ruby: opal uninstalled. reinstalling timing model." << endl; + SIMICS_install_timing_model(); +} + +//************************************************************************** +bool OpalInterface::isOpalLoaded( void ) { + if (!g_SIMICS) { + return false; + } else { + mf_opal_api_t *opal_interface = SIMICS_get_opal_interface(); + if ( opal_interface == NULL ) { + return false; + } else { + return true; + } + } +} + +//************************************************************************** +void OpalInterface::queryOpalInterface( void ) { + m_opal_intf = SIMICS_get_opal_interface(); + if ( m_opal_intf == NULL ) { + WARN_MSG("error: OpalInterface: opal does not implement mf-opal-api interface.\n"); + } else { + // opal is loaded -- remove the timing_model interface + cout << "Ruby: ruby-opal link established. removing timing_model." << endl; + SIMICS_remove_timing_model(); + + if (m_opal_intf->notifyCallback != NULL) { + cout << "opalinterface: doing notify callback\n"; + (*m_opal_intf->notifyCallback)( 1 ); + } else { + // 2/27/2005, removed spurious error message (MRM) + // cout << "error: opalinterface: mf-opal-api has NULL notify callback.\n"; + } + } +} + +// install the opal interface to simics +//************************************************************************** +void OpalInterface::installInterface( mf_ruby_api_t *api ) { + // install ruby interface + api->isReady = &OpalInterface::isReady; + api->makeRequest = &OpalInterface::makeRequest; + api->makePrefetch = &OpalInterface::makePrefetch; + api->advanceTime = &OpalInterface::advanceTime; + api->getTime = &OpalInterface::getTime; + api->staleDataRequest = &OpalInterface::staleDataRequest; + api->notifyCallback = &OpalInterface::notify; + api->getNumberOutstanding = &OpalInterface::getNumberOutstanding; + api->getNumberOutstandingDemand = &OpalInterface::getNumberOutstandingDemand; + api->getNumberOutstandingPrefetch = &OpalInterface::getNumberOutstandingPrefetch; + api->printProgress = &OpalInterface::printProgress; +} diff --git a/src/mem/ruby/interfaces/OpalInterface.hh b/src/mem/ruby/interfaces/OpalInterface.hh new file mode 100644 index 000000000..4bc63d15a --- /dev/null +++ b/src/mem/ruby/interfaces/OpalInterface.hh @@ -0,0 +1,214 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + * Description: + * + */ + +#ifndef OpalInterface_H +#define OpalInterface_H + +/*------------------------------------------------------------------------*/ +/* Includes */ +/*------------------------------------------------------------------------*/ + +#include "Global.hh" +#include "Driver.hh" +#include "mf_api.hh" +#include "CacheRequestType.hh" + +/*------------------------------------------------------------------------*/ +/* Class declaration(s) */ +/*------------------------------------------------------------------------*/ + +class System; +class TransactionInterfaceManager; +class Sequencer; + +/** + * the processor model (opal) calls these OpalInterface APIs to access + * the memory hierarchy (ruby). + * @see pseq_t + * @author cmauer + * @version $Id$ + */ +class OpalInterface : public Driver { +public: + // Constructors + OpalInterface(System* sys_ptr); + + // Destructor + // ~OpalInterface(); + + integer_t getInstructionCount(int procID) const; + void hitCallback( NodeID proc, SubBlock& data, CacheRequestType type, int thread ); + void printStats(ostream& out) const; + void clearStats(); + void printConfig(ostream& out) const; + void print(ostream& out) const; + + integer_t readPhysicalMemory(int procID, physical_address_t address, + int len ); + + void writePhysicalMemory( int procID, physical_address_t address, + integer_t value, int len ); + uint64 getOpalTime(int procID) const; + + // for WATTCH power + void incrementL2Access(int procID) const; + void incrementPrefetcherAccess(int procID, int num_prefetches, int isinstr) const; + + // notifies Opal of an L2 miss + void notifyL2Miss(int procID, physical_address_t physicalAddr, OpalMemop_t type, int tagexists) const; + + void printDebug(); + + /// The static opalinterface instance + static OpalInterface *inst; + + /// static methods + static int getNumberOutstanding(int cpuNumber); + static int getNumberOutstandingDemand(int cpuNumber); + static int getNumberOutstandingPrefetch( int cpuNumber ); + + /* returns true if the sequencer is able to handle more requests. + This implements "back-pressure" by which the processor knows + not to issue more requests if the network or cache's limits are reached. + */ + static int isReady( int cpuNumber, la_t logicalAddr, pa_t physicalAddr, OpalMemop_t typeOfRequest, int thread ); + + /* + makeRequest performs the coherence transactions necessary to get the + physical address in the cache with the correct permissions. More than + one request can be outstanding to ruby, but only one per block address. + The size of the cache line is defined to Intf_CacheLineSize. + When a request is finished (e.g. the cache contains physical address), + ruby calls completedRequest(). No request can be bigger than + Opal_CacheLineSize. It is illegal to request non-aligned memory + locations. A request of size 2 must be at an even byte, a size 4 must + be at a byte address half-word aligned, etc. Requests also can't cross a + cache-line boundaries. + */ + static void makeRequest(int cpuNumber, la_t logicalAddr, pa_t physicalAddr, + int requestSize, OpalMemop_t typeOfRequest, + la_t virtualPC, int isPriv, int thread); + + /* prefetch a given block... + */ + static void makePrefetch(int cpuNumber, la_t logicalAddr, pa_t physicalAddr, + int requestSize, OpalMemop_t typeOfRequest, + la_t virtualPC, int isPriv, int thread); + + /* + * request data from the cache, even if it's state is "Invalid". + */ + static int staleDataRequest( int cpuNumber, pa_t physicalAddr, + int requestSize, int8 *buffer ); + + /* notify ruby of opal's status + */ + static void notify( int status ); + + /* + * advance ruby one cycle + */ + static void advanceTime( void ); + + /* + * return ruby's cycle count. + */ + static unsigned long long getTime( void ); + + /* prints Ruby's outstanding request table */ + static void printProgress(int cpuNumber); + + /* + * initialize / install the inter-module interface + */ + static void installInterface( mf_ruby_api_t *api ); + + /* + * Test if opal is loaded or not + */ + static bool isOpalLoaded( void ); + + /* + * query opal for its api + */ + void queryOpalInterface( void ); + + /* + * remove the opal interface (opal is unloaded). + */ + void removeOpalInterface( void ); + + /* + * set the opal interface (used if stand-alone testing) + */ + void setOpalInterface( mf_opal_api_t *opal_intf ) { + m_opal_intf = opal_intf; + } + + /** + * Signal an abort + */ + //void abortCallback(NodeID proc); + +private: + // Private Methods + + // Private copy constructor and assignment operator + OpalInterface(const OpalInterface& obj); + OpalInterface& operator=(const OpalInterface& obj); + + // Data Members (m_ prefix) + mf_opal_api_t *m_opal_intf; + Time m_simicsStartTime; + + static int s_advance_counter; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const OpalInterface& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const OpalInterface& obj) +{ +// obj.print(out); + out << flush; + return out; +} + +#endif // OpalInterface_H diff --git a/src/mem/ruby/interfaces/mf_api.hh b/src/mem/ruby/interfaces/mf_api.hh new file mode 100644 index 000000000..c04a39308 --- /dev/null +++ b/src/mem/ruby/interfaces/mf_api.hh @@ -0,0 +1,165 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*------------------------------------------------------------------------*/ +/* Includes */ +/*------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------*/ +/* Macro declarations */ +/*------------------------------------------------------------------------*/ + +#ifndef _MF_MEMORY_API_H_ +#define _MF_MEMORY_API_H_ + +#ifdef SIMICS30 +#ifndef pa_t +typedef physical_address_t pa_t; +typedef physical_address_t la_t; +#endif +#endif + +/** + * Defines types of memory requests + */ +typedef enum OpalMemop { + OPAL_LOAD, + OPAL_STORE, + OPAL_IFETCH, + OPAL_ATOMIC, +} OpalMemop_t; + +/*------------------------------------------------------------------------*/ +/* Class declaration(s) */ +/*------------------------------------------------------------------------*/ + +/** +* structure which provides an interface between ruby and opal. +*/ +typedef struct mf_opal_api { + /** + * @name Methods + */ + //@{ + /** + * notify processor model that data from address address is available at proc + */ + void (*hitCallback)( int cpuNumber, pa_t phys_address, OpalMemop_t type, int thread ); + + /** + * notify opal that ruby is loaded, or removed + */ + void (*notifyCallback)( int status ); + + /** + * query for the number of instructions executed on a given processor. + */ + integer_t (*getInstructionCount)( int cpuNumber ); + + // for printing out debug info on crash + void (*printDebug)(); + + /** query Opal for the current time */ + uint64 (*getOpalTime)(int cpuNumber); + + /** For WATTCH power stats */ + // Called whenever L2 is accessed + void (*incrementL2Access)(int cpuNumber); + // Called whenever prefetcher is accessed + void (*incrementPrefetcherAccess)(int cpuNumber, int num_prefetches, int isinstr); + + /* Called whenever there's an L2 miss */ + void (*notifyL2Miss)(int cpuNumber, physical_address_t physicalAddr, OpalMemop_t type, int tagexists); + + //@} +} mf_opal_api_t; + +typedef struct mf_ruby_api { + /** + * @name Methods + */ + //@{ + /** + * Check to see if the system is ready for more requests + */ + int (*isReady)( int cpuNumber, la_t logicalAddr, pa_t physicalAddr, OpalMemop_t typeOfRequest, int thread ); + + /** + * Make a 'mandatory' request to the memory hierarchy + */ + void (*makeRequest)( int cpuNumber, la_t logicalAddr, pa_t physicalAddr, + int requestSize, OpalMemop_t typeOfRequest, + la_t virtualPC, int isPriv, int thread); + + /** + * Make a prefetch request to the memory hierarchy + */ + void (*makePrefetch)( int cpuNumber, la_t logicalAddr, pa_t physicalAddr, + int requestSize, OpalMemop_t typeOfRequest, + la_t virtualPC, int isPriv, int thread); + + /** + * Ask the memory hierarchy for 'stale' data that can be used for speculation + * Returns true (1) if the tag matches, false (0) if not. + */ + int (*staleDataRequest)( int cpuNumber, pa_t physicalAddr, + int requestSize, int8 *buffer ); + + /** + * Advance ruby's cycle time one step + */ + void (*advanceTime)( void ); + + /** + * Get ruby's cycle time count. + */ + uint64 (*getTime)( void ); + + /** prints Ruby's outstanding request table */ + void (*printProgress)(int cpuNumber); + + /** + * notify ruby that opal is loaded, or removed + */ + void (*notifyCallback)( int status ); + + // Returns the number of outstanding request + int (*getNumberOutstanding)(int cpuNumber); + + // Returns the number of outstanding demand requests + int (*getNumberOutstandingDemand)(int cpuNumber ); + + // Returns the number of outstanding prefetch request + int (*getNumberOutstandingPrefetch)(int cpuNumber ); + + + //@} +} mf_ruby_api_t; + +#endif //_MF_MEMORY_API_H_ diff --git a/src/mem/ruby/network/Network.hh b/src/mem/ruby/network/Network.hh new file mode 100644 index 000000000..662e54e93 --- /dev/null +++ b/src/mem/ruby/network/Network.hh @@ -0,0 +1,148 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Network.h + * + * Description: The Network class is the base class for classes that + * implement the interconnection network between components + * (processor/cache components and memory/directory components). The + * interconnection network as described here is not a physical + * network, but a programming concept used to implement all + * communication between components. Thus parts of this 'network' + * will model the on-chip connections between cache controllers and + * directory controllers as well as the links between chip and network + * switches. + * + * $Id$ + * */ + +#ifndef NETWORK_H +#define NETWORK_H + +#include "Global.hh" +#include "NodeID.hh" +#include "MessageSizeType.hh" + +class NetDest; +class MessageBuffer; +class Throttle; + +class Network { +public: + // Constructors + Network() {} + + // Destructor + virtual ~Network() {} + + // Public Methods + + static Network* createNetwork(int nodes); + + // returns the queue requested for the given component + virtual MessageBuffer* getToNetQueue(NodeID id, bool ordered, int netNumber) = 0; + virtual MessageBuffer* getFromNetQueue(NodeID id, bool ordered, int netNumber) = 0; + virtual const Vector* getThrottles(NodeID id) const { return NULL; } + + virtual int getNumNodes() {return 1;} + + virtual void makeOutLink(SwitchID src, NodeID dest, const NetDest& routing_table_entry, int link_latency, int link_weight, int bw_multiplier, bool isReconfiguration) = 0; + virtual void makeInLink(SwitchID src, NodeID dest, const NetDest& routing_table_entry, int link_latency, int bw_multiplier, bool isReconfiguration) = 0; + virtual void makeInternalLink(SwitchID src, NodeID dest, const NetDest& routing_table_entry, int link_latency, int link_weight, int bw_multiplier, bool isReconfiguration) = 0; + + virtual void reset() = 0; + + virtual void printStats(ostream& out) const = 0; + virtual void clearStats() = 0; + virtual void printConfig(ostream& out) const = 0; + virtual void print(ostream& out) const = 0; + +private: + + // Private Methods + // Private copy constructor and assignment operator + Network(const Network& obj); + Network& operator=(const Network& obj); + + // Data Members (m_ prefix) +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const Network& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const Network& obj) +{ + obj.print(out); + out << flush; + return out; +} + +// Code to map network message size types to an integer number of bytes +const int CONTROL_MESSAGE_SIZE = 8; +const int DATA_MESSAGE_SIZE = (64+8); + +extern inline +int MessageSizeType_to_int(MessageSizeType size_type) +{ + switch(size_type) { + case MessageSizeType_Undefined: + ERROR_MSG("Can't convert Undefined MessageSizeType to integer"); + break; + case MessageSizeType_Control: + case MessageSizeType_Request_Control: + case MessageSizeType_Reissue_Control: + case MessageSizeType_Response_Control: + case MessageSizeType_Writeback_Control: + case MessageSizeType_Forwarded_Control: + case MessageSizeType_Invalidate_Control: + case MessageSizeType_Unblock_Control: + case MessageSizeType_Persistent_Control: + case MessageSizeType_Completion_Control: + return CONTROL_MESSAGE_SIZE; + break; + case MessageSizeType_Data: + case MessageSizeType_Response_Data: + case MessageSizeType_ResponseLocal_Data: + case MessageSizeType_ResponseL2hit_Data: + case MessageSizeType_Writeback_Data: + return DATA_MESSAGE_SIZE; + break; + default: + ERROR_MSG("Invalid range for type MessageSizeType"); + break; + } + return 0; +} + +#endif //NETWORK_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/CreditLink_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/CreditLink_d.hh new file mode 100644 index 000000000..e3a9b7d2d --- /dev/null +++ b/src/mem/ruby/network/garnet-fixed-pipeline/CreditLink_d.hh @@ -0,0 +1,17 @@ +/* + * CreditLink_d.h + * + * Niket Agarwal, Princeton University + * + * */ +#ifndef CREDIT_LINK_D_H +#define CREDIT_LINK_D_H + +#include "NetworkLink_d.hh" + +class CreditLink_d : public NetworkLink_d { +public: + CreditLink_d(int id):NetworkLink_d(id) {} +}; + +#endif diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.cc new file mode 100644 index 000000000..43f9a31bd --- /dev/null +++ b/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.cc @@ -0,0 +1,349 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * GarnetNetwork_d.C + * + * Niket Agarwal, Princeton University + * + * */ + +#include "GarnetNetwork_d.hh" +#include "MachineType.hh" +#include "NetworkInterface_d.hh" +#include "MessageBuffer.hh" +#include "Router_d.hh" +#include "Topology.hh" +#include "NetworkLink_d.hh" +#include "CreditLink_d.hh" +#include "NetDest.hh" + +GarnetNetwork_d::GarnetNetwork_d(int nodes) +{ + m_nodes = MachineType_base_number(MachineType_NUM); // Total nodes in network + m_virtual_networks = NUMBER_OF_VIRTUAL_NETWORKS; // Number of virtual networks = number of message classes in the coherence protocol + m_ruby_start = 0; + m_flits_recieved = 0; + m_flits_injected = 0; + m_network_latency = 0.0; + m_queueing_latency = 0.0; + + m_router_ptr_vector.clear(); + + // Allocate to and from queues + m_toNetQueues.setSize(m_nodes); // Queues that are getting messages from protocol + m_fromNetQueues.setSize(m_nodes); // Queues that are feeding the protocol + m_in_use.setSize(m_virtual_networks); + m_ordered.setSize(m_virtual_networks); + for (int i = 0; i < m_virtual_networks; i++) + { + m_in_use[i] = false; + m_ordered[i] = false; + } + + for (int node = 0; node < m_nodes; node++) + { + //Setting how many vitual message buffers will there be per Network Queue + m_toNetQueues[node].setSize(m_virtual_networks); + m_fromNetQueues[node].setSize(m_virtual_networks); + + for (int j = 0; j < m_virtual_networks; j++) + { + m_toNetQueues[node][j] = new MessageBuffer(); // Instantiating the Message Buffers that interact with the coherence protocol + m_fromNetQueues[node][j] = new MessageBuffer(); + } + } + + // Setup the network switches + m_topology_ptr = new Topology(this, m_nodes); + + int number_of_routers = m_topology_ptr->numSwitches(); + for (int i=0; iaddNode(m_toNetQueues[i], m_fromNetQueues[i]); + m_ni_ptr_vector.insertAtBottom(ni); + } + m_topology_ptr->createLinks(false); // false because this isn't a reconfiguration + for(int i = 0; i < m_router_ptr_vector.size(); i++) + { + m_router_ptr_vector[i]->init(); + } +} + +GarnetNetwork_d::~GarnetNetwork_d() +{ + for (int i = 0; i < m_nodes; i++) + { + m_toNetQueues[i].deletePointers(); + m_fromNetQueues[i].deletePointers(); + } + m_router_ptr_vector.deletePointers(); + m_ni_ptr_vector.deletePointers(); + m_link_ptr_vector.deletePointers(); + m_creditlink_ptr_vector.deletePointers(); + delete m_topology_ptr; +} + +void GarnetNetwork_d::reset() +{ + for (int node = 0; node < m_nodes; node++) + { + for (int j = 0; j < m_virtual_networks; j++) + { + m_toNetQueues[node][j]->clear(); + m_fromNetQueues[node][j]->clear(); + } + } +} + +/* + * This function creates a link from the Network Interface (NI) into the Network. + * It creates a Network Link from the NI to a Router and a Credit Link from + * the Router to the NI +*/ + +void GarnetNetwork_d::makeInLink(NodeID src, SwitchID dest, const NetDest& routing_table_entry, int link_latency, int bw_multiplier, bool isReconfiguration) +{ + assert(src < m_nodes); + + if(!isReconfiguration) + { + NetworkLink_d *net_link = new NetworkLink_d(m_link_ptr_vector.size(), link_latency, this); + CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size()); + m_link_ptr_vector.insertAtBottom(net_link); + m_creditlink_ptr_vector.insertAtBottom(credit_link); + + m_router_ptr_vector[dest]->addInPort(net_link, credit_link); + m_ni_ptr_vector[src]->addOutPort(net_link, credit_link); + } + else + { + ERROR_MSG("Fatal Error:: Reconfiguration not allowed here"); + // do nothing + } +} + +/* + * This function creates a link from the Network to a NI. + * It creates a Network Link from a Router to the NI and + * a Credit Link from NI to the Router +*/ + +void GarnetNetwork_d::makeOutLink(SwitchID src, NodeID dest, const NetDest& routing_table_entry, int link_latency, int link_weight, int bw_multiplier, bool isReconfiguration) +{ + assert(dest < m_nodes); + assert(src < m_router_ptr_vector.size()); + assert(m_router_ptr_vector[src] != NULL); + + if(!isReconfiguration) + { + NetworkLink_d *net_link = new NetworkLink_d(m_link_ptr_vector.size(), link_latency, this); + CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size()); + m_link_ptr_vector.insertAtBottom(net_link); + m_creditlink_ptr_vector.insertAtBottom(credit_link); + + m_router_ptr_vector[src]->addOutPort(net_link, routing_table_entry, link_weight, credit_link); + m_ni_ptr_vector[dest]->addInPort(net_link, credit_link); + } + else + { + ERROR_MSG("Fatal Error:: Reconfiguration not allowed here"); + //do nothing + } +} + +/* + * This function creates a internal network links +*/ + +void GarnetNetwork_d::makeInternalLink(SwitchID src, SwitchID dest, const NetDest& routing_table_entry, int link_latency, int link_weight, int bw_multiplier, bool isReconfiguration) +{ + if(!isReconfiguration) + { + NetworkLink_d *net_link = new NetworkLink_d(m_link_ptr_vector.size(), link_latency, this); + CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size()); + m_link_ptr_vector.insertAtBottom(net_link); + m_creditlink_ptr_vector.insertAtBottom(credit_link); + + m_router_ptr_vector[dest]->addInPort(net_link, credit_link); + m_router_ptr_vector[src]->addOutPort(net_link, routing_table_entry, link_weight, credit_link); + } + else + { + ERROR_MSG("Fatal Error:: Reconfiguration not allowed here"); + // do nothing + } +} + +void GarnetNetwork_d::checkNetworkAllocation(NodeID id, bool ordered, int network_num) +{ + ASSERT(id < m_nodes); + ASSERT(network_num < m_virtual_networks); + + if (ordered) + { + m_ordered[network_num] = true; + } + m_in_use[network_num] = true; +} + +MessageBuffer* GarnetNetwork_d::getToNetQueue(NodeID id, bool ordered, int network_num) +{ + checkNetworkAllocation(id, ordered, network_num); + return m_toNetQueues[id][network_num]; +} + +MessageBuffer* GarnetNetwork_d::getFromNetQueue(NodeID id, bool ordered, int network_num) +{ + checkNetworkAllocation(id, ordered, network_num); + return m_fromNetQueues[id][network_num]; +} + +void GarnetNetwork_d::clearStats() +{ + m_ruby_start = g_eventQueue_ptr->getTime(); +} + +Time GarnetNetwork_d::getRubyStartTime() +{ + return m_ruby_start; +} + +void GarnetNetwork_d::printStats(ostream& out) const +{ double average_link_utilization = 0; + Vector average_vc_load; + average_vc_load.setSize(m_virtual_networks*NetworkConfig::getVCsPerClass()); + + for(int i = 0; i < m_virtual_networks*NetworkConfig::getVCsPerClass(); i++) + { + average_vc_load[i] = 0; + } + + out << endl; + out << "Network Stats" << endl; + out << "-------------" << endl; + out << endl; + for(int i = 0; i < m_link_ptr_vector.size(); i++) + { + average_link_utilization += (double(m_link_ptr_vector[i]->getLinkUtilization())) / (double(g_eventQueue_ptr->getTime()-m_ruby_start)); + + Vector vc_load = m_link_ptr_vector[i]->getVcLoad(); + for(int j = 0; j < vc_load.size(); j++) + { + assert(vc_load.size() == NetworkConfig::getVCsPerClass()*m_virtual_networks); + average_vc_load[j] += vc_load[j]; + } + } + average_link_utilization = average_link_utilization/m_link_ptr_vector.size(); + out << "Average Link Utilization :: " << average_link_utilization << " flits/cycle" << endl; + out << "-------------" << endl; + + for(int i = 0; i < NetworkConfig::getVCsPerClass()*NUMBER_OF_VIRTUAL_NETWORKS; i++) + { + average_vc_load[i] = (double(average_vc_load[i]) / (double(g_eventQueue_ptr->getTime()) - m_ruby_start)); + out << "Average VC Load [" << i << "] = " << average_vc_load[i] << " flits/cycle " << endl; + } + out << "-------------" << endl; + + // out << "Total flits injected = " << m_flits_injected << endl; + // out << "Total flits recieved = " << m_flits_recieved << endl; + out << "Average network latency = " << ((double) m_network_latency/ (double) m_flits_recieved)<< endl; + // out << "Average queueing latency = " << ((double) m_queueing_latency/ (double) m_flits_recieved)<< endl; + // out << "Average latency = " << ((double) (m_queueing_latency + m_network_latency) / (double) m_flits_recieved)<< endl; + out << "-------------" << endl; + + double m_total_link_power = 0.0; + double m_total_router_power = 0.0; + + for(int i = 0; i < m_link_ptr_vector.size(); i++) + { + m_total_link_power += m_link_ptr_vector[i]->calculate_power(); + } + + for(int i = 0; i < m_router_ptr_vector.size(); i++) + { + m_total_router_power += m_router_ptr_vector[i]->calculate_power(); + } + out << "Total Link Power = " << m_total_link_power << " W " << endl; + out << "Total Router Power = " << m_total_router_power << " W " <printConfig(out); + } + for(int i = 0; i < m_router_ptr_vector.size(); i++) + { + m_router_ptr_vector[i]->printConfig(out); + } + if (g_PRINT_TOPOLOGY) + { + m_topology_ptr->printConfig(out); + } +} + +void GarnetNetwork_d::print(ostream& out) const +{ + out << "[GarnetNetwork_d]"; +} diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh new file mode 100644 index 000000000..34486eab8 --- /dev/null +++ b/src/mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh @@ -0,0 +1,142 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * GarnetNetwork_d.h + * + * Niket Agarwal, Princeton University + * + * */ + +#ifndef GARNETNETWORK_D_H +#define GARNETNETWORK_D_H + +#include "NetworkHeader.hh" +#include "Vector.hh" +#include "NetworkConfig.hh" +#include "Network.hh" + +class NetworkInterface_d; +class MessageBuffer; +class Router_d; +class Topology; +class NetDest; +class NetworkLink_d; +class CreditLink_d; + +class GarnetNetwork_d : public Network{ +public: + GarnetNetwork_d(int nodes); + + ~GarnetNetwork_d(); + + int getNumNodes(){ return m_nodes;} + + // returns the queue requested for the given component + MessageBuffer* getToNetQueue(NodeID id, bool ordered, int network_num); + MessageBuffer* getFromNetQueue(NodeID id, bool ordered, int network_num); + + void clearStats(); + void printStats(ostream& out) const; + void printConfig(ostream& out) const; + void print(ostream& out) const; + + inline void increment_injected_flits() + { + m_flits_injected++; + } + inline void increment_recieved_flits() + { + m_flits_recieved++; + } + inline void increment_network_latency(Time latency) + { + m_network_latency += latency; + } + inline void increment_queueing_latency(Time latency) + { + m_queueing_latency += latency; + } + + bool isVNetOrdered(int vnet) + { + return m_ordered[vnet]; + } + bool validVirtualNetwork(int vnet) { return m_in_use[vnet]; } + + Time getRubyStartTime(); + + void reset(); + + // Methods used by Topology to setup the network + void makeOutLink(SwitchID src, NodeID dest, const NetDest& routing_table_entry, int link_latency, int link_weight, int bw_multiplier, bool isReconfiguration); + void makeInLink(SwitchID src, NodeID dest, const NetDest& routing_table_entry, int link_latency, int bw_multiplier, bool isReconfiguration); + void makeInternalLink(SwitchID src, NodeID dest, const NetDest& routing_table_entry, int link_latency, int link_weight, int bw_multiplier, bool isReconfiguration); + +private: + void checkNetworkAllocation(NodeID id, bool ordered, int network_num); + +// Private copy constructor and assignment operator + GarnetNetwork_d(const GarnetNetwork_d& obj); + GarnetNetwork_d& operator=(const GarnetNetwork_d& obj); + +/***********Data Members*************/ + int m_virtual_networks; + int m_nodes; + int m_flits_recieved, m_flits_injected; + double m_network_latency, m_queueing_latency; + + Vector m_in_use; + Vector m_ordered; + + Vector > m_toNetQueues; + Vector > m_fromNetQueues; + + Vector m_router_ptr_vector; // All Routers in Network + Vector m_link_ptr_vector; // All links in the network + Vector m_creditlink_ptr_vector; // All links in the network + Vector m_ni_ptr_vector; // All NI's in Network + + Topology* m_topology_ptr; + Time m_ruby_start; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const GarnetNetwork_d& obj); + +// ******************* Definitions ******************* +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const GarnetNetwork_d& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //GARNETNETWORK_D_H diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.cc new file mode 100644 index 000000000..bedd801d5 --- /dev/null +++ b/src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.cc @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * InputUnit_d.C + * + * Niket Agarwal, Princeton University + * + * */ + +#include "InputUnit_d.hh" +#include "Router_d.hh" + +InputUnit_d::InputUnit_d(int id, Router_d *router) +{ + m_id = id; + m_router = router; + m_num_vcs = m_router->get_num_vcs(); + + m_num_buffer_reads = 0; + m_num_buffer_writes = 0; + + creditQueue = new flitBuffer_d(); + // Instantiating the virtual channels + m_vcs.setSize(m_num_vcs); + for(int i=0; i < m_num_vcs; i++) + { + m_vcs[i] = new VirtualChannel_d(i); + } +} + +InputUnit_d::~InputUnit_d() +{ + delete creditQueue; + m_vcs.deletePointers(); +} + +void InputUnit_d::wakeup() +{ + flit_d *t_flit; + if(m_in_link->isReady()) + { + t_flit = m_in_link->consumeLink(); + int vc = t_flit->get_vc(); + if((t_flit->get_type() == HEAD_) || (t_flit->get_type() == HEAD_TAIL_)) + { + assert(m_vcs[vc]->get_state() == IDLE_); + m_router->route_req(t_flit, this, vc); // Do the route computation for this vc + m_vcs[vc]->set_enqueue_time(g_eventQueue_ptr->getTime()); + } + else + { + t_flit->advance_stage(SA_); + m_router->swarb_req(); + } + m_vcs[vc]->insertFlit(t_flit); // write flit into input buffer + m_num_buffer_writes++; + m_num_buffer_reads++; // same as read because any flit that is written will be read only once + } +} + + +void InputUnit_d::printConfig(ostream& out) +{ + out << endl; + out << "InputUnit Configuration" << endl; + out << "---------------------" << endl; + out << "id = " << m_id << endl; + out << "In link is " << m_in_link->get_id() << endl; +} diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.hh new file mode 100644 index 000000000..c22363fb1 --- /dev/null +++ b/src/mem/ruby/network/garnet-fixed-pipeline/InputUnit_d.hh @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * InputUnit_d.h + * + * Niket Agarwal, Princeton University + * + * */ + +#ifndef INPUT_UNIT_D_H +#define INPUT_UNIT_D_H + +#include "NetworkHeader.hh" +#include "flitBuffer_d.hh" +#include "Consumer.hh" +#include "Vector.hh" +#include "VirtualChannel_d.hh" +#include "NetworkLink_d.hh" +#include "CreditLink_d.hh" + +class Router_d; + +class InputUnit_d : public Consumer { +public: + InputUnit_d(int id, Router_d *router); + ~InputUnit_d(); + + void wakeup(); + void printConfig(ostream& out); + flitBuffer_d* getCreditQueue() { return creditQueue; } + void print(ostream& out) const {}; + + inline int get_inlink_id() + { + return m_in_link->get_id(); + } + + inline void set_vc_state(VC_state_type state, int vc) + { + m_vcs[vc]->set_state(state); + } + inline void set_enqueue_time(int invc, Time time) + { + m_vcs[invc]->set_enqueue_time(time); + } + inline Time get_enqueue_time(int invc) + { + return m_vcs[invc]->get_enqueue_time(); + } + inline void update_credit(int in_vc, int credit) + { + m_vcs[in_vc]->update_credit(credit); + } + + inline bool has_credits(int vc) + { + return m_vcs[vc]->has_credits(); + } + + inline void increment_credit(int in_vc, bool free_signal) + { + flit_d *t_flit = new flit_d(in_vc, free_signal); + creditQueue->insert(t_flit); + g_eventQueue_ptr->scheduleEvent(m_credit_link, 1); + } + + inline int get_outvc(int invc) + { + return m_vcs[invc]->get_outvc(); + } + + inline void updateRoute(int vc, int outport) + { + m_vcs[vc]->set_outport(outport); + m_vcs[vc]->set_state(VC_AB_); + } + + inline void grant_vc(int in_vc, int out_vc) + { + m_vcs[in_vc]->grant_vc(out_vc); + } + + inline flit_d* peekTopFlit(int vc) + { + return m_vcs[vc]->peekTopFlit(); + } + + inline flit_d* getTopFlit(int vc) + { + return m_vcs[vc]->getTopFlit(); + } + + inline bool need_stage(int vc, VC_state_type state, flit_stage stage) + { + return m_vcs[vc]->need_stage(state, stage); + } + + inline bool need_stage_nextcycle(int vc, VC_state_type state, flit_stage stage) + { + return m_vcs[vc]->need_stage_nextcycle(state, stage); + } + + inline bool isReady(int invc) + { + return m_vcs[invc]->isReady(); + } + + inline int get_route(int vc) + { + return m_vcs[vc]->get_route(); + } + inline void set_in_link(NetworkLink_d *link) + { + m_in_link = link; + } + + inline void set_credit_link(CreditLink_d *credit_link) + { + m_credit_link = credit_link; + } + + inline double get_buf_read_count() + { + return m_num_buffer_reads; + } + + inline double get_buf_write_count() + { + return m_num_buffer_writes; + } + +private: + int m_id; + int m_num_vcs; + double m_num_buffer_writes, m_num_buffer_reads; + + Router_d *m_router; + NetworkLink_d *m_in_link; + CreditLink_d *m_credit_link; + flitBuffer_d *creditQueue; + + // Virtual channels + Vector m_vcs; // [vc] +}; + +#endif diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkHeader.hh b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkHeader.hh new file mode 100644 index 000000000..6a212ce99 --- /dev/null +++ b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkHeader.hh @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * NetworkHeader.h + * + * Niket Agarwal, Princeton University + * + * */ + +#ifndef NETWORK_HEADER_H +#define NETWORK_HEADER_H + +#include "Global.hh" +#include "NodeID.hh" + +using namespace std; +using namespace __gnu_cxx; + +enum flit_type {HEAD_, BODY_, TAIL_, HEAD_TAIL_, NUM_FLIT_TYPE_}; +enum VC_state_type {IDLE_, VC_AB_, ACTIVE_, NUM_VC_STATE_TYPE_}; +enum flit_stage {I_, VA_, SA_, ST_, LT_, NUM_FLIT_STAGE_}; + +#define NETCONFIG_DEFAULTS "netconfig.defaults" + +#define INFINITE_ 10000 + +#endif + diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc new file mode 100644 index 000000000..edf2d4b95 --- /dev/null +++ b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc @@ -0,0 +1,351 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * NetworkInterface_d.C + * + * Niket Agarwal, Princeton University + * + * */ + +#include "NetworkInterface_d.hh" +#include "MessageBuffer.hh" +#include "flitBuffer_d.hh" +#include "NetworkMessage.hh" + +NetworkInterface_d::NetworkInterface_d(int id, int virtual_networks, GarnetNetwork_d *network_ptr) +{ + m_id = id; + m_net_ptr = network_ptr; + m_virtual_networks = virtual_networks; + m_vc_per_vnet = NetworkConfig::getVCsPerClass(); + m_num_vcs = m_vc_per_vnet*m_virtual_networks; + + m_vc_round_robin = 0; + m_ni_buffers.setSize(m_num_vcs); + m_ni_enqueue_time.setSize(m_num_vcs); + inNode_ptr.setSize(m_virtual_networks); + outNode_ptr.setSize(m_virtual_networks); + creditQueue = new flitBuffer_d(); + + for(int i =0; i < m_num_vcs; i++) + { + m_ni_buffers[i] = new flitBuffer_d(); // instantiating the NI flit buffers + m_ni_enqueue_time[i] = INFINITE_; + } + m_vc_allocator.setSize(m_virtual_networks); // 1 allocator per virtual net + for(int i = 0; i < m_virtual_networks; i++) + { + m_vc_allocator[i] = 0; + } + + for(int i = 0; i < m_num_vcs; i++) + { + m_out_vc_state.insertAtBottom(new OutVcState_d(i)); + m_out_vc_state[i]->setState(IDLE_, g_eventQueue_ptr->getTime()); + } +} + +NetworkInterface_d::~NetworkInterface_d() +{ + m_out_vc_state.deletePointers(); + m_ni_buffers.deletePointers(); + delete creditQueue; + delete outSrcQueue; +} + +void NetworkInterface_d::addInPort(NetworkLink_d *in_link, CreditLink_d *credit_link) +{ + inNetLink = in_link; + in_link->setLinkConsumer(this); + m_ni_credit_link = credit_link; + credit_link->setSourceQueue(creditQueue); +} + +void NetworkInterface_d::addOutPort(NetworkLink_d *out_link, CreditLink_d *credit_link) +{ + m_credit_link = credit_link; + credit_link->setLinkConsumer(this); + + outNetLink = out_link; + outSrcQueue = new flitBuffer_d(); + out_link->setSourceQueue(outSrcQueue); +} + +void NetworkInterface_d::addNode(Vector& in, Vector& out) +{ + ASSERT(in.size() == m_virtual_networks); + inNode_ptr = in; + outNode_ptr = out; + for (int j = 0; j < m_virtual_networks; j++) + { + inNode_ptr[j]->setConsumer(this); // So that protocol injects messages into the NI + } +} + +bool NetworkInterface_d::flitisizeMessage(MsgPtr msg_ptr, int vnet) +{ + NetworkMessage *net_msg_ptr = dynamic_cast(msg_ptr.ref()); + NetDest net_msg_dest = net_msg_ptr->getInternalDestination(); + Vector dest_nodes = net_msg_dest.getAllDest(); // gets all the destinations associated with this message. + + int num_flits = (int) ceil((double) MessageSizeType_to_int(net_msg_ptr->getMessageSize())/NetworkConfig::getFlitSize() ); // Number of flits is dependent on the link bandwidth available. This is expressed in terms of bytes/cycle or the flit size + + for(int ctr = 0; ctr < dest_nodes.size(); ctr++) // loop because we will be converting all multicast messages into unicast messages + { + int vc = calculateVC(vnet); // this will return a free output virtual channel + if(vc == -1) + { + return false ; + } + MsgPtr new_msg_ptr = *(msg_ptr.ref()); + NodeID destID = dest_nodes[ctr]; + + NetworkMessage *new_net_msg_ptr = dynamic_cast(new_msg_ptr.ref()); + if(dest_nodes.size() > 1) + { + NetDest personal_dest; + for(int m = 0; m < (int) MachineType_NUM; m++) + { + if((destID >= MachineType_base_number((MachineType) m)) && destID < MachineType_base_number((MachineType) (m+1))) + { + // calculating the NetDest associated with this destination ID + personal_dest.clear(); + personal_dest.add((MachineID) {(MachineType) m, (destID - MachineType_base_number((MachineType) m))}); + new_net_msg_ptr->getInternalDestination() = personal_dest; + break; + } + } + net_msg_dest.removeNetDest(personal_dest); + net_msg_ptr->getInternalDestination().removeNetDest(personal_dest); // removing the destination from the original message to reflect that a message with this particular destination has been flitisized and an output vc is acquired + } + for(int i = 0; i < num_flits; i++) + { + m_net_ptr->increment_injected_flits(); + flit_d *fl = new flit_d(i, vc, vnet, num_flits, new_msg_ptr); + fl->set_delay(g_eventQueue_ptr->getTime() - (msg_ptr.ref())->getTime()); + m_ni_buffers[vc]->insert(fl); + } + m_ni_enqueue_time[vc] = g_eventQueue_ptr->getTime(); + m_out_vc_state[vc]->setState(ACTIVE_, g_eventQueue_ptr->getTime()); + } + return true ; +} + +// Looking for a free output vc +int NetworkInterface_d::calculateVC(int vnet) +{ + for(int i = 0; i < m_vc_per_vnet; i++) + { + int delta = m_vc_allocator[vnet]; + m_vc_allocator[vnet]++; + if(m_vc_allocator[vnet] == m_vc_per_vnet) + m_vc_allocator[vnet] = 0; + + if(m_out_vc_state[(vnet*m_vc_per_vnet) + delta]->isInState(IDLE_, g_eventQueue_ptr->getTime())) + { + return ((vnet*m_vc_per_vnet) + delta); + } + } + return -1; +} + +/* + * The NI wakeup checks whether there are any ready messages in the protocol buffer. If yes, + * it picks that up, flitisizes it into a number of flits and puts it into an output buffer + * and schedules the output link. On a wakeup it also checks whether there are flits in the + * input link. If yes, it picks them up and if the flit is a tail, the NI inserts the + * corresponding message into the protocol buffer. It also checks for credits being sent + * by the downstream router. + */ + +void NetworkInterface_d::wakeup() +{ + DEBUG_EXPR(NETWORK_COMP, MedPrio, m_id); + DEBUG_MSG(NETWORK_COMP, MedPrio, "NI WOKE UP"); + DEBUG_EXPR(NETWORK_COMP, MedPrio, g_eventQueue_ptr->getTime()); + + MsgPtr msg_ptr; + + //Checking for messages coming from the protocol + for (int vnet = 0; vnet < m_virtual_networks; vnet++) // can pick up a message/cycle for each virtual net + { + while(inNode_ptr[vnet]->isReady()) // Is there a message waiting + { + msg_ptr = inNode_ptr[vnet]->peekMsgPtr(); + if(flitisizeMessage(msg_ptr, vnet)) + { + inNode_ptr[vnet]->pop(); + } + else + { + break; + } + } + } + + scheduleOutputLink(); + checkReschedule(); + +/*********** Picking messages destined for this NI **********/ + + if(inNetLink->isReady()) + { + flit_d *t_flit = inNetLink->consumeLink(); + bool free_signal = false; + if(t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) + { + free_signal = true; + if(!NetworkConfig::isNetworkTesting()) // When we are doing network only testing, the messages do not have to be buffered into the message buffers + { + outNode_ptr[t_flit->get_vnet()]->enqueue(t_flit->get_msg_ptr(), 1); // enqueueing for protocol buffer. This is not required when doing network only testing + } + } + flit_d *credit_flit = new flit_d(t_flit->get_vc(), free_signal); // Simply send a credit back since we are not buddering this flit in the NI + creditQueue->insert(credit_flit); + g_eventQueue_ptr->scheduleEvent(m_ni_credit_link, 1); + + m_net_ptr->increment_recieved_flits(); + int network_delay = g_eventQueue_ptr->getTime() - t_flit->get_enqueue_time(); + int queueing_delay = t_flit->get_delay(); + m_net_ptr->increment_network_latency(network_delay); + m_net_ptr->increment_queueing_latency(queueing_delay); + delete t_flit; + } + + /****************** Checking for credit link *******/ + + if(m_credit_link->isReady()) + { + flit_d *t_flit = m_credit_link->consumeLink(); + m_out_vc_state[t_flit->get_vc()]->increment_credit(); + if(t_flit->is_free_signal()) + { + m_out_vc_state[t_flit->get_vc()]->setState(IDLE_, g_eventQueue_ptr->getTime()); + } + delete t_flit; + } +} + +// This function look at the NI buffers and if some buffer has flits which are ready to traverse the link in the next cycle and also the downstream output vc associated with this flit has buffers left, the link is scheduled for the next cycle + +void NetworkInterface_d::scheduleOutputLink() +{ + int vc = m_vc_round_robin; + m_vc_round_robin++; + if(m_vc_round_robin == m_num_vcs) + m_vc_round_robin = 0; + + for(int i = 0; i < m_num_vcs; i++) + { + vc++; + if(vc == m_num_vcs) + vc = 0; + if(m_ni_buffers[vc]->isReady() && m_out_vc_state[vc]->has_credits()) // models buffer backpressure + { + bool is_candidate_vc = true; + int t_vnet = get_vnet(vc); + int vc_base = t_vnet * m_vc_per_vnet; + + if(m_net_ptr->isVNetOrdered(t_vnet)) + { + for (int vc_offset = 0; vc_offset < m_vc_per_vnet; vc_offset++) + { + int t_vc = vc_base + vc_offset; + if(m_ni_buffers[t_vc]->isReady()) + { + if(m_ni_enqueue_time[t_vc] < m_ni_enqueue_time[vc]) + { + is_candidate_vc = false; + break; + } + } + } + } + if(!is_candidate_vc) + continue; + + m_out_vc_state[vc]->decrement_credit(); + flit_d *t_flit = m_ni_buffers[vc]->getTopFlit(); // Just removing the flit + t_flit->set_time(g_eventQueue_ptr->getTime() + 1); + outSrcQueue->insert(t_flit); + g_eventQueue_ptr->scheduleEvent(outNetLink, 1); // schedule the out link + + if(t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) + { + m_ni_enqueue_time[vc] = INFINITE_; + } + return; + } + } +} + +int NetworkInterface_d::get_vnet(int vc) +{ + for(int i = 0; i < NUMBER_OF_VIRTUAL_NETWORKS; i++) + { + if(vc >= (i*m_vc_per_vnet) && vc < ((i+1)*m_vc_per_vnet)) + { + return i; + } + } + ERROR_MSG("Could not determine vc"); + return -1; +} + +void NetworkInterface_d::checkReschedule() +{ + for(int vnet = 0; vnet < m_virtual_networks; vnet++) + { + if(inNode_ptr[vnet]->isReady()) // Is there a message waiting + { + g_eventQueue_ptr->scheduleEvent(this, 1); + return; + } + } + for(int vc = 0; vc < m_num_vcs; vc++) + { + if(m_ni_buffers[vc]->isReadyForNext()) + { + g_eventQueue_ptr->scheduleEvent(this, 1); + return; + } + } +} + +void NetworkInterface_d::printConfig(ostream& out) const +{ + out << "[Network Interface " << m_id << "] - "; + out << "[inLink " << inNetLink->get_id() << "] - "; + out << "[outLink " << outNetLink->get_id() << "]" << endl; +} + +void NetworkInterface_d::print(ostream& out) const +{ + out << "[Network Interface]"; +} diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.hh b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.hh new file mode 100644 index 000000000..c776d343c --- /dev/null +++ b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.hh @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * NetworkInterface_d.h + * + * Niket Agarwal, Princeton University + * + * */ + +#ifndef NET_INTERFACE_D_H +#define NET_INTERFACE_D_H + +#include "NetworkHeader.hh" +#include "GarnetNetwork_d.hh" +#include "Vector.hh" +#include "Consumer.hh" +#include "Message.hh" +#include "NetworkLink_d.hh" +#include "CreditLink_d.hh" +#include "OutVcState_d.hh" + +class NetworkMessage; +class MessageBuffer; +class flitBuffer_d; + +class NetworkInterface_d : public Consumer { +public: + NetworkInterface_d(int id, int virtual_networks, GarnetNetwork_d* network_ptr); + + ~NetworkInterface_d(); + + void addInPort(NetworkLink_d *in_link, CreditLink_d *credit_link); + void addOutPort(NetworkLink_d *out_link, CreditLink_d *credit_link); + + void wakeup(); + void addNode(Vector &inNode, Vector &outNode); + void printConfig(ostream& out) const; + void print(ostream& out) const; + int get_vnet(int vc); + +private: +/**************Data Members*************/ + GarnetNetwork_d *m_net_ptr; + int m_virtual_networks, m_num_vcs, m_vc_per_vnet; + NodeID m_id; + Vector m_out_vc_state; + Vector m_vc_allocator; + int m_vc_round_robin; // For round robin scheduling + flitBuffer_d *outSrcQueue; // For modelling link contention + flitBuffer_d *creditQueue; + + NetworkLink_d *inNetLink; + NetworkLink_d *outNetLink; + CreditLink_d *m_credit_link; + CreditLink_d *m_ni_credit_link; + + // Input Flit Buffers + Vector m_ni_buffers; // The flit buffers which will serve the Consumer + Vector