├── ConfigDRAM.ini ├── ConfigSim.ini ├── LICENSE ├── Makefile ├── README ├── graph ├── example_CasHMC_plot_no0.dat └── example_CasHMC_plot_no0.gnuplot ├── integration └── gem5 │ ├── SConscript_CasHMC │ ├── integ_CasHMC-gem5.sh │ └── mem │ ├── DRAMSim2.py │ ├── dramsim2.cc │ ├── dramsim2.hh │ ├── dramsim2_wrapper.cc │ └── dramsim2_wrapper.hh ├── result ├── example_CasHMC_no0_result.log └── example_CasHMC_no0_setting.log ├── sources ├── BankState.cpp ├── BankState.h ├── CallBack.h ├── CasHMCWrapper.cpp ├── CasHMCWrapper.h ├── CommandQueue.cpp ├── CommandQueue.h ├── ConfigReader.cpp ├── ConfigReader.h ├── ConfigValue.h ├── CrossbarSwitch.cpp ├── CrossbarSwitch.h ├── DRAM.cpp ├── DRAM.h ├── DRAMCommand.cpp ├── DRAMCommand.h ├── DualVectorObject.h ├── HMC.cpp ├── HMC.h ├── HMCController.cpp ├── HMCController.h ├── Link.cpp ├── Link.h ├── LinkMaster.cpp ├── LinkMaster.h ├── LinkSlave.cpp ├── LinkSlave.h ├── Packet.cpp ├── Packet.h ├── RunSim.cpp ├── SimulatorObject.h ├── SingleVectorObject.h ├── TranStatistic.h ├── TranTrace.h ├── Transaction.cpp ├── Transaction.h ├── VaultController.cpp └── VaultController.h └── trace ├── SPEC_CPU2006_example ├── mase_trace_bwaves_base.alpha.v0.trc ├── mase_trace_bzip2_base.alpha.v0.trc ├── mase_trace_gobmk_base.alpha.v0.trc ├── mase_trace_gromacs_base.alpha.v0.trc ├── mase_trace_hmmer_base.alpha.v0.trc ├── mase_trace_lbm_base.alpha.v0.trc ├── mase_trace_mcf_base.alpha.v0.trc ├── mase_trace_milc_base.alpha.v0.trc ├── mase_trace_sjeng_base.alpha.v0.trc └── mase_trace_zeusmp_base.alpha.v0.trc ├── trace.trc └── trace_generator ├── Makefile └── TraceGen.cpp /ConfigDRAM.ini: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | //ConfigDRAM.ini 13 | 14 | MEMORY_DENSITY = 4; //[GB] Note that it needs to change the below vaules 15 | NUM_VAULTS = 32; 16 | NUM_BANKS = 8; //The number of banks per a vault (4GB:8 banks, 8GB:16 banks) 17 | NUM_ROWS = 16384; //one bank size is 16MB 18 | NUM_COLS = 1024; //Byte addressing 19 | 20 | ADDRESS_MAPPING = MAX_BLOCK_32B; //(MAX_BLOCK_32B, MAX_BLOCK_64B, MAX_BLOCK_128B, MAX_BLOCK_256B) 21 | 22 | QUE_PER_BANK = true; //Command queue structure (If true, every bank has respective command queue [Bank-Level parallelism]) 23 | OPEN_PAGE = true; //Whether open page policy or close page policy 24 | MAX_ROW_ACCESSES = 8; //The number of consecutive access to identical row address (It should be bigger than max block(ADDRESS_MAPPING) / 32) 25 | USE_LOW_POWER = true; //Power-down mode setting 26 | 27 | // 28 | //DRAM Timing (HMC_2500_x32(DDR3_1600_x64) - Gem5 HMC modeling) 29 | // 30 | REFRESH_PERIOD = 7800; 31 | 32 | //CLOCK PERIOD [ns] 33 | tCK = 0.8; //1250 MHz 34 | 35 | CWL = 3.2; //(CAS WRITE latency (CWL)) 36 | CL = 9.9; //(CAS (READ) latency) 37 | AL = 0.0; //(Additive Latency) 38 | tRAS = 21.6; //(ACTIVE-to-PRECHARGE command) 39 | tRCD = 10.2; //(ACTIVE-to-READ or WRITE delay) 40 | tRRD = 3.2; //(ACTIVE bank a to ACTIVE bank b command) 41 | tRC = 32.0; //(ACTIVE-to-ACTIVE/AUTO REFRESH command period) 42 | tRP = 7.7; //(PRECHARGE command period) 43 | tCCD = 3.2; //(CAS#-to-CAS# delay) 44 | tRTP = 4.9; //(Internal READ-to-PRECHARGE delay) 45 | tWTR = 4.9; //(Internal WRITE-to-READ command delay) 46 | tWR = 8.0; //(Write recovery time) 47 | tRTRS = 0.8; //(rank to rank switching time [consecutive read commands to different ranks]) 48 | tRFC = 59.0; //(AUTO REFRESH command period) 49 | tFAW = 19.2; //(4-bank activate period) 50 | tCKE = 3.6; //(CKE MIN HIGH/LOW time) 51 | tXP = 3.2; 52 | tCMD = 0.8; -------------------------------------------------------------------------------- /ConfigSim.ini: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | //ConfigSim.ini 13 | 14 | // 15 | //Simulation setting 16 | // 17 | LOG_EPOCH = 1000000; 18 | DEBUG_SIM = false; //Debug log file generation (true / false) 19 | ONLY_CR = false; //Print only critical debug (true / false) 20 | STATE_SIM = false; //State log file generation (true / false) 21 | PLOT_SAMPLING = 10000; //[cycle] Bandwidth graph data time unit 22 | BANDWIDTH_PLOT = true; //Bandwidth graph files generation (true / false) 23 | 24 | 25 | // 26 | //Memory transaction setting 27 | // 28 | CPU_CLK_PERIOD = 1; //[ns] CPU clock period in nanoseconds 29 | TRANSACTION_SIZE = 64; //[byte] Data size of DRAM request (the internal 32-byte granularity of the DRAM data bus within each vault in the HMC) 30 | MAX_REQ_BUF = 16; //[transaction] Request buffer size in HMC controller 31 | 32 | 33 | // 34 | //Link(SerDes) setting 35 | // 36 | NUM_LINKS = 4; //The number of links 37 | LINK_WIDTH = 4; //Full-Width(16-lane), Half-width(8-lane), and quarter-width link(4-lane) 38 | LINK_SPEED = 12.5; //[Gb/s] (12.5, 15, 25, 28, 30) 39 | 40 | MAX_LINK_BUF = 32; //[packet] Link master output buffer and Link slave input buffer size (one buffer space is for 1 unit packet (128 bits) ) 41 | //// the minimum packet length is 17 FLITs (256-byte WRITE request) 42 | MAX_RETRY_BUF = 32; //[packet] Retry buffer size in link mater (one buffer space is for 1 unit packet (128 bits) ) 43 | //// retry buffer that can hold up to 512 FLITs [Hybrid Memory Cube Specification 2.1 p.93] 44 | MAX_VLT_BUF = 32; //[packet] Vault controller buffer size (one buffer space is for 1 unit packet (128 bits) ) 45 | MAX_CROSS_BUF = 64; //[packet] Crossbar switch buffer size (one buffer space is for 1 unit packet (128 bits) ) 46 | MAX_CMD_QUE = 16; //[Command] Command queue size (the minimum is 8 due to 256-byte request [max data size(256) / min address mapping block size(32)]) 47 | 48 | CRC_CHECK = true; //CRC checking enable (true / false) 49 | CRC_CAL_CYCLE = 0.01; //[clock] CPU clock cycles to calculate CRC value of one packet (128 bits) 50 | //// '0' of CRC_CAL_CYCLE means that CRC calculation delay is completely hidden in transmitting packet header 51 | //// (the beginning of the packet may have been forwarded before the CRC was performed at the tail, to minimize latency ) 52 | 53 | NUM_OF_IRTRY = 2; //The number of single-FLIT IRTRY packets to be transmitted during StartRetry sequence 54 | RETRY_ATTEMPT_LIMIT = 2; //The number of retry attempts when the retry timer is time-out 55 | LINK_BER = -14; //[the power of 10] High speed serial links (SerDes) require the Bit Error Rate (BER) to be at the level of 10^-12 or lower. 56 | //// For a standard like Gigabit Ethernet (Data rate = 1.25Gbps), that specifies a bit error rate of less than 10^-12 57 | ////(NOTE!! it shoud be below than -15) 58 | 59 | LINK_PRIORITY = ROUND_ROBIN;//Link packet scheduling scheme (ROUND_ROBIN / BUFFER_AWARE) 60 | LINK_POWER = LINK_MONITOR; //Link power state management (NO_MANAGEMENT / QUIESCE_SLEEP / MSHR / LINK_MONITOR / AUTONOMOUS) 61 | //// MSHR and AUTONOMOUS management require to use 'UpdateMSHR' function in 'CasHMCWrapper.cpp' file 62 | AWAKE_REQ = 8; //The number of reqeusts in HMC controller to wake up the link from sleep to active mode 63 | LINK_EPOCH = 1; //[ms] One epoch time to measure HMC bandwidth for link power management (for BANDWIDTH_AWARE and BANDWIDTH_SAT_CNT) 64 | MSHR_SCALING = 1; //Scaling factor of the MSHR (for MSHR and AUTONOMOUS) 65 | LINK_SCALING = 4; //Scaling factor of the link monitor (for LINK_MONITOR and AUTONOMOUS) 66 | 67 | 68 | // 69 | //Link(SerDes) power state parameter 70 | // 71 | 72 | //Low power (Sleep & Down) mode power parameter 73 | PowPerLane = 5; //[mW/Gb] The power dissipation in normal operation 74 | SleepPow = 10; //[%] The proportion of power consumption in sleep mode 75 | DownPow = 1; //[%] The proportion of power consumption in down mode 76 | 77 | //Low power (Sleep & Down) mode entry timing [ns] 78 | tPST = 1500; //Power state transition timing 79 | tSME = 400; //Sleep mode entry 80 | tSS = 500; //Simultaneous power transition stagger 81 | tSD = 150000; //Time to transition links from sleep mode to down mode 82 | tSREF = 1000000; //Time required to stay in self refresh 83 | tOP = 1000000; //Time required to stay within active mode 84 | tQUIESCE = 1000; //The quiesced link traffic to enter sleep or down mode 85 | 86 | //Low power (Sleep & Down) mode exit timing [ns] 87 | tTXD = 50000; //Low power exit timing (transition of LxTXPS to TX PRBS) 88 | tRESP1 = 1000000; //Link receiver-phase acquisition (no DFE) 89 | tRESP2 = 4000; //FLIT synchronization time 90 | tPSC = 3000; //SerDes PLL self calibration timing -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * Copyright 2016, Dong-Ik Jeon 3 | * Ki-Seok Chung 4 | * Hanyang University 5 | * estwings57 [at] gmail [dot] com 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without modification, 9 | * are permitted provided that the following conditions are met: 10 | * 11 | * 1. Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * CasHMC refers to DRAMSim simulator. 29 | * The following is the detailed DRAMSim copyright. 30 | * 31 | * ================================================================================== 32 | * DRAMSim Copyright (c) 2010-2011, Elliott Cooper-Balis 33 | * Paul Rosenfeld 34 | * Bruce Jacob 35 | * University of Maryland 36 | * dramninjas [at] gmail [dot] com 37 | * All rights reserved. 38 | * ================================================================================== 39 | *********************************************************************************/ -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ################################################################################## 2 | # CasHMC v1.3 - 2017.07.10 3 | # A Cycle-accurate Simulator for Hybrid Memory Cube 4 | # 5 | # Copyright 2016, Dong-Ik Jeon 6 | # Ki-Seok Chung 7 | # Hanyang University 8 | # estwings57 [at] gmail [dot] com 9 | # All rights reserved. 10 | ################################################################################## 11 | 12 | CXXFLAGS=-O3 -g -DDEBUG_LOG 13 | EXE_NAME=CasHMC 14 | LIB_NAME=libcashmc.so 15 | STATIC_LIB_NAME := libcashmc.a 16 | LIB_NAME_MACOS=libcashmc.dylib 17 | SRCDIR=sources 18 | 19 | SRC = $(wildcard $(SRCDIR)/*.cpp) 20 | OBJ = $(addsuffix .o, $(basename $(SRC))) 21 | 22 | LIB_SRC := $(filter-out RunSim.cpp,$(SRC)) 23 | LIB_OBJ := $(addsuffix .o, $(basename $(LIB_SRC))) 24 | 25 | #build portable objects (i.e. with -fPIC) 26 | POBJ = $(addsuffix .po, $(basename $(LIB_SRC))) 27 | 28 | REBUILDABLES=$(OBJ) $(POBJ) $(EXE_NAME) $(LIB_NAME) $(STATIC_LIB_NAME) $(LIB_NAME_MACOS) 29 | 30 | all: $(EXE_NAME) 31 | 32 | # $@ target name, $^ target deps, $< matched pattern 33 | $(EXE_NAME): $(OBJ) 34 | $(CXX) $(LINK_FLAGS) -o $@ $^ 35 | @echo "Built $@ successfully" 36 | 37 | $(LIB_NAME): $(POBJ) 38 | g++ -g -shared -Wl,-soname,$@ -o $@ $^ 39 | @echo "Built $@ successfully" 40 | 41 | $(STATIC_LIB_NAME): $(LIB_OBJ) 42 | $(AR) crs $@ $^ 43 | 44 | $(LIB_NAME_MACOS): $(POBJ) 45 | g++ -dynamiclib -o $@ $^ 46 | @echo "Built $@ successfully" 47 | 48 | #include the autogenerated dependency files for each .o file 49 | -include $(OBJ:.o=.dep) 50 | -include $(POBJ:.po=.deppo) 51 | 52 | # build dependency list via gcc -M and save to a .dep file 53 | %.dep : %.cpp 54 | @$(CXX) -M $(CXXFLAGS) $< > $@ 55 | 56 | %.deppo : %.cpp 57 | @$(CXX) -M $(CXXFLAGS) -MT"$*.po" $< > $@ 58 | 59 | # build all .cpp files to .o files 60 | %.o : %.cpp 61 | g++ $(CXXFLAGS) -o $@ -c $< 62 | 63 | #po = portable object .. for lack of a better term 64 | %.po : %.cpp 65 | g++ $(CXXFLAGS) -DLOG_OUTPUT -fPIC -o $@ -c $< 66 | 67 | clean: 68 | -rm -f $(REBUILDABLES) $(SRCDIR)/*.dep $(SRCDIR)/*.deppo 69 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | CasHMC: A Cycle-accurate Simulator for Hybrid Memory Cube 2 | version CasHMC v1.3 - 2017.07.10 3 | 4 | 1. Developer 5 | 6 | Dong-Ik Jeon 7 | Ki-Seok Chung 8 | Hanyang University 9 | estwings57 [at] gmail [dot] com 10 | 11 | 12 | 2. About CasHMC 13 | 14 | CasHMC provides a cycle-by-cycle simulation of every module in HMC, and 15 | generates analysis results including a bandwidth graph and statistical data. 16 | It supports HMC unique features, such as the high speed serial link, 17 | the packet-based interface, and the vault-based DRAM structure. Since CasHMC 18 | simulates all HMC modules at a cycle-accurate level, it is capable of deriving 19 | precise simulation results and analyses. 20 | 21 | Furthemore, CasHMC is implemented in C++ as a single wrapped object that 22 | includes a HMC controller, communication links, and the HMC memory. 23 | Instantiating this single wrapped object facilitates simultaneous simulation 24 | in parallel with other simulators that generate memory access patterns 25 | such as a processor simulator or a memory trace generator. 26 | 27 | 28 | 3. CasHMC version info 29 | 30 | v1.0 (2016.05.07 released) 31 | - Released the 1st CasHMC 32 | - Modeling HMC architecture and packet-based interface 33 | 34 | v1.1 (2016.07.21 released) 35 | - Support 'atomic commands' refered to HMC specification 2.1 (arithmetic, bitwise, boolean, comparison) 36 | for more information, check Transaction.h (TransactionType) or RunSim.cpp (line 86) 37 | 38 | v1.2 (2016.09.27 released) 39 | - Modify vault mapping (CrossbarSwitch) of the packet bigger than the maximum block size 40 | - Support a new link priority scheme (buffer-aware scheme) 41 | - Add one cycle delay for an atomic command operation in VaultController class (atomicOperLeft) 42 | - Minor revision (few mistakes) 43 | 44 | v1.3 (2017.07.10 released) 45 | - Integrated with gem5 simulator 46 | * Configure parameters loading at the runtime (parameters in ConfigSim.ini and ConfigDRAM.ini files) 47 | * Static and dynamic library compilation by Makefile 48 | - Link power consumption simulation is added (configured by link power parameter in ConfigSim.ini file) 49 | - Support various link power managements 50 | * QUIESCE_SLEEP : on the basis of the tQUIESCE that is the time interval to enter link lowe power mode 51 | * MSHR : the number of active links is decided by the number of the allocated MSHR 52 | * LINK_MONITOR : the number of active links is decided by the derived downstream and upstream link bandwidth 53 | * AUTONOMOUS : MSHR and LINK_MONITOR together 54 | - Minor revision 55 | 56 | 57 | 4. Getting CasHMC 58 | 59 | CasHMC is available on github. 60 | https://github.com/estwings57/CasHMC 61 | 62 | 63 | 5. Folder directory 64 | 65 | graph : Gnuplot script file and a graph data file after a simulation run is over 66 | result : Log files after a simulation run is over 67 | sources : All CasHMC source files 68 | trace : The example of trace files (The files are extracted from SPEC CPU2006 benchmarks) 69 | 70 | 71 | 6. Building CasHMC 72 | 73 | To build an optimized CasHMC 74 | 75 | $ make 76 | 77 | 78 | 7. Running CasHMC 79 | 80 | > Command line arguments 81 | 82 | -c (--cycle) : The number of CPU cycles to be simulated 83 | -t (--trace) : Trace type ('random' or 'file') 84 | -u (--util) : Requests frequency (0 = no requests, 1 = as fast as possible) [Default 0.1] 85 | -r (--rwratio) : (%) The percentage of reads in request stream [Default 80] 86 | -f (--file) : Trace file name 87 | -h (--help) : Simulation option help 88 | 89 | > The example of trace generator mode 90 | 91 | $ ./CasHMC -c 100000 -t random -u 0.1 -r 60 92 | 93 | > The example of trace file mode 94 | 95 | $ ./CasHMC -c 100000 -t file -f ./trace/SPEC_CPU2006_example/mase_trace_bzip2_base.alpha.v0.trc 96 | 97 | > The example of CasHMCWrapper object instantiating 98 | 99 | In a source file 100 | 101 | #include "CasHMCWrapper.h“ 102 | #include "Transaction.h" 103 | ... 104 | 105 | CasHMCWrapper *casHMCWrapper = new CasHMCWrapper("ConfigSim.ini", "ConfigDRAM.ini"); 106 | ... 107 | 108 | TransactionType tranType = DATA_READ; 109 | uint64_t physicalAddress = 0x0123456789abcdef; 110 | unsigned dataSize = 32; 111 | Transaction *newTran = new Transaction(tranType, addr, dataSize, casHMCWrapper); 112 | casHMCWrapper->ReceiveTran(newTran); 113 | ... 114 | 115 | > Integration with gem5 simulator 116 | 117 | There is a script file [CasHMC/integration/gem5/integ_CasHMC-gem5.sh] for integrating CasHMC and gem5 118 | Copy this script file to gem5 root directory and then run the script 119 | (gem5 download : $ hg clone http://repo.gem5.org/gem5) 120 | 121 | $ cp -a CasHMC/integration/gem5/integ_CasHMC-gem5.sh $GEM5_DIR 122 | $ source $GEM5_DIR/integ_CasHMC-gem5.sh 123 | 124 | 125 | 8. Special thanks to 126 | 127 | HyeJin Choi, 128 | Kyeong-Bin Park 129 | -------------------------------------------------------------------------------- /graph/example_CasHMC_plot_no0.dat: -------------------------------------------------------------------------------- 1 | #Epoch Link[0] Link[1] Link[2] Link[3] HMC bandwidth 2 | 1 0.357628 0.357628 0.357628 0.351667 1.42455 3 | 2 0.339746 0.786781 0.566244 0.560284 2.25306 4 | 3 0 1.14441 0.572205 0.572205 2.29478 5 | 4 0 1.15037 0.572205 0.578165 2.29478 6 | 5 0 1.14441 0.572205 0.572205 2.28882 7 | 6 0 1.15037 0.578165 0.572205 2.28882 8 | 7 0 1.14441 0.572205 0.572205 2.30074 9 | 8 0 1.14441 0.572205 0.572205 2.28882 10 | 9 0 1.14441 0.572205 0.572205 2.28882 11 | -------------------------------------------------------------------------------- /graph/example_CasHMC_plot_no0.gnuplot: -------------------------------------------------------------------------------- 1 | set term png size 800, 500 font "Times-Roman," 2 | set output 'CasHMC_plot_no0.png' 3 | set title "CasHMC bandwidth graph" font ",18" 4 | set autoscale 5 | set grid 6 | set xlabel "Simulation plot epoch" 7 | set ylabel "Bandwidth [GB/s]" 8 | set key left box 9 | plot "CasHMC_plot_no0.dat" using 1:6 title 'HMC' with lines lw 2 , \ 10 | "CasHMC_plot_no0.dat" using 1:2 title 'Link[0]' with lines lw 1 , \ 11 | "CasHMC_plot_no0.dat" using 1:3 title 'Link[1]' with lines lw 1 , \ 12 | "CasHMC_plot_no0.dat" using 1:4 title 'Link[2]' with lines lw 1 , \ 13 | "CasHMC_plot_no0.dat" using 1:5 title 'Link[3]' with lines lw 1 , \ 14 | -------------------------------------------------------------------------------- /integration/gem5/SConscript_CasHMC: -------------------------------------------------------------------------------- 1 | # -*- mode:python -*- 2 | 3 | # Copyright (c) 2013 ARM Limited 4 | # All rights reserved. 5 | # 6 | # The license below extends only to copyright in the software and shall 7 | # not be construed as granting a license to any other intellectual 8 | # property including but not limited to intellectual property relating 9 | # to a hardware implementation of the functionality of the software 10 | # licensed hereunder. You may use the software subject to the license 11 | # terms below provided that you ensure that this notice is replicated 12 | # unmodified and in its entirety in all distributions of the software, 13 | # modified or unmodified, in source code or in binary form. 14 | # 15 | # Redistribution and use in source and binary forms, with or without 16 | # modification, are permitted provided that the following conditions are 17 | # met: redistributions of source code must retain the above copyright 18 | # notice, this list of conditions and the following disclaimer; 19 | # redistributions in binary form must reproduce the above copyright 20 | # notice, this list of conditions and the following disclaimer in the 21 | # documentation and/or other materials provided with the distribution; 22 | # neither the name of the copyright holders nor the names of its 23 | # contributors may be used to endorse or promote products derived from 24 | # this software without specific prior written permission. 25 | # 26 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | # 38 | # Authors: Andreas Hansson 39 | 40 | import os 41 | 42 | Import('main') 43 | 44 | # See if we got a cloned CasHMC repo as a subdirectory and set the 45 | # HAVE_DRAMSIM flag accordingly 46 | if not os.path.exists(Dir('.').srcnode().abspath + '/CasHMC'): 47 | main['HAVE_DRAMSIM'] = False 48 | Return() 49 | 50 | # We have got the folder, so add the library and build the wrappers 51 | main['HAVE_DRAMSIM'] = True 52 | 53 | # Add the appropriate files. We leave out the trace driven simulator 54 | casHMC_files = [] 55 | 56 | def DRAMFile(filename): 57 | casHMC_files.append(File('CasHMC/sources/' + filename)) 58 | 59 | DRAMFile('BankState.cpp') 60 | DRAMFile('CasHMCWrapper.cpp') 61 | DRAMFile('CommandQueue.cpp') 62 | DRAMFile('ConfigReader.cpp') 63 | DRAMFile('CrossbarSwitch.cpp') 64 | DRAMFile('DRAM.cpp') 65 | DRAMFile('DRAMCommand.cpp') 66 | DRAMFile('HMC.cpp') 67 | DRAMFile('HMCController.cpp') 68 | DRAMFile('Link.cpp') 69 | DRAMFile('LinkMaster.cpp') 70 | DRAMFile('LinkSlave.cpp') 71 | DRAMFile('Packet.cpp') 72 | DRAMFile('Transaction.cpp') 73 | DRAMFile('VaultController.cpp') 74 | 75 | casHMCenv = main.Clone() 76 | casHMCenv.Append(CCFLAGS=['-DDEBUG_LOG']) 77 | # CasHMC violates some of the warning flags used by gem5, so 78 | # we explicitly disable them here 79 | casHMCenv.Append(CCFLAGS=['-Wno-unused-value']) 80 | 81 | # If we are using clang, there are more flags to disable 82 | if main['CLANG']: 83 | casHMCenv.Append(CCFLAGS=['-Wno-unused-private-field', 84 | '-Wno-tautological-undefined-compare']) 85 | 86 | casHMCenv.Library('libcashmc', [casHMCenv.SharedObject(f) for f in casHMC_files]) 87 | 88 | main.Prepend(CPPPATH=Dir('.')) 89 | main.Append(LIBS=['libcashmc']) 90 | main.Prepend(LIBPATH=[Dir('.')]) 91 | -------------------------------------------------------------------------------- /integration/gem5/integ_CasHMC-gem5.sh: -------------------------------------------------------------------------------- 1 | # Script for integrating CasHMC and gem5 2 | # 3 | # CasHMC is integrated with gem5 by DRAMSim2 wrapper which is provided by gem5 simulator 4 | # in order to minimize modification of gem5 files. 5 | # We used DRAMSim2 wrappper class and ext/dramsim2 folder location in the same way as before. 6 | # All original DRAMSim2 files are made backup copy [*_backup.*] 7 | # 8 | # This script file should be run in gem5 root directory 9 | # (ex: source gem5/integ_CasHMC-gem5.sh) 10 | # 11 | # Copyright (C) 2017, by Dongik Jeon. All rights reserved 12 | 13 | # Path(directory) variables 14 | CURRENT_PATH=$(pwd) 15 | MEM_PATH=${CURRENT_PATH}/src/mem 16 | CASHMC_PATH=${CURRENT_PATH}/ext/dramsim2 17 | CONFIG_FILE=${CASHMC_PATH}/CasHMC/ConfigSim.ini 18 | TRANS_SIZE=64 # It should be the same as the last level cache block size 19 | 20 | 21 | echo "" 22 | echo "=======================================================" 23 | echo " Script for integrating CasHMC and gem5" 24 | date "+ time : %c" 25 | echo "======================================================" 26 | echo "" 27 | 28 | 29 | echo "----------------- gem5 folder check -----------------" 30 | if [ -d "$MEM_PATH" ]; then 31 | echo " folder exist [${MEM_PATH}]" 32 | if [ -d "$CASHMC_PATH" ]; then 33 | echo " folder exist [${CASHMC_PATH}]" 34 | echo "" 35 | 36 | 37 | echo "--------------- Backup DRAMSim2 files ---------------" 38 | cd ${MEM_PATH} 39 | if [ -f dramsim2.hh ] && [ ! -f dramsim2_backup.hh ]; then 40 | mv dramsim2.hh dramsim2_backup.hh; fi 41 | if [ -f dramsim2.cc ] && [ ! -f dramsim2_backup.cc ]; then 42 | mv dramsim2.cc dramsim2_backup.cc; fi 43 | if [ -f DRAMSim2.py ] && [ ! -f DRAMSim2_backup.py ]; then 44 | mv DRAMSim2.py DRAMSim2_backup.py; fi 45 | if [ -f dramsim2_wrapper.hh ] && [ ! -f dramsim2_wrapper_backup.hh ]; then 46 | mv dramsim2_wrapper.hh dramsim2_wrapper_backup.hh; fi 47 | if [ -f dramsim2_wrapper.cc ] && [ ! -f dramsim2_wrapper_backup.cc ]; then 48 | mv dramsim2_wrapper.cc dramsim2_wrapper_backup.cc; fi 49 | echo " Creating backup copy of DRAMSim2 wrapper files" 50 | find ${MEM_PATH}/ -name "*_backup*" 51 | echo "" 52 | 53 | 54 | echo "------------------ Download CasHMC ------------------" 55 | cd ${CASHMC_PATH} 56 | git clone https://github.com/estwings57/CasHMC 57 | cp -a ${CASHMC_PATH}/CasHMC/integration/gem5/mem/* ${MEM_PATH} 58 | if [ -f SConscript ] && [ ! -f SConscript_backup ]; then 59 | mv ${CASHMC_PATH}/SConscript ${CASHMC_PATH}/SConscript_backup; fi 60 | cp -a ${CASHMC_PATH}/CasHMC/integration/gem5/SConscript_CasHMC ${CASHMC_PATH}/SConscript 61 | echo " -> Transantion size modification" 62 | echo " for matching cache block and memory request size" 63 | sed -i '29d' ${CONFIG_FILE} 64 | sed -i '29i\TRANSACTION_SIZE = '${TRANS_SIZE}'; //[byte] Data size of DRAM request (the internal 32-byte granularity of the DRAM data bus within each vault in the HMC)' ${CONFIG_FILE} 65 | echo " " 66 | 67 | 68 | echo "--------- Running hello example with CasHMC ---------" 69 | cd ${CURRENT_PATH} 70 | echo " -> Compile gem5" 71 | scons build/ARM/gem5.opt 72 | echo " -> Running hello example" 73 | echo "" 74 | build/ARM/gem5.opt --outdir=./result ./configs/example/se.py --cpu-type=DerivO3CPU --caches --mem-type=DRAMSim2 -c ./tests/test-progs/hello/bin/arm/linux/hello 75 | 76 | 77 | else 78 | echo " folder not exist [${CASHMC_PATH}]" 79 | fi 80 | else 81 | echo " folder not exist [${MEM_PATH}]" 82 | fi -------------------------------------------------------------------------------- /integration/gem5/mem/DRAMSim2.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 ARM Limited 2 | # All rights reserved. 3 | # 4 | # The license below extends only to copyright in the software and shall 5 | # not be construed as granting a license to any other intellectual 6 | # property including but not limited to intellectual property relating 7 | # to a hardware implementation of the functionality of the software 8 | # licensed hereunder. You may use the software subject to the license 9 | # terms below provided that you ensure that this notice is replicated 10 | # unmodified and in its entirety in all distributions of the software, 11 | # modified or unmodified, in source code or in binary form. 12 | # 13 | # Redistribution and use in source and binary forms, with or without 14 | # modification, are permitted provided that the following conditions are 15 | # met: redistributions of source code must retain the above copyright 16 | # notice, this list of conditions and the following disclaimer; 17 | # redistributions in binary form must reproduce the above copyright 18 | # notice, this list of conditions and the following disclaimer in the 19 | # documentation and/or other materials provided with the distribution; 20 | # neither the name of the copyright holders nor the names of its 21 | # contributors may be used to endorse or promote products derived from 22 | # this software without specific prior written permission. 23 | # 24 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 30 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | # 36 | # Authors: Andreas Hansson 37 | 38 | from m5.params import * 39 | from AbstractMemory import * 40 | 41 | # A wrapper for CasHMC simulator based on DRAMSim2 wrapper 42 | class DRAMSim2(AbstractMemory): 43 | type = 'DRAMSim2' 44 | cxx_header = "mem/dramsim2.hh" 45 | 46 | # A single port for now 47 | port = SlavePort("Slave port") 48 | 49 | configSimFile = Param.String("ConfigSim.ini", "Simulation configuration file") 50 | configDRAMFile = Param.String("ConfigDRAM.ini", "DRAM configuration file") 51 | filePath = Param.String("ext/dramsim2/CasHMC", "Directory to prepend to file names") -------------------------------------------------------------------------------- /integration/gem5/mem/dramsim2.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 ARM Limited 3 | * All rights reserved 4 | * 5 | * The license below extends only to copyright in the software and shall 6 | * not be construed as granting a license to any other intellectual 7 | * property including but not limited to intellectual property relating 8 | * to a hardware implementation of the functionality of the software 9 | * licensed hereunder. You may use the software subject to the license 10 | * terms below provided that you ensure that this notice is replicated 11 | * unmodified and in its entirety in all distributions of the software, 12 | * modified or unmodified, in source code or in binary form. 13 | * 14 | * Redistribution and use in source and binary forms, with or without 15 | * modification, are permitted provided that the following conditions are 16 | * met: redistributions of source code must retain the above copyright 17 | * notice, this list of conditions and the following disclaimer; 18 | * redistributions in binary form must reproduce the above copyright 19 | * notice, this list of conditions and the following disclaimer in the 20 | * documentation and/or other materials provided with the distribution; 21 | * neither the name of the copyright holders nor the names of its 22 | * contributors may be used to endorse or promote products derived from 23 | * this software without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | * 37 | * Authors: Andreas Hansson 38 | */ 39 | 40 | #include "mem/dramsim2.hh" 41 | 42 | #include "CasHMC/sources/CallBack.h" 43 | #include "base/callback.hh" 44 | #include "base/trace.hh" 45 | #include "debug/DRAMSim2.hh" 46 | #include "debug/Drain.hh" 47 | #include "sim/system.hh" 48 | 49 | DRAMSim2::DRAMSim2(const Params* p) : 50 | AbstractMemory(p), 51 | port(name() + ".port", *this), 52 | wrapper(p->configSimFile, p->configDRAMFile, p->filePath), 53 | retryReq(false), retryResp(false), startTick(0), 54 | nbrOutstandingReads(0), nbrOutstandingWrites(0), 55 | sendResponseEvent([this]{ sendResponse(); }, name()), 56 | tickEvent([this]{ tick(); }, name()) 57 | { 58 | DPRINTF(DRAMSim2, 59 | "Instantiated DRAMSim2 with clock %d ns and queue size %d\n", 60 | wrapper.clockPeriod(), wrapper.queueSize()); 61 | 62 | CasHMC::TransCompCB* read_cb = 63 | new CasHMC::Callback( 64 | this, &DRAMSim2::readComplete); 65 | CasHMC::TransCompCB* write_cb = 66 | new CasHMC::Callback( 67 | this, &DRAMSim2::writeComplete); 68 | 69 | wrapper.setCallbacks(read_cb, write_cb); 70 | 71 | // Register a callback to compensate for the destructor not 72 | // being called. The callback prints the DRAMSim2 stats. 73 | Callback* cb = new MakeCallback(wrapper); 75 | registerExitCallback(cb); 76 | } 77 | 78 | void 79 | DRAMSim2::init() 80 | { 81 | AbstractMemory::init(); 82 | 83 | if (!port.isConnected()) { 84 | fatal("DRAMSim2 %s is unconnected!\n", name()); 85 | } else { 86 | port.sendRangeChange(); 87 | } 88 | 89 | if (system()->cacheLineSize() != wrapper.burstSize()) 90 | fatal("DRAMSim2 burst size %d does not match cache line size %d\n", 91 | wrapper.burstSize(), system()->cacheLineSize()); 92 | } 93 | 94 | void 95 | DRAMSim2::startup() 96 | { 97 | startTick = curTick(); 98 | 99 | // kick off the clock ticks 100 | schedule(tickEvent, clockEdge()); 101 | } 102 | 103 | void 104 | DRAMSim2::sendResponse() 105 | { 106 | assert(!retryResp); 107 | assert(!responseQueue.empty()); 108 | 109 | DPRINTF(DRAMSim2, "Attempting to send response\n"); 110 | 111 | bool success = port.sendTimingResp(responseQueue.front()); 112 | if (success) { 113 | responseQueue.pop_front(); 114 | 115 | DPRINTF(DRAMSim2, "Have %d read, %d write, %d responses outstanding\n", 116 | nbrOutstandingReads, nbrOutstandingWrites, 117 | responseQueue.size()); 118 | 119 | if (!responseQueue.empty() && !sendResponseEvent.scheduled()) 120 | schedule(sendResponseEvent, curTick()); 121 | 122 | if (nbrOutstanding() == 0) 123 | signalDrainDone(); 124 | } else { 125 | retryResp = true; 126 | 127 | DPRINTF(DRAMSim2, "Waiting for response retry\n"); 128 | 129 | assert(!sendResponseEvent.scheduled()); 130 | } 131 | } 132 | 133 | unsigned int 134 | DRAMSim2::nbrOutstanding() const 135 | { 136 | return nbrOutstandingReads + nbrOutstandingWrites + responseQueue.size(); 137 | } 138 | 139 | void 140 | DRAMSim2::tick() 141 | { 142 | wrapper.tick(); 143 | 144 | // is the connected port waiting for a retry, if so check the 145 | // state and send a retry if conditions have changed 146 | if (retryReq && nbrOutstanding() < wrapper.queueSize()) { 147 | retryReq = false; 148 | port.sendRetryReq(); 149 | } 150 | 151 | schedule(tickEvent, curTick() + wrapper.clockPeriod() * SimClock::Int::ns); 152 | } 153 | 154 | Tick 155 | DRAMSim2::recvAtomic(PacketPtr pkt) 156 | { 157 | access(pkt); 158 | 159 | // 50 ns is just an arbitrary value at this point 160 | return pkt->cacheResponding() ? 0 : 50000; 161 | } 162 | 163 | void 164 | DRAMSim2::recvFunctional(PacketPtr pkt) 165 | { 166 | pkt->pushLabel(name()); 167 | 168 | functionalAccess(pkt); 169 | 170 | // potentially update the packets in our response queue as well 171 | for (auto i = responseQueue.begin(); i != responseQueue.end(); ++i) 172 | pkt->checkFunctional(*i); 173 | 174 | pkt->popLabel(); 175 | } 176 | 177 | bool 178 | DRAMSim2::recvTimingReq(PacketPtr pkt) 179 | { 180 | // if a cache is responding, sink the packet without further action 181 | if (pkt->cacheResponding()) { 182 | pendingDelete.reset(pkt); 183 | return true; 184 | } 185 | 186 | // we should not get a new request after committing to retry the 187 | // current one, but unfortunately the CPU violates this rule, so 188 | // simply ignore it for now 189 | if (retryReq) 190 | return false; 191 | 192 | // if we cannot accept we need to send a retry once progress can 193 | // be made 194 | bool can_accept = nbrOutstanding() < wrapper.queueSize(); 195 | 196 | // keep track of the transaction 197 | if (pkt->isRead()) { 198 | if (can_accept) { 199 | outstandingReads[pkt->getAddr()].push(pkt); 200 | 201 | // we count a transaction as outstanding until it has left the 202 | // queue in the controller, and the response has been sent 203 | // back, note that this will differ for reads and writes 204 | ++nbrOutstandingReads; 205 | } 206 | } else if (pkt->isWrite()) { 207 | if (can_accept) { 208 | outstandingWrites[pkt->getAddr()].push(pkt); 209 | 210 | ++nbrOutstandingWrites; 211 | 212 | // perform the access for writes 213 | accessAndRespond(pkt); 214 | } 215 | } else { 216 | // keep it simple and just respond if necessary 217 | accessAndRespond(pkt); 218 | return true; 219 | } 220 | 221 | if (can_accept) { 222 | // we should never have a situation when we think there is space, 223 | // and there isn't 224 | assert(wrapper.canAccept()); 225 | 226 | DPRINTF(DRAMSim2, "Enqueueing address %lld\n", pkt->getAddr()); 227 | 228 | // @todo what about the granularity here, implicit assumption that 229 | // a transaction matches the burst size of the memory (which we 230 | // cannot determine without parsing the ini file ourselves) 231 | wrapper.enqueue(pkt->isWrite(), pkt->getAddr()); 232 | 233 | return true; 234 | } else { 235 | retryReq = true; 236 | return false; 237 | } 238 | } 239 | 240 | void 241 | DRAMSim2::recvRespRetry() 242 | { 243 | DPRINTF(DRAMSim2, "Retrying\n"); 244 | 245 | assert(retryResp); 246 | retryResp = false; 247 | sendResponse(); 248 | } 249 | 250 | void 251 | DRAMSim2::accessAndRespond(PacketPtr pkt) 252 | { 253 | DPRINTF(DRAMSim2, "Access for address %lld\n", pkt->getAddr()); 254 | 255 | bool needsResponse = pkt->needsResponse(); 256 | 257 | // do the actual memory access which also turns the packet into a 258 | // response 259 | access(pkt); 260 | 261 | // turn packet around to go back to requester if response expected 262 | if (needsResponse) { 263 | // access already turned the packet into a response 264 | assert(pkt->isResponse()); 265 | // Here we pay for xbar additional delay and to process the payload 266 | // of the packet. 267 | Tick time = curTick() + pkt->headerDelay + pkt->payloadDelay; 268 | // Reset the timings of the packet 269 | pkt->headerDelay = pkt->payloadDelay = 0; 270 | 271 | DPRINTF(DRAMSim2, "Queuing response for address %lld\n", 272 | pkt->getAddr()); 273 | 274 | // queue it to be sent back 275 | responseQueue.push_back(pkt); 276 | 277 | // if we are not already waiting for a retry, or are scheduled 278 | // to send a response, schedule an event 279 | if (!retryResp && !sendResponseEvent.scheduled()) 280 | schedule(sendResponseEvent, time); 281 | } else { 282 | // queue the packet for deletion 283 | pendingDelete.reset(pkt); 284 | } 285 | } 286 | 287 | void DRAMSim2::readComplete(uint64_t addr, uint64_t cycle) 288 | { 289 | assert(cycle == divCeil(curTick() - startTick, 290 | wrapper.clockPeriod() * SimClock::Int::ns)); 291 | 292 | DPRINTF(DRAMSim2, "Read to address %lld complete\n", addr); 293 | 294 | // get the outstanding reads for the address in question 295 | auto p = outstandingReads.find(addr); 296 | assert(p != outstandingReads.end()); 297 | 298 | // first in first out, which is not necessarily true, but it is 299 | // the best we can do at this point 300 | PacketPtr pkt = p->second.front(); 301 | p->second.pop(); 302 | 303 | if (p->second.empty()) 304 | outstandingReads.erase(p); 305 | 306 | // no need to check for drain here as the next call will add a 307 | // response to the response queue straight away 308 | assert(nbrOutstandingReads != 0); 309 | --nbrOutstandingReads; 310 | 311 | // perform the actual memory access 312 | accessAndRespond(pkt); 313 | } 314 | 315 | void DRAMSim2::writeComplete(uint64_t addr, uint64_t cycle) 316 | { 317 | assert(cycle == divCeil(curTick() - startTick, 318 | wrapper.clockPeriod() * SimClock::Int::ns)); 319 | 320 | DPRINTF(DRAMSim2, "Write to address %lld complete\n", addr); 321 | 322 | // get the outstanding reads for the address in question 323 | auto p = outstandingWrites.find(addr); 324 | assert(p != outstandingWrites.end()); 325 | 326 | // we have already responded, and this is only to keep track of 327 | // what is outstanding 328 | p->second.pop(); 329 | if (p->second.empty()) 330 | outstandingWrites.erase(p); 331 | 332 | assert(nbrOutstandingWrites != 0); 333 | --nbrOutstandingWrites; 334 | 335 | if (nbrOutstanding() == 0) 336 | signalDrainDone(); 337 | } 338 | 339 | BaseSlavePort& 340 | DRAMSim2::getSlavePort(const std::string &if_name, PortID idx) 341 | { 342 | if (if_name != "port") { 343 | return MemObject::getSlavePort(if_name, idx); 344 | } else { 345 | return port; 346 | } 347 | } 348 | 349 | DrainState 350 | DRAMSim2::drain() 351 | { 352 | // check our outstanding reads and writes and if any they need to 353 | // drain 354 | return nbrOutstanding() != 0 ? DrainState::Draining : DrainState::Drained; 355 | } 356 | 357 | DRAMSim2::MemoryPort::MemoryPort(const std::string& _name, 358 | DRAMSim2& _memory) 359 | : SlavePort(_name, &_memory), memory(_memory) 360 | { } 361 | 362 | AddrRangeList 363 | DRAMSim2::MemoryPort::getAddrRanges() const 364 | { 365 | AddrRangeList ranges; 366 | ranges.push_back(memory.getAddrRange()); 367 | return ranges; 368 | } 369 | 370 | Tick 371 | DRAMSim2::MemoryPort::recvAtomic(PacketPtr pkt) 372 | { 373 | return memory.recvAtomic(pkt); 374 | } 375 | 376 | void 377 | DRAMSim2::MemoryPort::recvFunctional(PacketPtr pkt) 378 | { 379 | memory.recvFunctional(pkt); 380 | } 381 | 382 | bool 383 | DRAMSim2::MemoryPort::recvTimingReq(PacketPtr pkt) 384 | { 385 | // pass it to the memory controller 386 | return memory.recvTimingReq(pkt); 387 | } 388 | 389 | void 390 | DRAMSim2::MemoryPort::recvRespRetry() 391 | { 392 | memory.recvRespRetry(); 393 | } 394 | 395 | DRAMSim2* 396 | DRAMSim2Params::create() 397 | { 398 | return new DRAMSim2(this); 399 | } 400 | -------------------------------------------------------------------------------- /integration/gem5/mem/dramsim2.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 ARM Limited 3 | * All rights reserved 4 | * 5 | * The license below extends only to copyright in the software and shall 6 | * not be construed as granting a license to any other intellectual 7 | * property including but not limited to intellectual property relating 8 | * to a hardware implementation of the functionality of the software 9 | * licensed hereunder. You may use the software subject to the license 10 | * terms below provided that you ensure that this notice is replicated 11 | * unmodified and in its entirety in all distributions of the software, 12 | * modified or unmodified, in source code or in binary form. 13 | * 14 | * Redistribution and use in source and binary forms, with or without 15 | * modification, are permitted provided that the following conditions are 16 | * met: redistributions of source code must retain the above copyright 17 | * notice, this list of conditions and the following disclaimer; 18 | * redistributions in binary form must reproduce the above copyright 19 | * notice, this list of conditions and the following disclaimer in the 20 | * documentation and/or other materials provided with the distribution; 21 | * neither the name of the copyright holders nor the names of its 22 | * contributors may be used to endorse or promote products derived from 23 | * this software without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | * 37 | * Authors: Andreas Hansson 38 | */ 39 | 40 | /** 41 | * @file 42 | * DRAMSim2 43 | */ 44 | #ifndef __MEM_DRAMSIM2_HH__ 45 | #define __MEM_DRAMSIM2_HH__ 46 | 47 | #include 48 | #include 49 | 50 | #include "mem/abstract_mem.hh" 51 | #include "mem/dramsim2_wrapper.hh" 52 | #include "mem/qport.hh" 53 | #include "params/DRAMSim2.hh" 54 | 55 | class DRAMSim2 : public AbstractMemory 56 | { 57 | private: 58 | 59 | /** 60 | * The memory port has to deal with its own flow control to avoid 61 | * having unbounded storage that is implicitly created in the port 62 | * itself. 63 | */ 64 | class MemoryPort : public SlavePort 65 | { 66 | 67 | private: 68 | 69 | DRAMSim2& memory; 70 | 71 | public: 72 | 73 | MemoryPort(const std::string& _name, DRAMSim2& _memory); 74 | 75 | protected: 76 | 77 | Tick recvAtomic(PacketPtr pkt); 78 | 79 | void recvFunctional(PacketPtr pkt); 80 | 81 | bool recvTimingReq(PacketPtr pkt); 82 | 83 | void recvRespRetry(); 84 | 85 | AddrRangeList getAddrRanges() const; 86 | 87 | }; 88 | 89 | MemoryPort port; 90 | 91 | /** 92 | * The actual CasHMC wrapper 93 | */ 94 | DRAMSim2Wrapper wrapper; 95 | 96 | /** 97 | * Is the connected port waiting for a retry from us 98 | */ 99 | bool retryReq; 100 | 101 | /** 102 | * Are we waiting for a retry for sending a response. 103 | */ 104 | bool retryResp; 105 | 106 | /** 107 | * Keep track of when the wrapper is started. 108 | */ 109 | Tick startTick; 110 | 111 | /** 112 | * Keep track of what packets are outstanding per 113 | * address, and do so separately for reads and writes. This is 114 | * done so that we can return the right packet on completion from 115 | * DRAMSim. 116 | */ 117 | std::unordered_map > outstandingReads; 118 | std::unordered_map > outstandingWrites; 119 | 120 | /** 121 | * Count the number of outstanding transactions so that we can 122 | * block any further requests until there is space in DRAMSim2 and 123 | * the sending queue we need to buffer the response packets. 124 | */ 125 | unsigned int nbrOutstandingReads; 126 | unsigned int nbrOutstandingWrites; 127 | 128 | /** 129 | * Queue to hold response packets until we can send them 130 | * back. This is needed as DRAMSim2 unconditionally passes 131 | * responses back without any flow control. 132 | */ 133 | std::deque responseQueue; 134 | 135 | unsigned int nbrOutstanding() const; 136 | 137 | /** 138 | * When a packet is ready, use the "access()" method in 139 | * AbstractMemory to actually create the response packet, and send 140 | * it back to the outside world requestor. 141 | * 142 | * @param pkt The packet from the outside world 143 | */ 144 | void accessAndRespond(PacketPtr pkt); 145 | 146 | void sendResponse(); 147 | 148 | /** 149 | * Event to schedule sending of responses 150 | */ 151 | EventFunctionWrapper sendResponseEvent; 152 | 153 | /** 154 | * Progress the controller one clock cycle. 155 | */ 156 | void tick(); 157 | 158 | /** 159 | * Event to schedule clock ticks 160 | */ 161 | EventFunctionWrapper tickEvent; 162 | 163 | /** 164 | * Upstream caches need this packet until true is returned, so 165 | * hold it for deletion until a subsequent call 166 | */ 167 | std::unique_ptr pendingDelete; 168 | 169 | public: 170 | 171 | typedef DRAMSim2Params Params; 172 | DRAMSim2(const Params *p); 173 | 174 | /** 175 | * Read completion callback. 176 | * 177 | * @param addr Address of the request 178 | * @param cycle Internal cycle count of CasHMC 179 | */ 180 | void readComplete(uint64_t addr, uint64_t cycle); 181 | 182 | /** 183 | * Write completion callback. 184 | * 185 | * @param addr Address of the request 186 | * @param cycle Internal cycle count of CasHMC 187 | */ 188 | void writeComplete(uint64_t addr, uint64_t cycle); 189 | 190 | DrainState drain() override; 191 | 192 | virtual BaseSlavePort& getSlavePort(const std::string& if_name, 193 | PortID idx = InvalidPortID) override; 194 | 195 | void init() override; 196 | void startup() override; 197 | 198 | protected: 199 | 200 | Tick recvAtomic(PacketPtr pkt); 201 | void recvFunctional(PacketPtr pkt); 202 | bool recvTimingReq(PacketPtr pkt); 203 | void recvRespRetry(); 204 | 205 | }; 206 | 207 | #endif // __MEM_DRAMSIM2_HH__ -------------------------------------------------------------------------------- /integration/gem5/mem/dramsim2_wrapper.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 ARM Limited 3 | * All rights reserved 4 | * 5 | * The license below extends only to copyright in the software and shall 6 | * not be construed as granting a license to any other intellectual 7 | * property including but not limited to intellectual property relating 8 | * to a hardware implementation of the functionality of the software 9 | * licensed hereunder. You may use the software subject to the license 10 | * terms below provided that you ensure that this notice is replicated 11 | * unmodified and in its entirety in all distributions of the software, 12 | * modified or unmodified, in source code or in binary form. 13 | * 14 | * Redistribution and use in source and binary forms, with or without 15 | * modification, are permitted provided that the following conditions are 16 | * met: redistributions of source code must retain the above copyright 17 | * notice, this list of conditions and the following disclaimer; 18 | * redistributions in binary form must reproduce the above copyright 19 | * notice, this list of conditions and the following disclaimer in the 20 | * documentation and/or other materials provided with the distribution; 21 | * neither the name of the copyright holders nor the names of its 22 | * contributors may be used to endorse or promote products derived from 23 | * this software without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | * 37 | * Authors: Andreas Hansson 38 | */ 39 | 40 | #include 41 | 42 | #include "mem/dramsim2_wrapper.hh" 43 | 44 | #include 45 | 46 | #include "base/compiler.hh" 47 | #include "base/logging.hh" 48 | 49 | DRAMSim2Wrapper::DRAMSim2Wrapper(const std::string& configSim_file, 50 | const std::string& configDRAM_file, 51 | const std::string& working_dir) : 52 | casHMCWrapper(new CasHMC::CasHMCWrapper(working_dir+'/'+configSim_file, working_dir+'/'+configDRAM_file)), 53 | _clockPeriod(0.0), _queueSize(0), _burstSize(0) 54 | { 55 | // there is no way of getting CasHMC to tell us what frequency 56 | // it is assuming, so we have to extract it ourselves 57 | _clockPeriod = extractConfig("tCK =", working_dir + '/' + configDRAM_file); 58 | 59 | if (!_clockPeriod) 60 | fatal("CasHMC wrapper failed to get clock\n"); 61 | 62 | // we also need to know what transaction queue size CasHMC is 63 | // using so we can stall when responses are blocked 64 | _queueSize = extractConfig("MAX_REQ_BUF =", working_dir + '/' + configSim_file); 65 | 66 | if (!_queueSize) 67 | fatal("CasHMC wrapper failed to get queue size\n"); 68 | 69 | 70 | // finally, get the data bus bits and burst length so we can add a 71 | // sanity check for the burst size 72 | unsigned int dataBusBits = 73 | extractConfig("TRANSACTION_SIZE = ", working_dir + '/' + configSim_file); 74 | 75 | unsigned int burstLength = 1; 76 | 77 | if (!dataBusBits || !burstLength) 78 | fatal("CasHMC wrapper failed to get burst size\n"); 79 | 80 | _burstSize = dataBusBits * burstLength; 81 | } 82 | 83 | DRAMSim2Wrapper::~DRAMSim2Wrapper() 84 | { 85 | delete casHMCWrapper; 86 | } 87 | 88 | template 89 | T 90 | DRAMSim2Wrapper::extractConfig(const std::string& field_name, 91 | const std::string& file_name) const 92 | { 93 | std::ifstream file_stream(file_name.c_str(), ios::in); 94 | 95 | if (!file_stream.good()) 96 | fatal("CasHMC wrapper could not open %s for reading\n", file_name); 97 | 98 | bool found = false; 99 | T res; 100 | std::string line; 101 | while (!found && file_stream) { 102 | getline(file_stream, line); 103 | if (line.substr(0, field_name.size()) == field_name) { 104 | found = true; 105 | istringstream iss(line.substr(field_name.size())); 106 | iss >> res; 107 | } 108 | } 109 | 110 | file_stream.close(); 111 | 112 | if (!found) 113 | fatal("CasHMC wrapper could not find %s in %s\n", field_name, 114 | file_name); 115 | 116 | return res; 117 | } 118 | 119 | void 120 | DRAMSim2Wrapper::printStats() 121 | { 122 | casHMCWrapper->PrintEpochStatistic(); 123 | casHMCWrapper->PrintFinalStatistic(); 124 | } 125 | 126 | void 127 | DRAMSim2Wrapper::setCallbacks(CasHMC::TransCompCB* read_callback, 128 | CasHMC::TransCompCB* write_callback) 129 | { 130 | casHMCWrapper->RegisterCallbacks(read_callback, write_callback); 131 | } 132 | 133 | bool 134 | DRAMSim2Wrapper::canAccept() const 135 | { 136 | return casHMCWrapper->CanAcceptTran(); 137 | } 138 | 139 | void 140 | DRAMSim2Wrapper::enqueue(bool is_write, uint64_t addr) 141 | { 142 | bool success M5_VAR_USED = casHMCWrapper->ReceiveTran((is_write ? CasHMC::DATA_WRITE : CasHMC::DATA_READ), addr, _burstSize); 143 | assert(success); 144 | } 145 | 146 | double 147 | DRAMSim2Wrapper::clockPeriod() const 148 | { 149 | return _clockPeriod; 150 | } 151 | 152 | unsigned int 153 | DRAMSim2Wrapper::queueSize() const 154 | { 155 | return _queueSize; 156 | } 157 | 158 | unsigned int 159 | DRAMSim2Wrapper::burstSize() const 160 | { 161 | return _burstSize; 162 | } 163 | 164 | void 165 | DRAMSim2Wrapper::tick() 166 | { 167 | casHMCWrapper->Update(); 168 | } 169 | -------------------------------------------------------------------------------- /integration/gem5/mem/dramsim2_wrapper.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 ARM Limited 3 | * All rights reserved 4 | * 5 | * The license below extends only to copyright in the software and shall 6 | * not be construed as granting a license to any other intellectual 7 | * property including but not limited to intellectual property relating 8 | * to a hardware implementation of the functionality of the software 9 | * licensed hereunder. You may use the software subject to the license 10 | * terms below provided that you ensure that this notice is replicated 11 | * unmodified and in its entirety in all distributions of the software, 12 | * modified or unmodified, in source code or in binary form. 13 | * 14 | * Redistribution and use in source and binary forms, with or without 15 | * modification, are permitted provided that the following conditions are 16 | * met: redistributions of source code must retain the above copyright 17 | * notice, this list of conditions and the following disclaimer; 18 | * redistributions in binary form must reproduce the above copyright 19 | * notice, this list of conditions and the following disclaimer in the 20 | * documentation and/or other materials provided with the distribution; 21 | * neither the name of the copyright holders nor the names of its 22 | * contributors may be used to endorse or promote products derived from 23 | * this software without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 | * 37 | * Authors: Andreas Hansson 38 | */ 39 | 40 | /** 41 | * @file 42 | * DRAMSim2Wrapper declaration for CasHMC wrapper 43 | */ 44 | 45 | #ifndef __MEM_CASHMC_WRAPPER_HH__ 46 | #define __MEM_CASHMC_WRAPPER_HH__ 47 | 48 | #include 49 | 50 | #include "CasHMC/sources/CasHMCWrapper.h" 51 | #include "CasHMC/sources/CallBack.h" 52 | #include "CasHMC/sources/Transaction.h" 53 | 54 | /** 55 | * Wrapper class to avoid having CasHMC names like ClockDomain etc 56 | * clashing with the normal gem5 world. Many of the CasHMC headers 57 | * do not make use of namespaces, and quite a few also open up 58 | * std. The only thing that needs to be exposed externally are the 59 | * callbacks. This wrapper effectively avoids clashes by not including 60 | * any of the conventional gem5 headers (e.g. Packet or SimObject). 61 | */ 62 | class DRAMSim2Wrapper 63 | { 64 | 65 | private: 66 | 67 | CasHMC::CasHMCWrapper *casHMCWrapper; 68 | 69 | double _clockPeriod; 70 | 71 | unsigned int _queueSize; 72 | 73 | unsigned int _burstSize; 74 | 75 | template 76 | T extractConfig(const std::string& field_name, 77 | const std::string& file_name) const; 78 | 79 | public: 80 | 81 | /** 82 | * Create an instance of the CasHMC multi-channel memory 83 | * controller using a specific config and system description. 84 | * 85 | * @param configSim_file simulation config file 86 | * @param configDRAM_file DRAM config file 87 | * @param working_dir Path pre-pended to config files 88 | */ 89 | DRAMSim2Wrapper(const std::string& configSim_file, 90 | const std::string& configDRAM_file, 91 | const std::string& working_dir); 92 | ~DRAMSim2Wrapper(); 93 | 94 | /** 95 | * Print the stats gathered in CasHMC. 96 | */ 97 | void printStats(); 98 | 99 | /** 100 | * Set the callbacks to use for read and write completion. 101 | * 102 | * @param read_callback Callback used for read completions 103 | * @param write_callback Callback used for write completions 104 | */ 105 | void setCallbacks(CasHMC::TransCompCB* read_callback, 106 | CasHMC::TransCompCB* write_callback); 107 | 108 | /** 109 | * Determine if the controller can accept a new packet or not. 110 | * 111 | * @return true if the controller can accept transactions 112 | */ 113 | bool canAccept() const; 114 | 115 | /** 116 | * Enqueue a packet. This assumes that canAccept has returned true. 117 | * 118 | * @param pkt Packet to turn into a CasHMC transaction 119 | */ 120 | void enqueue(bool is_write, uint64_t addr); 121 | 122 | /** 123 | * Get the internal clock period used by CasHMC, specified in 124 | * ns. 125 | * 126 | * @return The clock period of the DRAM interface in ns 127 | */ 128 | double clockPeriod() const; 129 | 130 | /** 131 | * Get the transaction queue size used by CasHMC. 132 | * 133 | * @return The queue size counted in number of transactions 134 | */ 135 | unsigned int queueSize() const; 136 | 137 | /** 138 | * Get the burst size in bytes used by CasHMC. 139 | * 140 | * @return The burst size in bytes (data width * burst length) 141 | */ 142 | unsigned int burstSize() const; 143 | 144 | /** 145 | * Progress the memory controller one cycle 146 | */ 147 | void tick(); 148 | }; 149 | 150 | #endif //__MEM_DRAMSIM2_WRAPPER_HH__ -------------------------------------------------------------------------------- /result/example_CasHMC_no0_result.log: -------------------------------------------------------------------------------- 1 | **************************************************************** 2 | * CasHMC version 1.3 * 3 | * result log file * 4 | * Date : 2017/11/16 Time : 17:31:49 * 5 | **************************************************************** 6 | 7 | - Trace type : file 8 | - Trace file : ./trace/SPEC_CPU2006_example/mase_trace_bzip2_base.alpha.v0.trc 9 | 10 | ============= CasHMC statistic result ============= 11 | 12 | Elapsed epoch : 0 13 | Elapsed clock : 100000 14 | 15 | HMC bandwidth : 2.20239 GB/s (Considered only data size) 16 | Link bandwidth : 6.60494 GB/s (Included flow packet) 17 | Transmitted data : 230.938 KB (236480 B) 18 | 19 | Active link power : 250 mW 20 | Sleep link power : 0 mW 21 | Down link power : 0 mW 22 | Total power on link : 250 mW 23 | 24 | Sleep mode ratio : 0 % 25 | Down mode ratio : 0 % 26 | Total low-power ratio : 0 % 27 | 28 | Tran latency mean : 61.0409 ns 29 | std : 7.50292 ns 30 | max : 86 ns 31 | min : 52 ns 32 | Link latency mean : 54.0398 ns 33 | std : 7.5039 ns 34 | max : 79 ns 35 | min : 45 ns 36 | Vault latency mean : 19.7015 ns 37 | std : 3.96844 ns 38 | max : 23.2 ns 39 | min : 15.2 ns 40 | Retry latency mean : 0 ns 41 | std : 0 ns 42 | max : 0 ns 43 | min : 0 ns 44 | 45 | Read count : 2079 46 | Write count : 1617 47 | Atomic count : 0 48 | Request count : 3696 49 | Response count : 3693 50 | Flow count : 22156 51 | Transaction count : 3693 52 | Error abort count : 0 53 | Error retry count : 0 54 | 55 | ---------------------- [Link 0] 56 | | Read per link : 924 57 | | Write per link : 0 58 | | Atomic per link : 0 59 | | Request per link : 924 60 | | Response per link : 924 61 | | Flow per link : 5544 62 | | Error abort per link : 0 63 | | Sleep mode ratio : 0 % 64 | | Down mode ratio : 0 % 65 | | Total low power mode ratio : 0 % 66 | | Downstream Bandwidth : 0.550747 GB/s 67 | | Upstream Bandwidth : 0.620484 GB/s 68 | | Total Bandwidth : 1.17123 GB/s 69 | | Downstream effec Bandwidth : 0 GB/s 70 | | Upstream effec Bandwidth : 0.0697374 GB/s 71 | | Total effec Bandwidth : 0.0697374 GB/s 72 | | Downstream transmitted data : 0 B (0 B) 73 | | Upstream transmitted data : 7.3125 KB (7488 B) 74 | ----- Total transmitted data : 7.3125 KB (7488 B) 75 | 76 | ---------------------- [Link 1] 77 | | Read per link : 116 78 | | Write per link : 808 79 | | Atomic per link : 0 80 | | Request per link : 924 81 | | Response per link : 923 82 | | Flow per link : 5535 83 | | Error abort per link : 0 84 | | Sleep mode ratio : 0 % 85 | | Down mode ratio : 0 % 86 | | Total low power mode ratio : 0 % 87 | | Downstream Bandwidth : 1.03161 GB/s 88 | | Upstream Bandwidth : 1.10015 GB/s 89 | | Total Bandwidth : 2.13176 GB/s 90 | | Downstream effec Bandwidth : 0.481606 GB/s 91 | | Upstream effec Bandwidth : 0.550151 GB/s 92 | | Total effec Bandwidth : 1.03176 GB/s 93 | | Downstream transmitted data : 50.5 KB (51712 B) 94 | | Upstream transmitted data : 57.6875 KB (59072 B) 95 | ----- Total transmitted data : 108.188 KB (110784 B) 96 | 97 | ---------------------- [Link 2] 98 | | Read per link : 923 99 | | Write per link : 1 100 | | Atomic per link : 0 101 | | Request per link : 924 102 | | Response per link : 923 103 | | Flow per link : 5539 104 | | Error abort per link : 0 105 | | Sleep mode ratio : 0 % 106 | | Down mode ratio : 0 % 107 | | Total low power mode ratio : 0 % 108 | | Downstream Bandwidth : 0.550896 GB/s 109 | | Upstream Bandwidth : 1.10045 GB/s 110 | | Total Bandwidth : 1.65135 GB/s 111 | | Downstream effec Bandwidth : 0.000596046 GB/s 112 | | Upstream effec Bandwidth : 0.550151 GB/s 113 | | Total effec Bandwidth : 0.550747 GB/s 114 | | Downstream transmitted data : 64 B (64 B) 115 | | Upstream transmitted data : 57.6875 KB (59072 B) 116 | ----- Total transmitted data : 57.75 KB (59136 B) 117 | 118 | ---------------------- [Link 3] 119 | | Read per link : 116 120 | | Write per link : 808 121 | | Atomic per link : 0 122 | | Request per link : 924 123 | | Response per link : 923 124 | | Flow per link : 5538 125 | | Error abort per link : 0 126 | | Sleep mode ratio : 0 % 127 | | Down mode ratio : 0 % 128 | | Total low power mode ratio : 0 % 129 | | Downstream Bandwidth : 1.03191 GB/s 130 | | Upstream Bandwidth : 0.618696 GB/s 131 | | Total Bandwidth : 1.6506 GB/s 132 | | Downstream effec Bandwidth : 0.481606 GB/s 133 | | Upstream effec Bandwidth : 0.0685453 GB/s 134 | | Total effec Bandwidth : 0.550151 GB/s 135 | | Downstream transmitted data : 50.5 KB (51712 B) 136 | | Upstream transmitted data : 7.1875 KB (7360 B) 137 | ----- Total transmitted data : 57.6875 KB (59072 B) 138 | 139 | * Effec bandwidth takes data transmission into account regardless of packet header and tail 140 | -------------------------------------------------------------------------------- /result/example_CasHMC_no0_setting.log: -------------------------------------------------------------------------------- 1 | **************************************************************** 2 | * CasHMC version 1.3 * 3 | * setting log file * 4 | * Date : 2017/11/16 Time : 17:31:49 * 5 | **************************************************************** 6 | 7 | ==== Memory transaction setting ==== 8 | CPU cycles to be simulated : 100000 9 | CPU clock period [ns] : 1 10 | Data size of DRAM request [byte] : 64 11 | Request buffer max size : 16 12 | Trace type : file 13 | Trace file name : ./trace/SPEC_CPU2006_example/mase_trace_bzip2_base.alpha.v0.trc 14 | 15 | ==== Link(SerDes) setting ==== 16 | CRC checking : Enable 17 | The number of links : 4 18 | Link width : 4 19 | Link speed [Gb/s] : 12.5 20 | Link master/slave max buffer size: 32 21 | Crossbar switch buffer size : 64 22 | Retry buffer max size : 32 23 | Time to calculate CRC [clk] : 0.01 24 | The number of IRTRY packet : 2 25 | Retry attempt limit : 2 26 | Link BER (the power of 10) : -14 27 | Link priority scheme : ROUND_ROBIN 28 | Link power management : LINK_MONITOR 29 | Rreqeust num to awake : 8 30 | tQUIESCE : 1000 31 | One epoch for link management : 1 32 | Scaling factor of MSHR : 1 33 | Scaling factor of link monitor : 4 34 | 35 | ==== DRAM general setting ==== 36 | Memory density : 4 37 | The number of vaults : 32 38 | The number of banks : 8 39 | The number of rows : 16384 40 | The number of columns : 1024 41 | Address mapping (Max block size) : 32 42 | Vault controller max buffer size : 32 43 | Command queue max size : 16 44 | Command queue structure : Bank-level command queue (Bank-Level parallelism) 45 | Memory scheduling : open page policy 46 | The maximum row buffer accesses : 8 47 | Power-down mode : Enable 48 | 49 | ==== DRAM timing setting ==== 50 | Refresh period : 7800 51 | tCK [ns] : 0.8 52 | CWL [clk] : 4 53 | CL [clk] : 13 54 | AL [clk] : 0 55 | tRAS [clk] : 27 56 | tRCD [clk] : 13 57 | tRRD [clk] : 4 58 | tRC [clk] : 40 59 | tRP [clk] : 10 60 | tCCD [clk] : 4 61 | tRTP [clk] : 7 62 | tWTR [clk] : 7 63 | tWR [clk] : 10 64 | tRTRS [clk] : 1 65 | tRFC [clk] : 74 66 | tFAW [clk] : 24 67 | tCKE [clk] : 5 68 | tXP [clk] : 4 69 | tCMD [clk] : 1 70 | RL [clk] : 13 71 | WL [clk] : 4 72 | BL [clk] : 1 73 | -------------------------------------------------------------------------------- /sources/BankState.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #include "BankState.h" 13 | 14 | namespace CasHMC 15 | { 16 | 17 | BankState::BankState(unsigned id): 18 | bankID(id) 19 | { 20 | currentBankState = IDLE; 21 | openRowAddress = 0; 22 | nextActivate = 0; 23 | nextRead = 0; 24 | nextWrite = 0; 25 | nextPrecharge = 0; 26 | nextPowerUp = 0; 27 | lastCommand = PRECHARGE; 28 | stateChangeCountdown = 0; 29 | } 30 | 31 | void BankState::UpdateStateChange() 32 | { 33 | 34 | } 35 | 36 | // 37 | //Defines "<<" operation for printing 38 | // 39 | ostream &operator<<(ostream &out, const BankState &bs) 40 | { 41 | switch(bs.currentBankState) { 42 | case IDLE: 43 | out<<"Idle"; 44 | break; 45 | case ROW_ACTIVE: 46 | out<<"Actv"; 47 | break; 48 | case PRECHARGING: 49 | out<<"Prch"; 50 | break; 51 | case REFRESHING: 52 | out<<"Refr"; 53 | break; 54 | case POWERDOWN: 55 | out<<"Pwdw"; 56 | break; 57 | case AWAKING: 58 | out<<"Awak"; 59 | break; 60 | default: 61 | ERROR(" (BS) == Error - Trying to print unknown kind of bank state"); 62 | ERROR(" Type : "< //uint64_t 18 | #include //exit(0) 19 | #include //setw() 20 | #include //ostream 21 | 22 | #include "ConfigValue.h" 23 | #include "DRAMCommand.h" 24 | 25 | using namespace std; 26 | 27 | namespace CasHMC 28 | { 29 | enum BankStateType 30 | { 31 | IDLE, 32 | ROW_ACTIVE, 33 | PRECHARGING, 34 | REFRESHING, 35 | POWERDOWN, 36 | AWAKING 37 | }; 38 | 39 | class BankState 40 | { 41 | public: 42 | // 43 | //Functions 44 | // 45 | BankState(unsigned id); 46 | void UpdateStateChange(); 47 | 48 | // 49 | //Fields 50 | // 51 | unsigned bankID; 52 | 53 | BankStateType currentBankState; 54 | unsigned openRowAddress; 55 | uint64_t nextActivate; 56 | uint64_t nextRead; 57 | uint64_t nextWrite; 58 | uint64_t nextPrecharge; 59 | uint64_t nextPowerUp; 60 | 61 | DRAMCommandType lastCommand; 62 | unsigned stateChangeCountdown; 63 | }; 64 | 65 | ostream &operator<<(ostream &out, const BankState &bs); 66 | } 67 | 68 | #endif -------------------------------------------------------------------------------- /sources/CallBack.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef CALLBACK_H 13 | #define CALLBACK_H 14 | 15 | //CallBack.h 16 | 17 | #include //uint64_t 18 | 19 | namespace CasHMC 20 | { 21 | 22 | template 23 | class CallbackBase 24 | { 25 | public: 26 | virtual ~CallbackBase() = 0; 27 | virtual ReturnT operator()(Param1T, Param2T) = 0; 28 | }; 29 | 30 | template 31 | CasHMC::CallbackBase::~CallbackBase() {} 32 | 33 | template 34 | class Callback : public CallbackBase 35 | { 36 | private: 37 | typedef ReturnT (ConsumerT::*PtrMember)(Param1T,Param2T); 38 | ConsumerT* const object; 39 | const PtrMember member; 40 | 41 | public: 42 | Callback(ConsumerT* const object, PtrMember member): 43 | object(object), member(member) 44 | { 45 | } 46 | 47 | Callback(const Callback& e): 48 | object(e.object), member(e.member) 49 | { 50 | } 51 | 52 | ReturnT operator()(Param1T param1, Param2T param2) 53 | { 54 | return (const_cast(object)->*member)(param1,param2); 55 | } 56 | }; 57 | 58 | typedef CallbackBase TransCompCB; 59 | } 60 | 61 | #endif -------------------------------------------------------------------------------- /sources/CasHMCWrapper.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef CASHMCWRAPPER_H 13 | #define CASHMCWRAPPER_H 14 | 15 | //CasHMCWrapper.h 16 | 17 | #include //time 18 | #include //mkdir 19 | #include //EEXIST 20 | #include //access() 21 | #include //stringstream 22 | #include //ofstream 23 | #include //vector 24 | 25 | #include "ConfigReader.h" 26 | #include "ConfigValue.h" 27 | #include "TranStatistic.h" 28 | #include "CallBack.h" 29 | #include "HMCController.h" 30 | #include "Link.h" 31 | #include "HMC.h" 32 | 33 | using namespace std; 34 | 35 | namespace CasHMC 36 | { 37 | 38 | class CasHMCWrapper : public TranStatistic 39 | { 40 | public: 41 | // 42 | //Functions 43 | // 44 | CasHMCWrapper(string simCfg, string dramCfg); 45 | virtual ~CasHMCWrapper(); 46 | void RegisterCallbacks(TransCompCB *readCB, TransCompCB *writeCB); 47 | bool ReceiveTran(TransactionType tranType, uint64_t addr, unsigned size); 48 | bool ReceiveTran(Transaction *tran); 49 | bool CanAcceptTran(); 50 | void UpdateMSHR(unsigned mshr); 51 | void Update(); 52 | void DownLinkUpdate(bool lastUpdate); 53 | void UpLinkUpdate(bool lastUpdate); 54 | void PrintEpochHeader(); 55 | void PrintSetting(struct tm t); 56 | void MakePlotData(); 57 | void PrintEpochStatistic(); 58 | void PrintFinalStatistic(); 59 | string DataScaling(double dataScale); 60 | 61 | // 62 | //Fields 63 | // 64 | HMCController *hmcCont; 65 | vector downstreamLinks; 66 | vector upstreamLinks; 67 | HMC *hmc; 68 | 69 | uint64_t currentClockCycle; 70 | uint64_t dramTuner; 71 | uint64_t downLinkTuner; 72 | uint64_t downLinkClock; 73 | uint64_t upLinkTuner; 74 | uint64_t upLinkClock; 75 | double linkPeriod; 76 | string logName; 77 | int logNum; 78 | 79 | unsigned cpu_link_ratio; 80 | unsigned cpu_link_tune; 81 | unsigned clockTuner_link; 82 | unsigned clockTuner_HMC; 83 | 84 | //Temporary variable for plot data 85 | uint64_t hmcTransmitSizeTemp; 86 | vector downLinkDataSizeTemp; 87 | vector upLinkDataSizeTemp; 88 | 89 | //Output log files 90 | ofstream settingOut; 91 | ofstream debugOut; 92 | ofstream stateOut; 93 | ofstream plotDataOut; 94 | ofstream plotScriptOut; 95 | ofstream resultOut; 96 | }; 97 | 98 | } 99 | 100 | #endif -------------------------------------------------------------------------------- /sources/CommandQueue.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef COMMANDQUEUE_H 13 | #define COMMANDQUEUE_H 14 | 15 | //CommandQueue.h 16 | 17 | #include //vector 18 | 19 | #include "SimulatorObject.h" 20 | #include "ConfigValue.h" 21 | #include "DRAMCommand.h" 22 | 23 | #define ACCESSQUE(b) (QUE_PER_BANK==true ? queue[b] : queue[0]) 24 | #define POPCYCLE(b) (QUE_PER_BANK==true ? bufPopDelayPerBank[b] : bufPopDelayPerBank[0]) 25 | #define BANKSTATE(b) vaultContP->dramP->bankStates[b] 26 | 27 | using namespace std; 28 | 29 | namespace CasHMC 30 | { 31 | //forward declaration 32 | class VaultController; 33 | class CommandQueue : public SimulatorObject 34 | { 35 | public: 36 | // 37 | //Functions 38 | // 39 | CommandQueue(ofstream &debugOut_, ofstream &stateOut_, unsigned id, VaultController *parent); 40 | virtual ~CommandQueue(); 41 | bool AvailableSpace(unsigned bank, unsigned cmdN); 42 | void Enqueue(unsigned bank, DRAMCommand *enqCMD); 43 | bool CmdPop(DRAMCommand **popedCMD); 44 | bool isIssuable(DRAMCommand *issueCMD); 45 | bool isEmpty(); 46 | void Update(); 47 | void PrintState(); 48 | 49 | // 50 | //Fields 51 | // 52 | unsigned cmdQueID; 53 | unsigned issuedBank; 54 | bool refreshWaiting; 55 | VaultController *vaultContP; 56 | 57 | 58 | vector atomicLock; 59 | vector atomicLockTag; 60 | vector bufPopDelayPerBank; 61 | vector< vector > queue; 62 | vector tFAWCountdown; 63 | vector rowAccessCounter; 64 | }; 65 | 66 | } 67 | 68 | #endif -------------------------------------------------------------------------------- /sources/ConfigReader.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #include "ConfigReader.h" 13 | 14 | //Configure values that are extern vaules 15 | 16 | //The unique identifier for transaction and packet 17 | unsigned tranGlobalID = 0; 18 | unsigned packetGlobalTAG = 0; 19 | 20 | // 21 | //SimConfig.ini 22 | // 23 | uint64_t LOG_EPOCH; 24 | bool DEBUG_SIM; 25 | bool ONLY_CR; 26 | bool STATE_SIM; 27 | int PLOT_SAMPLING; 28 | bool BANDWIDTH_PLOT; 29 | 30 | double CPU_CLK_PERIOD; 31 | int TRANSACTION_SIZE; 32 | int MAX_REQ_BUF; 33 | 34 | int NUM_LINKS; 35 | int LINK_WIDTH; 36 | double LINK_SPEED; 37 | int MAX_LINK_BUF; 38 | int MAX_RETRY_BUF; 39 | int MAX_VLT_BUF; 40 | int MAX_CROSS_BUF; 41 | int MAX_CMD_QUE; 42 | bool CRC_CHECK; 43 | double CRC_CAL_CYCLE; 44 | int NUM_OF_IRTRY; 45 | int RETRY_ATTEMPT_LIMIT; 46 | int LINK_BER; 47 | LINK_PRIORITY_SCHEME LINK_PRIORITY; 48 | LINK_POWER_MANAGEMENT LINK_POWER; 49 | int AWAKE_REQ; 50 | double LINK_EPOCH; 51 | double MSHR_SCALING; 52 | double LINK_SCALING; 53 | 54 | double PowPerLane; 55 | double SleepPow; 56 | double DownPow; 57 | 58 | double tPST; 59 | double tSME; 60 | double tSS; 61 | double tSD; 62 | double tSREF; 63 | double tOP; 64 | double tQUIESCE; 65 | 66 | double tTXD; 67 | double tRESP1; 68 | double tRESP2; 69 | double tPSC; 70 | 71 | // 72 | //DRAMConfig.ini 73 | // 74 | int MEMORY_DENSITY; 75 | int NUM_VAULTS; 76 | int NUM_BANKS; 77 | int NUM_ROWS; 78 | int NUM_COLS; 79 | MAPPING_SCHEME ADDRESS_MAPPING; 80 | bool QUE_PER_BANK; 81 | bool OPEN_PAGE; 82 | int MAX_ROW_ACCESSES; 83 | bool USE_LOW_POWER; 84 | 85 | int REFRESH_PERIOD; 86 | 87 | double tCK; 88 | unsigned CWL; 89 | unsigned CL; 90 | unsigned AL; 91 | unsigned tRAS; 92 | unsigned tRCD; 93 | unsigned tRRD; 94 | unsigned tRC; 95 | unsigned tRP; 96 | unsigned tCCD; 97 | unsigned tRTP; 98 | unsigned tWTR; 99 | unsigned tWR; 100 | unsigned tRTRS; 101 | unsigned tRFC; 102 | unsigned tFAW; 103 | unsigned tCKE; 104 | unsigned tXP; 105 | unsigned tCMD; 106 | 107 | #define DEFINE_PARAM(type, name) {#name, &name, type, false} 108 | 109 | namespace CasHMC 110 | { 111 | 112 | static ConfigMap configMap[] = 113 | { 114 | //SimConfig.ini 115 | DEFINE_PARAM(UINT64, LOG_EPOCH), DEFINE_PARAM(BOOL, DEBUG_SIM), 116 | DEFINE_PARAM(BOOL, ONLY_CR), DEFINE_PARAM(BOOL, STATE_SIM), 117 | DEFINE_PARAM(INT, PLOT_SAMPLING), DEFINE_PARAM(BOOL, BANDWIDTH_PLOT), 118 | DEFINE_PARAM(DOUBLE, CPU_CLK_PERIOD), DEFINE_PARAM(INT, TRANSACTION_SIZE), 119 | DEFINE_PARAM(INT, MAX_REQ_BUF), DEFINE_PARAM(INT, NUM_LINKS), 120 | DEFINE_PARAM(INT, LINK_WIDTH), DEFINE_PARAM(DOUBLE, LINK_SPEED), 121 | DEFINE_PARAM(INT, MAX_LINK_BUF), DEFINE_PARAM(INT, MAX_RETRY_BUF), 122 | DEFINE_PARAM(INT, MAX_VLT_BUF), DEFINE_PARAM(INT, MAX_CROSS_BUF), 123 | DEFINE_PARAM(INT, MAX_CMD_QUE), DEFINE_PARAM(BOOL, CRC_CHECK), 124 | DEFINE_PARAM(DOUBLE, CRC_CAL_CYCLE), DEFINE_PARAM(INT, NUM_OF_IRTRY), 125 | DEFINE_PARAM(INT, RETRY_ATTEMPT_LIMIT), DEFINE_PARAM(INT, LINK_BER), 126 | DEFINE_PARAM(STRING, LINK_PRIORITY), DEFINE_PARAM(STRING, LINK_POWER), 127 | DEFINE_PARAM(INT, AWAKE_REQ), DEFINE_PARAM(DOUBLE, LINK_EPOCH), 128 | DEFINE_PARAM(DOUBLE, MSHR_SCALING), DEFINE_PARAM(DOUBLE, LINK_SCALING), 129 | DEFINE_PARAM(DOUBLE, PowPerLane), DEFINE_PARAM(DOUBLE, SleepPow), 130 | DEFINE_PARAM(DOUBLE, DownPow), DEFINE_PARAM(DOUBLE, tPST), 131 | DEFINE_PARAM(DOUBLE, tSME), DEFINE_PARAM(DOUBLE, tSS), 132 | DEFINE_PARAM(DOUBLE, tSD), DEFINE_PARAM(DOUBLE, tSREF), 133 | DEFINE_PARAM(DOUBLE, tOP), DEFINE_PARAM(DOUBLE, tQUIESCE), 134 | DEFINE_PARAM(DOUBLE, tTXD), DEFINE_PARAM(DOUBLE, tRESP1), 135 | DEFINE_PARAM(DOUBLE, tRESP2), DEFINE_PARAM(DOUBLE, tPSC), 136 | 137 | //DRAMConfig.ini 138 | DEFINE_PARAM(INT, MEMORY_DENSITY), DEFINE_PARAM(INT, NUM_VAULTS), 139 | DEFINE_PARAM(INT, NUM_BANKS), DEFINE_PARAM(INT, NUM_ROWS), 140 | DEFINE_PARAM(INT, NUM_COLS), DEFINE_PARAM(STRING, ADDRESS_MAPPING), 141 | DEFINE_PARAM(BOOL, QUE_PER_BANK), DEFINE_PARAM(BOOL, OPEN_PAGE), 142 | DEFINE_PARAM(INT, MAX_ROW_ACCESSES), DEFINE_PARAM(BOOL, USE_LOW_POWER), 143 | DEFINE_PARAM(INT, REFRESH_PERIOD), DEFINE_PARAM(DOUBLE, tCK), 144 | DEFINE_PARAM(UNSIGNED_CLK, CWL), DEFINE_PARAM(UNSIGNED_CLK, CL), 145 | DEFINE_PARAM(UNSIGNED_CLK, AL), DEFINE_PARAM(UNSIGNED_CLK, tRAS), 146 | DEFINE_PARAM(UNSIGNED_CLK, tRCD), DEFINE_PARAM(UNSIGNED_CLK, tRRD), 147 | DEFINE_PARAM(UNSIGNED_CLK, tRC), DEFINE_PARAM(UNSIGNED_CLK, tRP), 148 | DEFINE_PARAM(UNSIGNED_CLK, tCCD), DEFINE_PARAM(UNSIGNED_CLK, tRTP), 149 | DEFINE_PARAM(UNSIGNED_CLK, tWTR), DEFINE_PARAM(UNSIGNED_CLK, tWR), 150 | DEFINE_PARAM(UNSIGNED_CLK, tRTRS), DEFINE_PARAM(UNSIGNED_CLK, tRFC), 151 | DEFINE_PARAM(UNSIGNED_CLK, tFAW), DEFINE_PARAM(UNSIGNED_CLK, tCKE), 152 | DEFINE_PARAM(UNSIGNED_CLK, tXP), DEFINE_PARAM(UNSIGNED_CLK, tCMD), 153 | //end of list 154 | {"", NULL, BOOL, false} 155 | }; 156 | 157 | // 158 | //Read configure field values 159 | // 160 | void ReadIniFile(string file_name) 161 | { 162 | fstream file_stream(file_name.c_str(), ios::in); 163 | if(!file_stream.good()) { 164 | ERROR("CasHMC could not open "<> val; 300 | *((int *)configMap[i].fieldPtr) = val; 301 | break; 302 | } 303 | case UNSIGNED_CLK: { 304 | double val; 305 | val_st >> val; 306 | unsigned val_by_clk = ceil(val/tCK); 307 | *((unsigned *)configMap[i].fieldPtr) = val_by_clk; 308 | break; 309 | } 310 | case UINT64: { 311 | uint64_t val; 312 | val_st >> val; 313 | *((uint64_t *)configMap[i].fieldPtr) = val; 314 | break; 315 | } 316 | case DOUBLE: { 317 | double val; 318 | val_st >> val; 319 | *((double *)configMap[i].fieldPtr) = val; 320 | break; 321 | } 322 | } 323 | configMap[i].wasSet = true; 324 | break; 325 | } 326 | } 327 | 328 | if(configMap[i].fieldPtr == NULL) { 329 | ERROR(" == Error - Unknown field ["< 18 | #include 19 | #include 20 | #include //ceil() 21 | #include //exit() 22 | 23 | #include "ConfigValue.h" 24 | 25 | using namespace std; 26 | 27 | namespace CasHMC 28 | { 29 | 30 | typedef enum _variableType {STRING, BOOL, INT, UNSIGNED_CLK, UINT64, DOUBLE} varType; 31 | typedef struct _configMap 32 | { 33 | string fieldName; 34 | void *fieldPtr; 35 | varType fieldType; 36 | bool wasSet; 37 | } ConfigMap; 38 | 39 | void ReadIniFile(string file_name); 40 | void SetField(string field_name, string field_value); 41 | 42 | } 43 | 44 | #endif -------------------------------------------------------------------------------- /sources/ConfigValue.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef CONFIGVALUE_H 13 | #define CONFIGVALUE_H 14 | 15 | //ConfigValue.h 16 | 17 | #include //uint64_t 18 | #include //cerr 19 | 20 | // 21 | //Debug setting 22 | // 23 | #ifdef DEBUG_LOG 24 | #define DEBUG(str) if(DEBUG_SIM && !ONLY_CR) {debugOut<>= 1; 179 | while(value > 0) 180 | { 181 | value >>= 1; 182 | logbase2++; 183 | } 184 | if(1<(debugOut_, stateOut_, MAX_CROSS_BUF, MAX_CROSS_BUF) 19 | { 20 | header = " (CS)"; 21 | 22 | inServiceLink = -1; 23 | 24 | downBufferDest = vector *>(NUM_VAULTS, NULL); 25 | upBufferDest = vector(NUM_LINKS, NULL); 26 | } 27 | 28 | CrossbarSwitch::~CrossbarSwitch() 29 | { 30 | downBufferDest.clear(); 31 | upBufferDest.clear(); 32 | pendingSegTag.clear(); 33 | pendingSegPacket.clear(); 34 | } 35 | 36 | // 37 | //Callback Adding packet 38 | // 39 | void CrossbarSwitch::CallbackReceiveDown(Packet *downEle, bool chkReceive) 40 | { 41 | /* if(chkReceive) { 42 | DEBUG(ALI(18)<reqDataSize > ADDRESS_MAPPING) { 69 | int segPacket = ceil((double)downBuffers[i]->reqDataSize/ADDRESS_MAPPING); 70 | downBuffers[i]->reqDataSize = ADDRESS_MAPPING; 71 | DEBUG(ALI(18)<LNG); 76 | if(tempPacket->LNG > 1) tempPacket->LNG = 1 + ADDRESS_MAPPING/16; //one flit is 16 bytes 77 | for(int j=0; jADRS += j*ADDRESS_MAPPING; 80 | if(j>0) vaultPacket->trace = NULL; 81 | downBuffers.insert(downBuffers.begin()+i, vaultPacket); 82 | for(int k=1; kLNG; k++) { //Virtual tail packet 83 | downBuffers.insert(downBuffers.begin()+i+1, NULL); 84 | } 85 | i += vaultPacket->LNG; 86 | vaultPacket->segment = true; 87 | pendingSegTag.push_back(vaultPacket->TAG); 88 | } 89 | delete tempPacket; 90 | } 91 | else { 92 | unsigned vaultMap = (downBuffers[i]->ADRS >> _log2(ADDRESS_MAPPING)) & (NUM_VAULTS-1); 93 | if(downBufferDest[vaultMap]->ReceiveDown(downBuffers[i])) { 94 | DEBUG(ALI(18)<LNG); 96 | i--; 97 | } 98 | else { 99 | //DEBUG(ALI(18)<segment) { 111 | //Check a stored segment packet tag 112 | bool foundSeg = false; 113 | bool foundLastSeg = true; 114 | for(int j=0; jTAG == pendingSegTag[j]) { 116 | pendingSegTag.erase(pendingSegTag.begin()+j); 117 | foundSeg = true; 118 | //Check whether upBuffers[i] packet is the last segment packet or not 119 | for(int k=j; kTAG == pendingSegTag[k]) { 121 | DEBUG(ALI(18)<TAG == pendingSegPacket[j]->TAG) { 141 | if(upBuffers[i]->LNG > 1) pendingSegPacket[j]->LNG += ADDRESS_MAPPING/16; 142 | if(upBuffers[i]->trace != NULL) { //It is the first segment packet 143 | pendingSegPacket[j]->trace = upBuffers[i]->trace; 144 | pendingSegPacket[j]->ADRS = upBuffers[i]->ADRS; 145 | } 146 | //Delete a segment packet 147 | int packetLNG = upBuffers[i]->LNG; 148 | delete upBuffers[i]; 149 | upBuffers.erase(upBuffers.begin()+i, upBuffers.begin()+i+packetLNG); 150 | foundSeg = true; 151 | //All segment packets are combined 152 | if(foundLastSeg) { 153 | Packet *combPacket = new Packet(*pendingSegPacket[j]); 154 | delete pendingSegPacket[j]; 155 | pendingSegPacket.erase(pendingSegPacket.begin()+j); 156 | combPacket->segment = false; 157 | upBuffers.insert(upBuffers.begin(), combPacket); 158 | for(int k=1; kLNG; k++) { //Virtual tail packet 159 | upBuffers.insert(upBuffers.begin()+1, NULL); 160 | } 161 | } 162 | else { 163 | i--; 164 | } 165 | break; 166 | } 167 | } 168 | //Thr first arrived segment packet 169 | if(!foundSeg) { 170 | pendingSegPacket.push_back(upBuffers[i]); 171 | upBuffers.erase(upBuffers.begin()+i, upBuffers.begin()+i+upBuffers[i]->LNG); 172 | i--; 173 | } 174 | } 175 | else { 176 | for(int l=0; lcurrentState != ACTIVE 182 | && upBufferDest[link]->currentState != LINK_RETRY) { 183 | continue; 184 | //DEBUG(ALI(18)<powerMode<<"]"); 185 | } 186 | else { 187 | if(upBufferDest[link]->Receive(upBuffers[i])) { 188 | DEBUG(ALI(18)<LNG); 190 | i--; 191 | break; 192 | } 193 | else { 194 | //DEBUG(ALI(18)<0) { 212 | STATEN(ALI(17)<0 && i%8==0) { 216 | STATEN(endl<<" "); 217 | } 218 | if(i < downBuffers.size()) { 219 | if(downBuffers[i] != NULL) realInd = i; 220 | STATEN(*downBuffers[realInd]); 221 | } 222 | else if(i == downBufferMax-1) { 223 | STATEN("[ - ]"); 224 | } 225 | else { 226 | STATEN("[ - ]..."); 227 | break; 228 | } 229 | } 230 | STATEN(endl); 231 | } 232 | 233 | if(upBuffers.size()>0) { 234 | STATEN(ALI(17)<0 && i%8==0) { 239 | STATEN(endl<<" "); 240 | } 241 | if(i < upBuffers.size()) { 242 | if(upBuffers[i] != NULL) realInd = i; 243 | STATEN(*upBuffers[realInd]); 244 | } 245 | else if(i == upBufferMax-1) { 246 | STATEN("[ - ]"); 247 | } 248 | else { 249 | STATEN("[ - ]..."); 250 | break; 251 | } 252 | } 253 | } 254 | else { 255 | for(int i=0; i0 && i%8==0) { 257 | STATEN(endl<<" "); 258 | } 259 | if(upBuffers[i] != NULL) realInd = i; 260 | STATEN(*upBuffers[realInd]); 261 | } 262 | } 263 | STATEN(endl); 264 | } 265 | } 266 | 267 | } //namespace CasHMC -------------------------------------------------------------------------------- /sources/CrossbarSwitch.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef CROSSBARSWITCH_H 13 | #define CROSSBARSWITCH_H 14 | 15 | //CrossbarSwitch.h 16 | 17 | #include //vector 18 | 19 | #include "DualVectorObject.h" 20 | #include "ConfigValue.h" 21 | #include "LinkMaster.h" 22 | 23 | using namespace std; 24 | 25 | namespace CasHMC 26 | { 27 | 28 | class CrossbarSwitch : public DualVectorObject 29 | { 30 | public: 31 | // 32 | //Functions 33 | // 34 | CrossbarSwitch(ofstream &debugOut_, ofstream &stateOut_); 35 | virtual ~CrossbarSwitch(); 36 | void CallbackReceiveDown(Packet *downEle, bool chkReceive); 37 | void CallbackReceiveUp(Packet *upEle, bool chkReceive); 38 | void Update(); 39 | void PrintState(); 40 | 41 | // 42 | //Fields 43 | // 44 | vector *> downBufferDest; 45 | vector upBufferDest; 46 | int inServiceLink; 47 | vector pendingSegTag; //Store segment packet tag for returning 48 | vector pendingSegPacket; //Store segment packets 49 | }; 50 | 51 | } 52 | 53 | #endif -------------------------------------------------------------------------------- /sources/DRAM.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #include "DRAM.h" 13 | #include "VaultController.h" 14 | 15 | namespace CasHMC 16 | { 17 | 18 | DRAM::DRAM(ofstream &debugOut_, ofstream &stateOut_, unsigned id, VaultController *contP): 19 | SimulatorObject(debugOut_, stateOut_), 20 | DRAMID(id), 21 | vaultContP(contP) 22 | { 23 | classID << DRAMID; 24 | header = " (DR_" + classID.str() + ")"; 25 | 26 | readData = NULL; 27 | dataCyclesLeft = 0; 28 | 29 | bankStates.reserve(NUM_BANKS); 30 | for(int b=0; b(NUM_BANKS, IDLE); 34 | } 35 | 36 | DRAM::~DRAM() 37 | { 38 | for(int i=0; icommandType) { 56 | case ACTIVATE: 57 | bankStates[recvCMD->bank]->currentBankState = ROW_ACTIVE; 58 | bankStates[recvCMD->bank]->lastCommand = ACTIVATE; 59 | bankStates[recvCMD->bank]->openRowAddress = recvCMD->row; 60 | bankStates[recvCMD->bank]->nextActivate = max(currentClockCycle + tRC, bankStates[recvCMD->bank]->nextActivate); 61 | bankStates[recvCMD->bank]->nextPrecharge = max(currentClockCycle + tRAS, bankStates[recvCMD->bank]->nextPrecharge); 62 | bankStates[recvCMD->bank]->nextRead = max(currentClockCycle + (tRCD-AL), bankStates[recvCMD->bank]->nextRead); 63 | bankStates[recvCMD->bank]->nextWrite = max(currentClockCycle + (tRCD-AL), bankStates[recvCMD->bank]->nextWrite); 64 | for(int b=0; bbank != b) { 66 | bankStates[b]->nextActivate = max(currentClockCycle + tRRD, bankStates[b]->nextActivate); 67 | } 68 | } 69 | DEBUG(ALI(18)<bank]->nextRead<<" [HMC clk]"); 70 | delete recvCMD; 71 | break; 72 | case READ: 73 | bankStates[recvCMD->bank]->nextPrecharge = max(currentClockCycle + READ_TO_PRE_DELAY, bankStates[recvCMD->bank]->nextPrecharge); 74 | bankStates[recvCMD->bank]->lastCommand = READ; 75 | for(int b=0; bnextRead = max(currentClockCycle + max(tCCD, BL), bankStates[b]->nextRead); 77 | bankStates[b]->nextWrite = max(currentClockCycle + READ_TO_WRITE_DELAY, bankStates[b]->nextWrite); 78 | } 79 | DEBUG(ALI(18)<bank]->nextPrecharge<<" [HMC clk]"); 81 | recvCMD->commandType = READ_DATA; 82 | readReturnDATA.push_back(recvCMD); 83 | readReturnCountdown.push_back(RL); 84 | break; 85 | case READ_P: 86 | bankStates[recvCMD->bank]->nextActivate = max(currentClockCycle + READ_AUTOPRE_DELAY, bankStates[recvCMD->bank]->nextActivate); 87 | bankStates[recvCMD->bank]->lastCommand = READ_P; 88 | bankStates[recvCMD->bank]->stateChangeCountdown = READ_TO_PRE_DELAY; 89 | for(int b=0; bnextRead = max(currentClockCycle + max(tCCD, BL), bankStates[b]->nextRead); 91 | bankStates[b]->nextWrite = max(currentClockCycle + READ_TO_WRITE_DELAY, bankStates[b]->nextWrite); 92 | } 93 | if(recvCMD->commandType == READ_P) { 94 | bankStates[recvCMD->bank]->nextRead = bankStates[recvCMD->bank]->nextActivate; 95 | bankStates[recvCMD->bank]->nextWrite = bankStates[recvCMD->bank]->nextActivate; 96 | } 97 | DEBUG(ALI(18)<bank]->nextActivate<<" [HMC clk]"); 99 | recvCMD->commandType = READ_DATA; 100 | readReturnDATA.push_back(recvCMD); 101 | readReturnCountdown.push_back(RL); 102 | break; 103 | case WRITE: 104 | bankStates[recvCMD->bank]->nextPrecharge = max(currentClockCycle + WRITE_TO_PRE_DELAY, bankStates[recvCMD->bank]->nextPrecharge); 105 | bankStates[recvCMD->bank]->lastCommand = WRITE; 106 | for(int b=0; bnextWrite = max(currentClockCycle + max(BL, tCCD), bankStates[b]->nextWrite); 108 | bankStates[b]->nextRead = max(currentClockCycle + WRITE_TO_READ_DELAY_B, bankStates[b]->nextRead); 109 | } 110 | DEBUG(ALI(18)<bank]->nextPrecharge<<" [HMC clk]"); 112 | delete recvCMD; 113 | break; 114 | case WRITE_P: 115 | bankStates[recvCMD->bank]->nextActivate = max(currentClockCycle + WRITE_AUTOPRE_DELAY, bankStates[recvCMD->bank]->nextActivate); 116 | bankStates[recvCMD->bank]->lastCommand = WRITE_P; 117 | bankStates[recvCMD->bank]->stateChangeCountdown = WRITE_TO_PRE_DELAY; 118 | for(int b=0; bnextWrite = max(currentClockCycle + max(BL, tCCD), bankStates[b]->nextWrite); 120 | bankStates[b]->nextRead = max(currentClockCycle + WRITE_TO_READ_DELAY_B, bankStates[b]->nextRead); 121 | } 122 | bankStates[recvCMD->bank]->nextRead = bankStates[recvCMD->bank]->nextActivate; 123 | bankStates[recvCMD->bank]->nextWrite = bankStates[recvCMD->bank]->nextActivate; 124 | DEBUG(ALI(18)<bank]->nextActivate<<" [HMC clk]"); 126 | delete recvCMD; 127 | break; 128 | case WRITE_DATA: 129 | delete recvCMD; 130 | break; 131 | case PRECHARGE: 132 | bankStates[recvCMD->bank]->currentBankState = PRECHARGING; 133 | bankStates[recvCMD->bank]->lastCommand = PRECHARGE; 134 | bankStates[recvCMD->bank]->openRowAddress = 0; 135 | bankStates[recvCMD->bank]->stateChangeCountdown = tRP; 136 | bankStates[recvCMD->bank]->nextActivate = max(currentClockCycle + tRP, bankStates[recvCMD->bank]->nextActivate); 137 | DEBUG(ALI(18)<bank]->nextActivate<<" [HMC clk]"); 138 | delete recvCMD; 139 | break; 140 | case REFRESH: 141 | for(int b=0; bnextActivate = currentClockCycle + tRFC; 143 | bankStates[b]->currentBankState = REFRESHING; 144 | bankStates[b]->lastCommand = REFRESH; 145 | bankStates[b]->stateChangeCountdown = tRFC; 146 | } 147 | DEBUG(ALI(18)<bank]->nextActivate<<" [HMC clk]"); 148 | delete recvCMD; 149 | break; 150 | default: 151 | ERROR(header<<" (DR) == Error - Wrong command type popped command : "<<*recvCMD<<" (CurrentClock : "<currentBankState != IDLE) { 166 | allIdle = false; 167 | break; 168 | } 169 | } 170 | if(allIdle) { 171 | for(int b=0; bcurrentBankState = POWERDOWN; 173 | bankStates[b]->nextPowerUp = currentClockCycle + tCKE; 174 | } 175 | return true; 176 | } 177 | else { 178 | return false; 179 | } 180 | } 181 | 182 | // 183 | //Awake DRAM in power down mode 184 | // 185 | void DRAM::powerUp() 186 | { 187 | for(int b=0; blastCommand = POWERDOWN_EXIT; 189 | bankStates[b]->currentBankState = AWAKING; 190 | bankStates[b]->stateChangeCountdown = tXP; 191 | bankStates[b]->nextActivate = currentClockCycle + tXP; 192 | } 193 | DEBUG(ALI(39)<nextActivate); 194 | } 195 | 196 | // 197 | //Updates the state of DRAM 198 | // 199 | void DRAM::Update() 200 | { 201 | //update bank states 202 | for(int b=0; bstateChangeCountdown>0) { 204 | //decrement counters 205 | bankStates[b]->stateChangeCountdown--; 206 | 207 | //if counter has reached 0, change state 208 | if(bankStates[b]->stateChangeCountdown == 0) { 209 | switch(bankStates[b]->lastCommand) { 210 | //only these commands have an implicit state change 211 | case WRITE_P: 212 | case READ_P: 213 | bankStates[b]->currentBankState = PRECHARGING; 214 | bankStates[b]->lastCommand = PRECHARGE; 215 | bankStates[b]->stateChangeCountdown = tRP; 216 | break; 217 | case REFRESH: 218 | case PRECHARGE: 219 | case POWERDOWN_EXIT: 220 | bankStates[b]->currentBankState = IDLE; 221 | break; 222 | default: 223 | break; 224 | } 225 | } 226 | } 227 | } 228 | 229 | UpdateState(); 230 | Step(); 231 | } 232 | 233 | // 234 | //Decrease countdown and send back return command to vault controller 235 | // 236 | void DRAM::UpdateState() 237 | { 238 | if(readData != NULL) { 239 | dataCyclesLeft--; 240 | if(dataCyclesLeft == 0) { 241 | vaultContP->ReturnCommand(readData); 242 | readData = NULL; 243 | } 244 | } 245 | 246 | //Send back return command to vault controller 247 | if(readReturnCountdown.size() > 0 && readReturnCountdown[0] == 0) { 248 | readData = readReturnDATA[0]; 249 | dataCyclesLeft = BL; 250 | readReturnDATA.erase(readReturnDATA.begin()); 251 | readReturnCountdown.erase(readReturnCountdown.begin()); 252 | } 253 | 254 | for(int i=0; icurrentBankState) { 267 | printDR = true; 268 | break; 269 | } 270 | } 271 | 272 | if(printDR) { 273 | STATEN(ALI(17)<currentBankState; 277 | STATEN("["); 278 | STATEN(*bankStates[b]); 279 | if(bankStates[b]->currentBankState == ROW_ACTIVE) { 280 | STATEN("-"<openRowAddress); 281 | } 282 | STATEN("]"); 283 | } 284 | STATEN(endl); 285 | } 286 | } 287 | 288 | } //namespace CasHMC -------------------------------------------------------------------------------- /sources/DRAM.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef DRAM_H 13 | #define DRAM_H 14 | 15 | //DRAM.h 16 | 17 | #include //vector 18 | #include //uint64_t 19 | 20 | #include "SimulatorObject.h" 21 | #include "ConfigValue.h" 22 | #include "DRAMCommand.h" 23 | #include "BankState.h" 24 | 25 | using namespace std; 26 | 27 | namespace CasHMC 28 | { 29 | //forward declaration 30 | class VaultController; 31 | class DRAM : public SimulatorObject 32 | { 33 | public: 34 | // 35 | //Functions 36 | // 37 | DRAM(ofstream &debugOut_, ofstream &stateOut_, unsigned id, VaultController *contP); 38 | ~DRAM(); 39 | void receiveCMD(DRAMCommand *recvCMD); 40 | bool powerDown(); 41 | void powerUp(); 42 | void Update(); 43 | void UpdateState(); 44 | void PrintState(); 45 | 46 | // 47 | //Fields 48 | // 49 | unsigned DRAMID; 50 | VaultController *vaultContP; 51 | vector bankStates; 52 | vector previousBankState; 53 | 54 | //To be returned command 55 | DRAMCommand *readData; 56 | unsigned dataCyclesLeft; 57 | vector readReturnDATA; 58 | vector readReturnCountdown; 59 | }; 60 | 61 | } 62 | 63 | #endif -------------------------------------------------------------------------------- /sources/DRAMCommand.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #include "DRAMCommand.h" 13 | 14 | namespace CasHMC 15 | { 16 | 17 | DRAMCommand::DRAMCommand(DRAMCommandType cmdtype, unsigned tag, unsigned bnk, unsigned col, unsigned rw, unsigned dSize, 18 | bool pst, TranTrace *lat, bool last, PacketCommandType pktCMD, bool atm, bool seg): 19 | trace(lat), 20 | commandType(cmdtype), 21 | packetTAG(tag), 22 | bank(bnk), 23 | column(col), 24 | row(rw), 25 | dataSize(dSize), 26 | posted(pst), 27 | lastCMD(last), 28 | packetCMD(pktCMD), 29 | atomic(atm), 30 | segment(seg) 31 | { 32 | } 33 | 34 | DRAMCommand::DRAMCommand(const DRAMCommand &dc) 35 | { 36 | trace = dc.trace; 37 | commandType = dc.commandType; 38 | packetTAG = dc.packetTAG; 39 | bank = dc.bank; 40 | column = dc.column; 41 | row = dc.row; 42 | dataSize = dc.dataSize; 43 | posted = dc.posted; 44 | lastCMD = dc.lastCMD; 45 | packetCMD = dc.packetCMD; 46 | atomic = dc.atomic; 47 | segment = dc.segment; 48 | } 49 | 50 | DRAMCommand::~DRAMCommand() 51 | { 52 | } 53 | 54 | // 55 | //Defines "<<" operation for printing 56 | // 57 | ostream& operator<<(ostream &out, const DRAMCommand &dc) 58 | { 59 | string header; 60 | stringstream id; 61 | id << dc.packetTAG; 62 | 63 | switch(dc.commandType) { 64 | case ACTIVATE: 65 | header = "[C" + id.str() + "-ACT]"; 66 | break; 67 | case READ: 68 | header = "[C" + id.str() + "-READ]"; 69 | break; 70 | case READ_P: 71 | header = "[C" + id.str() + "-READ_P]"; 72 | break; 73 | case WRITE: 74 | header = "[C" + id.str() + "-WRITE]"; 75 | break; 76 | case WRITE_P: 77 | header = "[C" + id.str() + "-WRITE_P]"; 78 | break; 79 | case PRECHARGE: 80 | header = "[C" + id.str() + "-PRE]"; 81 | break; 82 | case REFRESH: 83 | header = "[C" + id.str() + "-REF]"; 84 | break; 85 | case READ_DATA: 86 | header = "[C" + id.str() + "-R_DATA]"; 87 | break; 88 | case WRITE_DATA: 89 | header = "[C" + id.str() + "-W_DATA]"; 90 | break; 91 | case POWERDOWN_ENTRY: 92 | header = "[C" + id.str() + "-PD_ENT]"; 93 | break; 94 | case POWERDOWN_EXIT: 95 | header = "[C" + id.str() + "-PD_EXT]"; 96 | break; 97 | default: 98 | ERROR(" (DC) == Error - Trying to print unknown kind of bus packet"); 99 | ERROR(" Type : "< //uint64_t 18 | #include //exit(0) 19 | #include //setw() 20 | #include //ostream 21 | #include //stringstream 22 | 23 | #include "ConfigValue.h" 24 | #include "TranTrace.h" 25 | #include "Packet.h" 26 | 27 | using namespace std; 28 | 29 | namespace CasHMC 30 | { 31 | 32 | enum DRAMCommandType 33 | { 34 | ACTIVATE, 35 | READ, 36 | READ_P, 37 | WRITE, 38 | WRITE_P, 39 | READ_DATA, 40 | WRITE_DATA, 41 | PRECHARGE, 42 | REFRESH, 43 | POWERDOWN_ENTRY, 44 | POWERDOWN_EXIT 45 | }; 46 | 47 | class DRAMCommand 48 | { 49 | public: 50 | // 51 | //Functions 52 | // 53 | DRAMCommand(DRAMCommandType cmdtype, unsigned tag, unsigned bnk, unsigned col, unsigned rw, unsigned dSize, 54 | bool pst, TranTrace *lat, bool last, PacketCommandType pktCMD, bool atm, bool seg); 55 | DRAMCommand(const DRAMCommand &dc); 56 | virtual ~DRAMCommand(); 57 | 58 | // 59 | //Fields 60 | // 61 | TranTrace *trace; 62 | DRAMCommandType commandType; 63 | unsigned packetTAG; 64 | unsigned bank; 65 | unsigned column; 66 | unsigned row; 67 | unsigned dataSize; //[Byte] 68 | bool posted; 69 | bool lastCMD; 70 | PacketCommandType packetCMD; 71 | bool atomic; 72 | bool segment; 73 | }; 74 | 75 | ostream& operator<<(ostream &out, const DRAMCommand &dc); 76 | } 77 | 78 | #endif -------------------------------------------------------------------------------- /sources/DualVectorObject.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef DUALVECTOROBJ_H 13 | #define DUALVECTOROBJ_H 14 | 15 | //DualVectorObject.h 16 | // 17 | //Header file for dual buffer object class 18 | // 19 | 20 | #include //vector 21 | 22 | #include "SimulatorObject.h" 23 | #include "Transaction.h" 24 | #include "Packet.h" 25 | 26 | namespace CasHMC 27 | { 28 | 29 | template 30 | class DualVectorObject : public SimulatorObject 31 | { 32 | public: 33 | DualVectorObject(ofstream &debugOut_, ofstream &stateOut_, int downBufMax, int upBufMax): 34 | SimulatorObject(debugOut_, stateOut_), downBufferMax(downBufMax), upBufferMax(upBufMax) { 35 | bufPopDelay = 0; 36 | downBuffers.reserve(downBufferMax); 37 | upBuffers.reserve(upBufferMax); 38 | } 39 | virtual ~DualVectorObject() { 40 | downBuffers.clear(); 41 | upBuffers.clear(); 42 | } 43 | virtual void Update()=0; 44 | void Step() { 45 | currentClockCycle++; 46 | bufPopDelay = (bufPopDelay>0) ? bufPopDelay-1 : 0; 47 | } 48 | 49 | bool ReceiveDown(DownT *downEle) { 50 | if(downBuffers.size() + downEle->LNG <= downBufferMax) { 51 | if(downBuffers.size() == 0) { 52 | bufPopDelay = (bufPopDelay>0) ? bufPopDelay : 1; 53 | } 54 | downBuffers.push_back(downEle); 55 | //If receiving packet is packet, add virtual tail packet in Buffers as long as packet length 56 | if(sizeof(*downEle) == sizeof(Packet)) { 57 | for(int i=1; iLNG; i++) { 58 | downBuffers.push_back(NULL); 59 | } 60 | } 61 | CallbackReceiveDown(downEle, true); 62 | return true; 63 | } 64 | else { 65 | CallbackReceiveDown(downEle, false); 66 | return false; 67 | } 68 | } 69 | bool ReceiveUp(UpT *upEle) { 70 | if(upBuffers.size() + upEle->LNG <= upBufferMax) { 71 | //Upstream buffer does not need upBufPopCycle (one cycle to pop one buffer data), 72 | // because upBufferDest (upstream buffer destination) is updated before buffer class. 73 | upBuffers.push_back(upEle); 74 | //If receiving packet is packet, add virtual tail packet in Buffers as long as packet length 75 | if(sizeof(*upEle) == sizeof(Packet)) { 76 | for(int i=1; iLNG; i++) { 77 | upBuffers.push_back(NULL); 78 | } 79 | } 80 | CallbackReceiveUp(upEle, true); 81 | return true; 82 | } 83 | else { 84 | CallbackReceiveUp(upEle, false); 85 | return false; 86 | } 87 | } 88 | virtual void CallbackReceiveDown(DownT *downEle, bool chkReceive)=0; 89 | virtual void CallbackReceiveUp(UpT *upEle, bool chkReceive)=0; 90 | 91 | int downBufferMax; 92 | int upBufferMax; 93 | vector downBuffers; 94 | vector upBuffers; 95 | int bufPopDelay; 96 | }; 97 | 98 | } 99 | 100 | #endif -------------------------------------------------------------------------------- /sources/HMC.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #include "HMC.h" 13 | 14 | namespace CasHMC 15 | { 16 | 17 | HMC::HMC(ofstream &debugOut_, ofstream &stateOut_): 18 | SimulatorObject(debugOut_, stateOut_) 19 | { 20 | clockTuner = 1; 21 | 22 | //Make class objects 23 | downLinkSlaves.reserve(NUM_LINKS); 24 | upLinkMasters.reserve(NUM_LINKS); 25 | for(int l=0; lrefreshCountdown = ((REFRESH_PERIOD/tCK)/NUM_VAULTS)*(v+1); 40 | } 41 | 42 | //Crossbar switch, and vault are linked each other by respective lanes 43 | for(int v=0; vdownBufferDest[v] = vaultControllers[v]; 46 | vaultControllers[v]->dramP = drams[v]; 47 | //Upstream 48 | vaultControllers[v]->upBufferDest = crossbarSwitch; 49 | } 50 | } 51 | 52 | HMC::~HMC() 53 | { 54 | for(int l=0; lUpdate(); 79 | } 80 | crossbarSwitch->Update(); 81 | for(int v=0; vUpdate(); 83 | } 84 | for(int v=0; vUpdate(); 86 | } 87 | for(int l=0; lUpdate(); 89 | } 90 | clockTuner++; 91 | Step(); 92 | } 93 | 94 | // 95 | //Print current state in state log file 96 | // 97 | void HMC::PrintState() 98 | { 99 | for(int l=0; lPrintState(); 101 | } 102 | crossbarSwitch->PrintState(); 103 | for(int v=0; vPrintState(); 105 | } 106 | for(int v=0; vPrintState(); 108 | } 109 | for(int l=0; lPrintState(); 111 | } 112 | } 113 | 114 | } //namespace CasHMC -------------------------------------------------------------------------------- /sources/HMC.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef HMC_H 13 | #define HMC_H 14 | 15 | //HMC.h 16 | 17 | #include //vector 18 | 19 | #include "SimulatorObject.h" 20 | #include "ConfigValue.h" 21 | #include "LinkSlave.h" 22 | #include "LinkMaster.h" 23 | #include "CrossbarSwitch.h" 24 | #include "VaultController.h" 25 | #include "DRAM.h" 26 | 27 | using namespace std; 28 | 29 | namespace CasHMC 30 | { 31 | 32 | class HMC : public SimulatorObject 33 | { 34 | public: 35 | // 36 | //Functions 37 | // 38 | HMC(ofstream &debugOut_, ofstream &stateOut_); 39 | virtual ~HMC(); 40 | void Update(); 41 | void PrintState(); 42 | 43 | // 44 | //Fields 45 | // 46 | uint64_t clockTuner; 47 | 48 | vector downLinkSlaves; 49 | vector upLinkMasters; 50 | CrossbarSwitch *crossbarSwitch; 51 | vector vaultControllers; 52 | vector drams; 53 | }; 54 | 55 | } 56 | 57 | #endif -------------------------------------------------------------------------------- /sources/HMCController.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef HMCCONTROLLER_H 13 | #define HMCCONTROLLER_H 14 | 15 | //HMCController.h 16 | 17 | #include //vector 18 | 19 | #include "DualVectorObject.h" 20 | #include "ConfigValue.h" 21 | #include "CallBack.h" 22 | #include "LinkMaster.h" 23 | #include "LinkSlave.h" 24 | 25 | using namespace std; 26 | 27 | namespace CasHMC 28 | { 29 | 30 | class HMCController : public DualVectorObject 31 | { 32 | public: 33 | // 34 | //Functions 35 | // 36 | HMCController(ofstream &debugOut_, ofstream &stateOut_); 37 | virtual ~HMCController(); 38 | void RegisterCallbacks(TransCompCB *readCB, TransCompCB *writeCB); 39 | void CallbackReceiveDown(Transaction *downEle, bool chkReceive); 40 | void CallbackReceiveUp(Packet *upEle, bool chkReceive); 41 | bool CanAcceptTran(); 42 | void Update(); 43 | Packet *ConvTranIntoPacket(Transaction *tran); 44 | void LinkPowerEntryManager(); 45 | void LinkPowerStateManager(); 46 | void LinkPowerExitManager(); 47 | void UpdateMSHR(unsigned mshr); 48 | void LinkStatistic(); 49 | void PrintState(); 50 | 51 | // 52 | //Fields 53 | // 54 | vector downLinkMasters; 55 | vector upLinkSlaves; 56 | int inServiceLink; 57 | 58 | unsigned maxLinkBand; 59 | unsigned linkEpochCycle; 60 | uint64_t requestAccLNG; 61 | uint64_t responseAccLNG; 62 | unsigned sleepLink; 63 | unsigned alloMSHR; 64 | uint64_t accuMSHR; 65 | 66 | unsigned returnTransCnt; 67 | unsigned quiesceClk; 68 | uint64_t staggerSleep; 69 | uint64_t staggerActive; 70 | uint64_t staySREF; 71 | vector stayActive; 72 | vector quiesceLink; 73 | vector modeTransition; 74 | vector staggeringSleep; 75 | vector staggeringActive; 76 | 77 | vector linkSleepTime; 78 | vector linkDownTime; 79 | 80 | TransCompCB *readDone; 81 | TransCompCB *writeDone; 82 | }; 83 | 84 | } 85 | 86 | #endif -------------------------------------------------------------------------------- /sources/Link.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #include "Link.h" 13 | #include "LinkMaster.h" 14 | 15 | namespace CasHMC 16 | { 17 | 18 | Link::Link(ofstream &debugOut_, ofstream &stateOut_, unsigned id, bool down, TranStatistic *statisP): 19 | SimulatorObject(debugOut_, stateOut_), 20 | linkID(id), 21 | downstream(down), 22 | statis(statisP) 23 | { 24 | classID << linkID; 25 | header = " (LK_"; 26 | header += downstream ? "D" : "U"; 27 | header += classID.str() + ")"; 28 | 29 | linkMasterP = NULL; 30 | linkSlaveP = NULL; 31 | inFlightPacket = NULL; 32 | inFlightCountdown = 0; 33 | 34 | //The probability of at least one bit error 35 | // (pow(10, -LINK_BER) - 1)/pow(10, -LINK_BER) : Probability of no error in one bit 36 | // (1 - pow((pow(10, -LINK_BER) - 1)/pow(10, -LINK_BER), 128)) : Probability of at least one bit error in 128 bits 37 | // errorProba is square root of bits size per one bit error, because errorProba is over than variable capacity. 38 | // Link error will be calculated two times by errorProba respectively 39 | errorProba = sqrt(1 / (1 - pow((pow(10, -LINK_BER) - 1)/pow(10, -LINK_BER), 128))); 40 | } 41 | 42 | Link::~Link() 43 | { 44 | } 45 | 46 | // 47 | //Update the state of link 48 | // 49 | void Link::Update(bool lastUpdate) 50 | { 51 | //Transmit packet from buffer 52 | if(linkMasterP->linkRxTx.size()>0 && linkMasterP->linkRxTx[0]->bufPopDelay==0 && inFlightPacket==NULL) { 53 | // if(linkMasterP->currentState == ACTIVE 54 | // || linkMasterP->currentState == LINK_RETRY 55 | // || (linkMasterP->currentState == START_RETRY && linkMasterP->linkRxTx[0]->CMD == IRTRY && linkMasterP->linkRxTx[0]->FRP == 1) 56 | // || ((linkMasterP->currentState == WAIT || linkMasterP->currentState == SLEEP) && linkMasterP->linkRxTx[0]->CMD == QUIET) 57 | // || linkMasterP->linkRxTx[0]->CMD == NULL_) { 58 | inFlightPacket = linkMasterP->linkRxTx[0]; 59 | UpdateStatistic(inFlightPacket); 60 | inFlightCountdown = (inFlightPacket->LNG * 128) / LINK_WIDTH; 61 | DEBUG(ALI(18)<linkRxTx.erase(linkMasterP->linkRxTx.begin()); 63 | // } 64 | } 65 | 66 | if(inFlightCountdown > 0) { 67 | inFlightCountdown--; 68 | //Packet transmission done 69 | if(inFlightCountdown == 0) { 70 | NoisePacket(inFlightPacket); 71 | DEBUG(ALI(18)<bufPopDelay = 1; 73 | linkSlaveP->linkRxTx.push_back(inFlightPacket); 74 | if(inFlightPacket->packetType == RESPONSE) 75 | inFlightPacket->trace->linkFullLat = linkSlaveP->currentClockCycle - inFlightPacket->trace->linkTransmitTime; 76 | inFlightPacket = NULL; 77 | } 78 | else if(lastUpdate) { 79 | DEBUG(ALI(18)<linkRxTx.size()>0) { 84 | for(int i=0; ilinkRxTx.size(); i++) { 85 | linkMasterP->linkRxTx[i]->bufPopDelay = (linkMasterP->linkRxTx[i]->bufPopDelay>0) ? linkMasterP->linkRxTx[i]->bufPopDelay-1 : 0; 86 | } 87 | } 88 | Step(); 89 | } 90 | 91 | // 92 | //Update the statistic of transmitting FILTs 93 | // 94 | void Link::UpdateStatistic(Packet *packet) 95 | { 96 | if(downstream) { 97 | statis->downLinkTransmitSize[linkID] += packet->LNG * 16; 98 | if(packet->LNG > 1) { 99 | statis->downLinkDataSize[linkID] += (packet->LNG-1) * 16; 100 | } 101 | } 102 | else { 103 | statis->upLinkTransmitSize[linkID] += packet->LNG * 16; 104 | if(packet->LNG > 1) { 105 | statis->upLinkDataSize[linkID] += (packet->LNG-1) * 16; 106 | } 107 | } 108 | 109 | switch(packet->packetType) { 110 | case REQUEST: 111 | statis->reqPerLink[linkID]++; 112 | packet->trace->linkTransmitTime = linkMasterP->currentClockCycle; 113 | 114 | if((WR16 <= packet->CMD && packet->CMD <= MD_WR) 115 | || packet->CMD == WR256 116 | || (P_WR16 <= packet->CMD && packet->CMD <= P_WR128) 117 | || packet->CMD == P_WR256) { 118 | statis->writePerLink[linkID]++; 119 | } 120 | else if((RD16 <= packet->CMD && packet->CMD <= RD128) 121 | || packet->CMD == RD256 122 | || packet->CMD == MD_RD) { 123 | statis->readPerLink[linkID]++; 124 | } 125 | else { 126 | statis->atomicPerLink[linkID]++; 127 | } 128 | break; 129 | case RESPONSE: 130 | statis->resPerLink[linkID]++; 131 | break; 132 | case FLOW: 133 | statis->flowPerLink[linkID]++; 134 | break; 135 | default: 136 | ERROR(header<<" == Error - Unknown packet type"); 137 | ERROR(" Type : "<packetType); 138 | exit(0); 139 | } 140 | } 141 | 142 | // 143 | //Make link noise on transmitting packet 144 | // 145 | void Link::NoisePacket(Packet *packet) 146 | { 147 | for(int i=0; iLNG; i++) { 148 | unsigned ranNum1 = rand(); 149 | unsigned ranNum2 = rand(); 150 | if(ranNum1%errorProba == 0 && ranNum2%errorProba == 0) { 151 | DE_CR(ALI(18)< Link ERROR is occurred <===="); 152 | packet->CRC = ~packet->CRC; 153 | break; 154 | } 155 | } 156 | } 157 | 158 | // 159 | //Print current state in state log file 160 | // 161 | void Link::PrintState() 162 | { 163 | if(inFlightPacket != NULL) { 164 | STATEN(ALI(17)<LNG); 168 | } 169 | } 170 | 171 | } //namespace CasHMC -------------------------------------------------------------------------------- /sources/Link.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef LINK_H 13 | #define LINK_H 14 | 15 | //Link.h 16 | 17 | #include //uint64_t 18 | 19 | #include "SingleVectorObject.h" 20 | #include "ConfigValue.h" 21 | 22 | using namespace std; 23 | 24 | namespace CasHMC 25 | { 26 | //forward declaration 27 | class LinkMaster; 28 | class Link : public SimulatorObject 29 | { 30 | public: 31 | // 32 | //Functions 33 | // 34 | Link(ofstream &debugOut_, ofstream &stateOut_, unsigned id, bool down, TranStatistic *statisP); 35 | virtual ~Link(); 36 | void Update() {}; 37 | void Update(bool lastUpdate); 38 | void UpdateStatistic(Packet *packet); 39 | void NoisePacket(Packet *packet); 40 | void PrintState(); 41 | 42 | // 43 | //Fields 44 | // 45 | unsigned linkID; 46 | bool downstream; 47 | unsigned errorProba; 48 | LinkMaster *linkMasterP; 49 | TranStatistic *statis; 50 | SingleVectorObject *linkSlaveP; 51 | 52 | //Currently transmitting packet through link 53 | Packet *inFlightPacket; 54 | unsigned inFlightCountdown; 55 | }; 56 | 57 | } 58 | 59 | #endif -------------------------------------------------------------------------------- /sources/LinkMaster.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef LINKMASTER_H 13 | #define LINKMASTER_H 14 | 15 | //LinkMaster.h 16 | 17 | #include //vector 18 | #include //pow() 19 | 20 | #include "SingleVectorObject.h" 21 | #include "ConfigValue.h" 22 | #include "TranStatistic.h" 23 | #include "Link.h" 24 | #include "LinkSlave.h" 25 | 26 | using namespace std; 27 | 28 | namespace CasHMC 29 | { 30 | enum LinkQuite 31 | { 32 | CHECK, 33 | QUITE, 34 | BUSY 35 | }; 36 | 37 | int FindAvailableLink(int &link, vector &LM); 38 | 39 | class LinkMaster : public SingleVectorObject 40 | { 41 | public: 42 | // 43 | //Functions 44 | // 45 | LinkMaster(ofstream &debugOut_, ofstream &stateOut_, unsigned id, bool down); 46 | virtual ~LinkMaster(); 47 | void CallbackReceive(Packet *packet, bool chkReceive); 48 | void UpdateRetryPointer(Packet *packet); 49 | void ReturnRetryPointer(Packet *packet); 50 | void UpdateToken(Packet *packet); 51 | void ReturnTocken(Packet *packet); 52 | void StartRetry(Packet *packet); 53 | void LinkRetry(Packet *packet); 54 | void FinishRetry(); 55 | void Update(); 56 | void CRCCountdown(int writeP, Packet *packet); 57 | void UpdateField(int nextWriteP, Packet *packet); 58 | void QuitePacket(); 59 | void FinishRetrain(); 60 | void PrintState(); 61 | 62 | // 63 | //Fields 64 | // 65 | unsigned linkMasterID; 66 | unsigned tokenCount; 67 | unsigned lastestRRP; 68 | Link *linkP; 69 | LinkSlave *localLinkSlave; 70 | vector backupBuffers; 71 | 72 | int masterSEQ; 73 | int countdownCRC; 74 | bool startCRC; 75 | 76 | Packet *retryStartPacket; 77 | bool readyStartRetry; 78 | bool startRetryTimer; 79 | unsigned retryTimer; 80 | unsigned retryAttempts; 81 | unsigned retBufReadP; 82 | unsigned retBufWriteP; 83 | unsigned retrainTransit; 84 | bool firstNull; 85 | vector retryBuffers; 86 | }; 87 | 88 | } 89 | 90 | #endif -------------------------------------------------------------------------------- /sources/LinkSlave.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #include "LinkSlave.h" 13 | #include "LinkMaster.h" 14 | 15 | namespace CasHMC 16 | { 17 | 18 | LinkSlave::LinkSlave(ofstream &debugOut_, ofstream &stateOut_, unsigned id, bool down): 19 | SingleVectorObject(debugOut_, stateOut_, MAX_LINK_BUF, down), 20 | linkSlaveID(id) 21 | { 22 | classID << linkSlaveID; 23 | header = " (LS_"; 24 | header += downstream ? "D" : "U"; 25 | header += classID.str() + ")"; 26 | 27 | slaveSEQ = 0; 28 | countdownCRC = 0; 29 | startCRC = false; 30 | downBufferDest = NULL; 31 | upBufferDest = NULL; 32 | localLinkMaster = NULL; 33 | } 34 | 35 | LinkSlave::~LinkSlave() 36 | { 37 | linkRxTx.clear(); 38 | } 39 | 40 | // 41 | //Callback receiving packet result 42 | // 43 | void LinkSlave::CallbackReceive(Packet *packet, bool chkReceive) 44 | { 45 | /* if(chkReceive) { 46 | DEBUG(ALI(18)<packetType == FLOW) { 53 | ERROR(header<<" == Error - flow packet "<<*packet<<" is not meant to be here"); 54 | exit(0); 55 | } 56 | else { 57 | if(!chkReceive) { 58 | ERROR(header<<" == Error - packet "<<*packet<<" is missed, because link slave buffer is FULL (CurrentClock : "< 0) { 71 | //Make sure that linkRxTx[0] is not virtual tail packet. 72 | if(linkRxTx[0] == NULL) { 73 | ERROR(header<<" == Error - linkRxTx[0] is NULL (It could be one of virtual tail packet (CurrentClock : "<bufPopDelay == 0) { 79 | //Link retraining sequence 80 | if(linkRxTx[i]->CMD == NULL_) { 81 | //[Responder descrambler initializing] 82 | //The responder descrambler sync should occur within tRESP1 of the PLL locking 83 | if(downstream && localLinkMaster->currentState == SLEEP) { 84 | localLinkMaster->firstNull = true; 85 | localLinkMaster->currentState = RETRAIN1; 86 | uint64_t tran = ceil((double)(tRESP1)/tCK); 87 | localLinkMaster->retrainTransit = currentClockCycle + tran; 88 | } 89 | //[Requester descrambler synchronization] 90 | else if(!downstream && localLinkMaster->currentState == RETRAIN1) { 91 | localLinkMaster->firstNull = true; 92 | localLinkMaster->currentState = RETRAIN2; 93 | } 94 | //[Responder FLIT synchrony] 95 | //Responder link lock should occur within tRESP2 96 | else if(downstream && localLinkMaster->currentState == RETRAIN1) { 97 | localLinkMaster->firstNull = true; 98 | localLinkMaster->currentState = RETRAIN2; 99 | uint64_t tran = ceil((double)(tRESP2)/tCK); 100 | localLinkMaster->retrainTransit = currentClockCycle + tran; 101 | } 102 | //[Requester FLIT synchrony and sending a minimum of 32 NULL FLITs before entering ACTIVE] 103 | else if(!downstream && localLinkMaster->currentState == RETRAIN2) { 104 | currentState = ACTIVE; 105 | localLinkMaster->FinishRetrain(); 106 | } 107 | //[sending a minimum of 32 NULL FLITs before entering ACTIVE] 108 | else if(downstream && localLinkMaster->currentState == RETRAIN2) { 109 | currentState = ACTIVE; 110 | localLinkMaster->FinishRetrain(); 111 | } 112 | delete linkRxTx[i]; 113 | linkRxTx.erase(linkRxTx.begin()+i); 114 | continue; 115 | } 116 | 117 | //Retry control 118 | if(linkRxTx[i]->CMD == IRTRY) { 119 | if(linkRxTx[i]->bufPopDelay == 0) { 120 | linkRxTx[i]->chkRRP = true; 121 | localLinkMaster->UpdateRetryPointer(linkRxTx[i]); 122 | if(linkRxTx[i]->FRP == 1) { 123 | if(localLinkMaster->currentState != LINK_RETRY) { 124 | localLinkMaster->LinkRetry(linkRxTx[i]); 125 | } 126 | } 127 | else if(linkRxTx[i]->FRP == 2) { 128 | if(localLinkMaster->currentState == START_RETRY 129 | || localLinkMaster->currentState == LINK_RETRY) { 130 | localLinkMaster->FinishRetry(); 131 | currentState = ACTIVE; 132 | slaveSEQ = 0; 133 | } 134 | } 135 | delete linkRxTx[i]; 136 | linkRxTx.erase(linkRxTx.begin()+i); 137 | break; 138 | } 139 | } 140 | else if(currentState == START_RETRY) { 141 | delete linkRxTx[i]; 142 | linkRxTx.erase(linkRxTx.begin()+i); 143 | break; 144 | } 145 | 146 | //Flow control 147 | if(linkRxTx[i]->chkRRP == false) { 148 | linkRxTx[i]->chkRRP = true; 149 | localLinkMaster->UpdateRetryPointer(linkRxTx[i]); 150 | 151 | //PRET packet is not saved in the retry buffer (No need to check CRC) 152 | if(linkRxTx[i]->CMD == PRET) { 153 | delete linkRxTx[i]; 154 | linkRxTx.erase(linkRxTx.begin()+i); 155 | break; 156 | } 157 | } 158 | 159 | //Link low power mode control 160 | if(linkRxTx[i]->CMD == QUIET) { 161 | //(upstream) all-way links are checked to enter sleep mode 162 | if(localLinkMaster->currentState == WAIT) { 163 | localLinkMaster->currentState = CONFIRM; 164 | DEBUG(ALI(18)<chkRRP == true && linkRxTx[i]->chkCRC == false) { 180 | if(CRC_CHECK && !startCRC) { 181 | startCRC = true; 182 | countdownCRC = ceil((double)CRC_CAL_CYCLE * linkRxTx[i]->LNG); 183 | } 184 | 185 | if(CRC_CHECK && countdownCRC > 0) { 186 | DEBUG(ALI(18)<LNG)<<")"); 188 | } 189 | else { 190 | //Error check 191 | linkRxTx[i]->chkCRC = true; 192 | if(CheckNoError(linkRxTx[i])) { 193 | localLinkMaster->ReturnRetryPointer(linkRxTx[i]); 194 | localLinkMaster->UpdateToken(linkRxTx[i]); 195 | if(linkRxTx[i]->CMD != TRET) { 196 | Receive(linkRxTx[i]); 197 | } 198 | else { 199 | delete linkRxTx[i]; 200 | } 201 | linkRxTx.erase(linkRxTx.begin()+i); 202 | break; 203 | } 204 | //Error abort mode 205 | else { 206 | if(localLinkMaster->retryStartPacket == NULL) { 207 | localLinkMaster->retryStartPacket = new Packet(*linkRxTx[i]); 208 | } 209 | else { 210 | ERROR(header<<" == Error - localLinkMaster->retryStartPacket is NOT NULL (CurrentClock : "<StartRetry(linkRxTx[i]); 214 | localLinkMaster->linkP->statis->errorPerLink[linkSlaveID]++; 215 | for(int j=0; j0) ? countdownCRC-1 : 0; 228 | } 229 | } 230 | } 231 | } 232 | } 233 | 234 | //Checking the link state to enter sleep mode 235 | if(currentState == WAIT) { 236 | //Link is ready for low power mode 237 | if(localLinkMaster->Buffers.size() == 0 238 | && localLinkMaster->retBufReadP == localLinkMaster->retBufWriteP 239 | && localLinkMaster->tokenCount == MAX_LINK_BUF) { 240 | currentState = SLEEP; 241 | localLinkMaster->currentState = SLEEP; 242 | localLinkMaster->QuitePacket(); 243 | } 244 | } 245 | 246 | //Sending packet 247 | if(Buffers.size() > 0) { 248 | bool chkRcv = (downstream ? downBufferDest->ReceiveDown(Buffers[0]) : upBufferDest->ReceiveUp(Buffers[0])); 249 | if(chkRcv) { 250 | localLinkMaster->ReturnTocken(Buffers[0]); 251 | DEBUG(ALI(18)<LNG); 254 | } 255 | else { 256 | //DEBUG(ALI(18)<bufPopDelay = (linkRxTx[i]->bufPopDelay>0) ? linkRxTx[i]->bufPopDelay-1 : 0; 264 | } 265 | } 266 | } 267 | 268 | // 269 | //Check error in receiving packet by CRC and SEQ 270 | // 271 | bool LinkSlave::CheckNoError(Packet *chkPacket) 272 | { 273 | unsigned tempSEQ = (slaveSEQ<7) ? slaveSEQ++ : 0; 274 | if(CRC_CHECK) { 275 | unsigned tempCRC = chkPacket->GetCRC(); 276 | if(chkPacket->CRC == tempCRC) { 277 | if(chkPacket->SEQ == tempSEQ) { 278 | DEBUG(ALI(18)<SEQ<<" / Slave SEQ : "<SEQ<<" / Slave SEQ : "<CRC<SEQ == tempSEQ) { 299 | DEBUG(ALI(18)<SEQ<<" / Slave SEQ : "<0) { 318 | STATEN(ALI(17)<0 && i%8==0) { 323 | STATEN(endl<<" "); 324 | } 325 | if(i < Buffers.size()) { 326 | if(Buffers[i] != NULL) realInd = i; 327 | STATEN(*Buffers[realInd]); 328 | } 329 | else if(i == bufferMax-1) { 330 | STATEN("[ - ]"); 331 | } 332 | else { 333 | STATEN("[ - ]..."); 334 | break; 335 | } 336 | } 337 | STATEN(endl); 338 | } 339 | 340 | //Print linkRx buffer 341 | if(linkRxTx.size()>0) { 342 | STATEN(ALI(17)<0 && i%8==0) { 347 | STATEN(endl<<" "); 348 | } 349 | if(linkRxTx[i] != NULL) realInd = i; 350 | STATEN(*linkRxTx[realInd]); 351 | } 352 | STATEN(endl); 353 | } 354 | } 355 | 356 | } //namespace CasHMC -------------------------------------------------------------------------------- /sources/LinkSlave.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef LINKSLAVE_H 13 | #define LINKSLAVE_H 14 | 15 | //LinkSlave.h 16 | 17 | #include //vector 18 | 19 | #include "SingleVectorObject.h" 20 | #include "DualVectorObject.h" 21 | #include "ConfigValue.h" 22 | #include "Packet.h" 23 | 24 | using namespace std; 25 | 26 | namespace CasHMC 27 | { 28 | //forward declaration 29 | class LinkMaster; 30 | class LinkSlave : public SingleVectorObject 31 | { 32 | public: 33 | // 34 | //Functions 35 | // 36 | LinkSlave(ofstream &debugOut_, ofstream &stateOut_, unsigned id, bool down); 37 | virtual ~LinkSlave(); 38 | void CallbackReceive(Packet *packet, bool chkReceive); 39 | void Update(); 40 | bool CheckNoError(Packet *chkPacket); 41 | void PrintState(); 42 | 43 | // 44 | //Fields 45 | // 46 | unsigned linkSlaveID; 47 | DualVectorObject *downBufferDest; 48 | DualVectorObject *upBufferDest; 49 | LinkMaster *localLinkMaster; 50 | 51 | int slaveSEQ; 52 | int countdownCRC; 53 | bool startCRC; 54 | }; 55 | 56 | } 57 | 58 | #endif -------------------------------------------------------------------------------- /sources/Packet.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #include "Packet.h" 13 | 14 | using namespace std; 15 | 16 | extern unsigned packetGlobalTAG; 17 | 18 | namespace CasHMC 19 | { 20 | 21 | //Request packet 22 | Packet::Packet(PacketType packet, PacketCommandType cmd, uint64_t addr, unsigned cub, unsigned lng, TranTrace *lat): 23 | trace(lat), 24 | packetType(packet), 25 | CUB(cub), 26 | LNG(lng), 27 | CMD(cmd), 28 | ADRS(addr) 29 | { 30 | bufPopDelay=1; 31 | CRCtable[256]=0; 32 | Pb=0; 33 | CRC=0; RTC=0; SLID=0; 34 | SEQ=0; FRP=0; RRP=0; 35 | AF=0; ERRSTAT=0; DINV=0; 36 | chkCRC = false; 37 | chkRRP = false; 38 | segment = false; 39 | reqDataSize=16; //The minimum size is 16-Byte 40 | 41 | if(packet != FLOW) { 42 | TAG = (packetGlobalTAG++)%2048; 43 | } 44 | else { 45 | TAG = 0; 46 | } 47 | 48 | ADRS = (ADRS<<30)>>30; //Address length is 34 bits 49 | 50 | if(CRC_CHECK) { 51 | if(LNG>1) { 52 | DATA = new uint64_t[(LNG-1)*2]; 53 | uint64_t tempData; 54 | for(int i=0; i<(LNG-1)*2; i++) { 55 | tempData = rand(); 56 | tempData = (tempData<<32)|rand(); 57 | DATA[i] = tempData; 58 | } 59 | } 60 | else { 61 | DATA = NULL; 62 | } 63 | MakeCRCtable(CRCtable, 0xEB31D82E); 64 | } 65 | else { 66 | DATA = NULL; 67 | } 68 | } 69 | //Response packet 70 | Packet::Packet(PacketType packet, PacketCommandType cmd, unsigned tag, unsigned lng, TranTrace *lat): 71 | trace(lat), 72 | packetType(packet), 73 | TAG(tag), 74 | LNG(lng), 75 | CMD(cmd) 76 | { 77 | bufPopDelay=1; 78 | CRCtable[256]=0; 79 | CUB=0; Pb=0; 80 | CRC=0; RTC=0; SLID=0; 81 | SEQ=0; FRP=0; RRP=0; 82 | AF=0; ERRSTAT=0; DINV=0; 83 | chkCRC = false; 84 | chkRRP = false; 85 | segment = false; 86 | reqDataSize=16; //The minimum size is 16-Byte 87 | 88 | if(CRC_CHECK) { 89 | if(LNG>1) { 90 | DATA = new uint64_t[(LNG-1)*2]; 91 | uint64_t tempData; 92 | for(int i=0; i<(LNG-1)*2; i++) { 93 | tempData = rand(); 94 | tempData = (tempData<<32)|rand(); 95 | DATA[i] = tempData; 96 | } 97 | } 98 | else { 99 | DATA = NULL; 100 | } 101 | MakeCRCtable(CRCtable, 0xEB31D82E); 102 | } 103 | else { 104 | DATA = NULL; 105 | } 106 | } 107 | 108 | Packet::~Packet() 109 | { 110 | if(DATA != NULL) { 111 | delete[] DATA; 112 | } 113 | } 114 | 115 | Packet::Packet(const Packet &f) 116 | { 117 | trace = f.trace; 118 | packetType = f.packetType; 119 | bufPopDelay = f.bufPopDelay; 120 | chkCRC = f.chkCRC; 121 | chkRRP = f.chkRRP; 122 | segment = f.segment; 123 | reqDataSize = f.reqDataSize; 124 | 125 | CUB = f.CUB; TAG = f.TAG; 126 | LNG = f.LNG; CMD = f.CMD; 127 | 128 | CRC = f.CRC; RTC = f.RTC; 129 | SLID = f.SLID; SEQ = f.SEQ; 130 | FRP = f.FRP; RRP = f.RRP; 131 | 132 | ADRS = f.ADRS; Pb = f.Pb; 133 | 134 | AF = f.AF; ERRSTAT = f.ERRSTAT; 135 | DINV = f.DINV; 136 | 137 | if(CRC_CHECK) { 138 | if(LNG>1) { 139 | DATA = new uint64_t[(LNG-1)*2]; 140 | uint64_t tempData; 141 | for(int i=0; i<(LNG-1)*2; i++) { 142 | tempData = rand(); 143 | tempData = (tempData<<32)|rand(); 144 | DATA[i] = tempData; 145 | } 146 | } 147 | else { 148 | DATA = NULL; 149 | } 150 | MakeCRCtable(CRCtable, 0xEB31D82E); 151 | } 152 | else { 153 | DATA = NULL; 154 | } 155 | } 156 | 157 | // 158 | //Set Packet data included header, data, and tail for CRC generation 159 | // 160 | unsigned long Packet::GetCRC() 161 | { 162 | uint64_t packetData[LNG*2]; 163 | 164 | if(packetType == REQUEST) { 165 | packetData[0] <<= 3; packetData[0] |= (CUB&0x7); 166 | packetData[0] <<= 3; packetData[0] |= (RES&0x7); 167 | packetData[0] <<= 34; packetData[0] |= (ADRS&0x3FFFFFFFF); 168 | packetData[0] <<= 1; packetData[0] |= (RES&0x1); 169 | packetData[0] <<= 11; packetData[0] |= (TAG&0x7FF); 170 | packetData[0] <<= 5; packetData[0] |= (LNG&0x1F); 171 | packetData[0] <<= 7; packetData[0] |= (CMD&0x7F); 172 | } 173 | else { 174 | packetData[0] <<= 3; packetData[0] |= (CUB&0x7); 175 | packetData[0] <<= 19; packetData[0] |= (RES&0x7FFFF); 176 | packetData[0] <<= 3; packetData[0] |= (SLID&0x7); 177 | packetData[0] <<= 5; packetData[0] |= (RES&0x1F); 178 | packetData[0] <<= 1; packetData[0] |= (AF&0x1); 179 | packetData[0] <<= 10; packetData[0] |= (RES&0x3FF); 180 | packetData[0] <<= 11; packetData[0] |= (TAG&0x7FF); 181 | packetData[0] <<= 5; packetData[0] |= (LNG&0x1F); 182 | packetData[0] <<= 7; packetData[0] |= (CMD&0x7F); 183 | } 184 | 185 | for(int i=1; i<=(LNG-1)*2; i++){ 186 | packetData[i]=DATA[i-1]; 187 | } 188 | 189 | if(packetType == REQUEST) { 190 | packetData[LNG*2-1] <<= 32; packetData[LNG*2-1] |= (0&0xFFFFFFFF); //CRC initial value is '0' before CRC calculation 191 | packetData[LNG*2-1] <<= 3; packetData[LNG*2-1] |= (RTC&0x7); 192 | packetData[LNG*2-1] <<= 3; packetData[LNG*2-1] |= (SLID&0x7); 193 | packetData[LNG*2-1] <<= 4; packetData[LNG*2-1] |= (RES&0xF); 194 | packetData[LNG*2-1] <<= 1; packetData[LNG*2-1] |= (Pb&0x1); 195 | packetData[LNG*2-1] <<= 3; packetData[LNG*2-1] |= (SEQ&0x7); 196 | packetData[LNG*2-1] <<= 9; packetData[LNG*2-1] |= (FRP&0x1FF); 197 | packetData[LNG*2-1] <<= 9; packetData[LNG*2-1] |= (RRP&0x1FF); 198 | } 199 | else { 200 | packetData[LNG*2-1] <<= 32; packetData[LNG*2-1] |= (0&0xFFFFFFFF); //CRC initial value is '0' before CRC calculation 201 | packetData[LNG*2-1] <<= 3; packetData[LNG*2-1] |= (RTC&0x7); 202 | packetData[LNG*2-1] <<= 7; packetData[LNG*2-1] |= (ERRSTAT&0x7F); 203 | packetData[LNG*2-1] <<= 1; packetData[LNG*2-1] |= (DINV&0x1); 204 | packetData[LNG*2-1] <<= 3; packetData[LNG*2-1] |= (SEQ&0x7); 205 | packetData[LNG*2-1] <<= 9; packetData[LNG*2-1] |= (FRP&0x1FF); 206 | packetData[LNG*2-1] <<= 9; packetData[LNG*2-1] |= (RRP&0x1FF); 207 | } 208 | 209 | unsigned char buf[8]; 210 | uint32_t crc = 0; 211 | 212 | for(int j=0; j>= 8; 216 | } 217 | crc = CalcCRC(buf, 8, crc, CRCtable); 218 | } 219 | return crc; 220 | } 221 | 222 | // 223 | //Makes remainder table diveded by polynomial (CRC-32K) 224 | // 225 | void Packet::MakeCRCtable(uint32_t *table, uint32_t id) 226 | { 227 | uint32_t k; 228 | for(int i=0; i<256; ++i){ 229 | k = i; 230 | for(int j=0; j<8; ++j){ 231 | if(k&1) k = (k >> 1) ^ id; 232 | else k >>= 1; 233 | } 234 | table[i] = k; 235 | } 236 | } 237 | 238 | // 239 | //Calculates CRC value 240 | // 241 | uint32_t Packet::CalcCRC(const unsigned char *mem, signed int size, uint32_t crc, uint32_t *table) 242 | { 243 | crc = ~crc; 244 | while(size--){ 245 | crc = table[(crc ^ *(mem++)) & 0xFF] ^ (crc >> 8); 246 | } 247 | return ~crc; 248 | } 249 | 250 | // 251 | //Reduction packetGlobalTAG 252 | // 253 | void Packet::ReductGlobalTAG() 254 | { 255 | packetGlobalTAG--; 256 | } 257 | 258 | // 259 | //Defines "<<" operation for printing 260 | // 261 | ostream& operator<<(ostream &out, const Packet &f) 262 | { 263 | string header; 264 | stringstream id; 265 | id << f.TAG; 266 | 267 | switch(f.CMD) { 268 | //Request commands 269 | case WR16: header = "[P" + id.str() + "-WR16]"; break; case WR32: header = "[P" + id.str() + "-WR32]"; break; 270 | case WR48: header = "[P" + id.str() + "-WR48]"; break; case WR64: header = "[P" + id.str() + "-WR64]"; break; 271 | case WR80: header = "[P" + id.str() + "-WR80]"; break; case WR96: header = "[P" + id.str() + "-WR96]"; break; 272 | case WR112: header = "[P" + id.str() + "-WR112]"; break; case WR128: header = "[P" + id.str() + "-WR128]"; break; 273 | case MD_WR: header = "[P" + id.str() + "-MD_WR]"; break; case WR256: header = "[P" + id.str() + "-WR256]"; break; 274 | case P_WR16: header = "[P" + id.str() + "-P_WR16]"; break; case P_WR32: header = "[P" + id.str() + "-P_WR32]"; break; 275 | case P_WR48: header = "[P" + id.str() + "-P_WR48]"; break; case P_WR64: header = "[P" + id.str() + "-P_WR64]"; break; 276 | case P_WR80: header = "[P" + id.str() + "-P_WR80]"; break; case P_WR96: header = "[P" + id.str() + "-P_WR96]"; break; 277 | case P_WR112: header = "[P" + id.str() + "-P_WR112]"; break; case P_WR128: header = "[P" + id.str() + "-P_WR128]"; break; 278 | case P_WR256: header = "[P" + id.str() + "-P_WR256]"; break; 279 | case RD16: header = "[P" + id.str() + "-RD16]"; break; case RD32: header = "[P" + id.str() + "-RD32]"; break; 280 | case RD48: header = "[P" + id.str() + "-RD48]"; break; case RD64: header = "[P" + id.str() + "-RD64]"; break; 281 | case RD80: header = "[P" + id.str() + "-RD80]"; break; case RD96: header = "[P" + id.str() + "-RD96]"; break; 282 | case RD112: header = "[P" + id.str() + "-RD112]"; break; case RD128: header = "[P" + id.str() + "-RD128]"; break; 283 | case RD256: header = "[P" + id.str() + "-RD256]"; break; case MD_RD: header = "[P" + id.str() + "-MD_RD]"; break; 284 | //ATOMICS commands 285 | case _2ADD8: header = "[P" + id.str() + "-2ADD8]"; break; case ADD16: header = "[P" + id.str() + "-ADD16]"; break; 286 | case P_2ADD8: header = "[P" + id.str() + "-P_2ADD8]"; break; case P_ADD16: header = "[P" + id.str() + "-P_ADD16]"; break; 287 | case _2ADDS8R: header = "[P" + id.str() + "-2ADDS8R]"; break; case ADDS16R: header = "[P" + id.str() + "-ADDS16R]"; break; 288 | case INC8: header = "[P" + id.str() + "-INC8]"; break; case P_INC8: header = "[P" + id.str() + "-P_INC8]"; break; 289 | case XOR16: header = "[P" + id.str() + "-XOR16]"; break; case OR16: header = "[P" + id.str() + "-OR16]"; break; 290 | case NOR16: header = "[P" + id.str() + "-NOR16]"; break; case AND16: header = "[P" + id.str() + "-AND16]"; break; 291 | case NAND16: header = "[P" + id.str() + "-NAND16]"; break; case CASGT8: header = "[P" + id.str() + "-CASGT8]"; break; 292 | case CASLT8: header = "[P" + id.str() + "-CASLT8]"; break; case CASGT16: header = "[P" + id.str() + "-CASGT16]"; break; 293 | case CASLT16: header = "[P" + id.str() + "-CASLT16]"; break; case CASEQ8: header = "[P" + id.str() + "-CASEQ8]"; break; 294 | case CASZERO16: header = "[P" + id.str() + "-CASZR16]"; break; case EQ16: header = "[P" + id.str() + "-EQ16]"; break; 295 | case EQ8: header = "[P" + id.str() + "-EQ8]"; break; case BWR: header = "[P" + id.str() + "-BWR]"; break; 296 | case P_BWR: header = "[P" + id.str() + "-P_BWR]"; break; case BWR8R: header = "[P" + id.str() + "-BWR8R]"; break; 297 | case SWAP16: header = "[P" + id.str() + "-SWAP16]"; break; 298 | //Flow Commands 299 | case NULL_: header = "[P" + id.str() + "-NULL]"; break; case PRET: header = "[P" + id.str() + "-PRET]"; break; 300 | case TRET: header = "[P" + id.str() + "-TRET]"; break; 301 | case IRTRY: if(f.FRP==1) header = "[P" + id.str() + "-IRTRY1]"; 302 | else if(f.FRP==2) header = "[P" + id.str() + "-IRTRY2]"; 303 | else header = "[P" + id.str() + "-IRTRY]"; break; 304 | case QUIET: if(f.FRP==1) header = "[P" + id.str() + "-QUIET1]"; 305 | else if(f.FRP==2) header = "[P" + id.str() + "-QUIET2]"; 306 | else header = "[P" + id.str() + "-QUIET]"; break; 307 | //Respond commands 308 | case RD_RS: header = "[P" + id.str() + "-RD_RS]"; break; case WR_RS: header = "[P" + id.str() + "-WR_RS]"; break; 309 | case MD_RD_RS: header = "[P" + id.str() + "-MD_RD_RS]"; break; case MD_WR_RS: header = "[P" + id.str() + "-MD_WR_RS]"; break; 310 | case ERROR: header = "[P" + id.str() + "-ERROR]"; break; 311 | default: 312 | ERROR(" (FL) == Error - Trying to print unknown kind of Packet CMD type"); 313 | ERROR(" F-"< //uint64_t 18 | #include //exit(0) 19 | #include //setw() 20 | #include //ostream 21 | #include //stringstream 22 | 23 | #include "ConfigValue.h" 24 | #include "TranTrace.h" 25 | 26 | #define RES 0 27 | 28 | using namespace std; 29 | 30 | namespace CasHMC 31 | { 32 | 33 | enum PacketType 34 | { 35 | REQUEST, 36 | RESPONSE, 37 | FLOW 38 | }; 39 | 40 | enum PacketCommandType 41 | { 42 | //Request commands 43 | WR16=8, WR32, WR48, WR64, WR80, WR96, WR112, WR128, MD_WR, WR256=79, //WRITE Requests 44 | P_WR16=24, P_WR32, P_WR48, P_WR64, P_WR80, P_WR96, P_WR112, P_WR128, P_WR256=95, //POSTED WRITE Requests 45 | RD16=48, RD32, RD48, RD64, RD80, RD96, RD112, RD128, RD256=119, MD_RD=40, //READ Requests 46 | //ATOMICS commands 47 | _2ADD8=18, ADD16, P_2ADD8=34, P_ADD16, _2ADDS8R=82, ADDS16R, INC8=80, P_INC8=84, //ARITHMETIC ATOMICS 48 | XOR16=64, OR16, NOR16, AND16, NAND16, //BOOLEAN ATOMICS 49 | CASGT8=96, CASLT8, CASGT16, CASLT16, CASEQ8, CASZERO16, EQ16=104, EQ8, //COMPARISON ATOMICS 50 | BWR=17, P_BWR=33, BWR8R=81, SWAP16=106, //BITWISE ATOMICS 51 | //Flow Commands 52 | NULL_=0, PRET=1, TRET=2, IRTRY=3, QUIET=4, 53 | 54 | //Respond commands 55 | RD_RS=56, WR_RS, MD_RD_RS, MD_WR_RS, ERROR=62 56 | }; 57 | 58 | class Packet 59 | { 60 | public: 61 | //Functions 62 | Packet(PacketType packet, PacketCommandType cmd, uint64_t addr, unsigned cub, unsigned lng, TranTrace *lat); //Request Packet 63 | Packet(PacketType packet, PacketCommandType cmd, unsigned tag, unsigned lng, TranTrace *lat); //Response Packet 64 | virtual ~Packet(); 65 | Packet(const Packet &f); 66 | unsigned long GetCRC(); 67 | void MakeCRCtable(uint32_t *table, uint32_t id); 68 | uint32_t CalcCRC(const unsigned char *mem, signed int size, uint32_t crc, uint32_t *table); 69 | void ReductGlobalTAG(); 70 | 71 | //Fields 72 | TranTrace *trace; 73 | PacketType packetType; //Type of transaction (defined above) 74 | int bufPopDelay; 75 | uint64_t *DATA; 76 | uint32_t CRCtable[256]; 77 | bool chkCRC; 78 | bool chkRRP; 79 | bool segment; 80 | unsigned reqDataSize; 81 | 82 | //Packet Common Fields 83 | unsigned CUB, TAG, LNG; 84 | PacketCommandType CMD; 85 | 86 | unsigned CRC, RTC, SLID; 87 | unsigned SEQ, FRP, RRP; 88 | 89 | //Request Packet Fields 90 | uint64_t ADRS; 91 | unsigned Pb; 92 | 93 | //Response Packet Fields 94 | unsigned AF, ERRSTAT, DINV; 95 | }; 96 | 97 | ostream& operator<<(ostream &out, const Packet &t); 98 | } 99 | 100 | #endif -------------------------------------------------------------------------------- /sources/RunSim.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #include //getopt_long 13 | #include //exit(0) 14 | #include //ofstream 15 | #include //vector 16 | 17 | #include "CasHMCWrapper.h" 18 | #include "Transaction.h" 19 | #include "CallBack.h" 20 | 21 | using namespace std; 22 | using namespace CasHMC; 23 | 24 | extern long numSimCycles; 25 | extern string traceType; 26 | extern double memUtil; 27 | extern double rwRatio; 28 | extern string traceFileName; 29 | 30 | uint64_t lineNumber = 1; 31 | vector transactionBuffers; 32 | CasHMCWrapper *casHMCWrapper; 33 | 34 | #ifdef CALLBACKTRANS 35 | class CallbackTrans 36 | { 37 | public: 38 | void ReadComplete(uint64_t addr, uint64_t cycle) { 39 | cout<<" # ["<>clockCycle; 86 | previousIndex = spaceIndex; 87 | 88 | spaceIndex = line.find_first_not_of(" ", previousIndex); 89 | if(spaceIndex==-1) ERROR(" == Error - tracefile format is wrong : "<>hex>>addr; 93 | previousIndex = line.find_first_of(" ", spaceIndex); 94 | 95 | spaceIndex = line.find_first_not_of(" ", previousIndex); 96 | if(spaceIndex==-1) ERROR(" == Error - tracefile format is wrong : "<>dataSize; 143 | } 144 | 145 | int main(int argc, char **argv) 146 | { 147 | // 148 | //parse command-line options setting 149 | // 150 | numSimCycles = 100000; 151 | memUtil = 0.1; 152 | rwRatio = 80; 153 | traceType = ""; 154 | traceFileName = ""; 155 | 156 | int opt; 157 | string pwdString = ""; 158 | ifstream traceFile; 159 | string line; 160 | bool pendingTran = false; 161 | while(1) { 162 | static struct option long_options[] = { 163 | {"pwd", required_argument, 0, 'p'}, 164 | {"cycle", required_argument, 0, 'c'}, 165 | {"trace", required_argument, 0, 't'}, 166 | {"util", required_argument, 0, 'u'}, 167 | {"rwratio", required_argument, 0, 'r'}, 168 | {"file", required_argument, 0, 'f'}, 169 | {"help", no_argument, 0, 'h'}, 170 | {0, 0, 0, 0} 171 | }; 172 | int option_index=0; 173 | opt = getopt_long (argc, argv, "p:c:t:u:r:f:h", long_options, &option_index); 174 | if(opt == -1) { 175 | break; 176 | } 177 | switch(opt) { 178 | case 0: 179 | if (long_options[option_index].flag != 0) { 180 | cout<<"setting flag"< 1) { 206 | cout< 100) { 214 | cout<(&callbackTrans, &CallbackTrans::ReadComplete); 242 | TransCompCB* write_cb = new Callback(&callbackTrans, &CallbackTrans::WriteComplete); 243 | casHMCWrapper->RegisterCallbacks(read_cb, write_cb); 244 | #endif 245 | 246 | if(traceType == "random") { 247 | for(uint64_t cpuCycle=0; cpuCycleReceiveTran(transactionBuffers[0])) { 251 | transactionBuffers.erase(transactionBuffers.begin()); 252 | } 253 | } 254 | casHMCWrapper->Update(); 255 | } 256 | } 257 | else if(traceType == "file") { 258 | uint64_t issueClock = 0; 259 | traceFile.open(traceFileName.c_str()); 260 | if(!traceFile.is_open()) { 261 | ERROR(" == Error - Could not open trace file ["< 0) { 269 | uint64_t addr; 270 | TransactionType tranType; 271 | unsigned dataSize; 272 | ParseTraceFileLine(line, issueClock, addr, tranType, dataSize); 273 | Transaction *newTran = new Transaction(tranType, addr, dataSize, casHMCWrapper); 274 | 275 | if(cpuCycle >= issueClock) { 276 | if(!casHMCWrapper->ReceiveTran(newTran)) { 277 | pendingTran = true; 278 | transactionBuffers.push_back(newTran); 279 | } 280 | } 281 | else { 282 | pendingTran = true; 283 | transactionBuffers.push_back(newTran); 284 | } 285 | } 286 | else { 287 | cout<<" ## WARNING ## Skipping line ("<= issueClock) { 294 | if(casHMCWrapper->ReceiveTran(transactionBuffers[0])) { 295 | pendingTran = false; 296 | transactionBuffers.erase(transactionBuffers.begin()); 297 | } 298 | } 299 | } 300 | casHMCWrapper->Update(); 301 | } 302 | } 303 | 304 | transactionBuffers.clear(); 305 | delete casHMCWrapper; 306 | casHMCWrapper = NULL; 307 | 308 | return 0; 309 | } -------------------------------------------------------------------------------- /sources/SimulatorObject.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef SIMULATOROBJ_H 13 | #define SIMULATOROBJ_H 14 | 15 | //SimulatorObject.h 16 | // 17 | //Header file for simulator object class 18 | // 19 | 20 | #include //uint64_t 21 | #include //ofstream 22 | #include //setw() 23 | #include //stringstream 24 | 25 | using namespace std; 26 | 27 | namespace CasHMC 28 | { 29 | 30 | class SimulatorObject 31 | { 32 | public: 33 | SimulatorObject(ofstream &debugOut_, ofstream &stateOut_):debugOut(debugOut_), stateOut(stateOut_) { 34 | currentClockCycle = 0; 35 | } 36 | virtual ~SimulatorObject() {}; 37 | virtual void Update()=0; 38 | void Step() { 39 | currentClockCycle++; 40 | } 41 | 42 | uint64_t currentClockCycle; 43 | 44 | //Output log files 45 | ofstream &debugOut; 46 | ofstream &stateOut; 47 | string header; 48 | stringstream classID; 49 | 50 | }; 51 | 52 | } 53 | 54 | #endif -------------------------------------------------------------------------------- /sources/SingleVectorObject.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef SINGLEVECTOROBJ_H 13 | #define SINGLEVECTOROBJ_H 14 | 15 | //SingleVectorObject.h 16 | // 17 | //Header file for single buffer object class 18 | // 19 | 20 | #include //vector 21 | 22 | #include "SimulatorObject.h" 23 | #include "Transaction.h" 24 | #include "Packet.h" 25 | 26 | namespace CasHMC 27 | { 28 | enum LinkState 29 | { 30 | ACTIVE, 31 | SLEEP, 32 | DOWN, 33 | RETRAIN1, 34 | RETRAIN2, 35 | WAIT, 36 | CONFIRM, 37 | TRANSITION_TO_RETRAIN, 38 | TRANSITION_TO_SLEEP, 39 | TRANSITION_TO_DOWN, 40 | START_RETRY, 41 | LINK_RETRY 42 | }; 43 | 44 | template 45 | class SingleVectorObject : public SimulatorObject 46 | { 47 | public: 48 | SingleVectorObject(ofstream &debugOut_, ofstream &stateOut_, int bufMax, bool down): 49 | SimulatorObject(debugOut_, stateOut_), bufferMax(bufMax), downstream(down) { 50 | currentState = ACTIVE; 51 | Buffers.reserve(bufferMax); 52 | } 53 | virtual ~SingleVectorObject() { 54 | Buffers.clear(); 55 | linkRxTx.clear(); 56 | } 57 | virtual void Update()=0; 58 | void Step() { 59 | currentClockCycle++; 60 | for(int i=0; ibufPopDelay = (Buffers[i]->bufPopDelay>0) ? Buffers[i]->bufPopDelay-1 : 0; 63 | } 64 | } 65 | } 66 | 67 | bool Receive(BufT *ele) { 68 | if(Buffers.size() + ele->LNG <= bufferMax) { 69 | Buffers.push_back(ele); 70 | //If receiving packet is packet, add virtual tail packet in Buffers as long as packet length 71 | if(sizeof(*ele) == sizeof(Packet)) { 72 | for(int i=1; iLNG; i++) { 73 | Buffers.push_back(NULL); 74 | } 75 | } 76 | CallbackReceive(ele, true); 77 | return true; 78 | } 79 | else { 80 | CallbackReceive(ele, false); 81 | return false; 82 | } 83 | } 84 | virtual void CallbackReceive(BufT *ele, bool chkReceive)=0; 85 | 86 | int bufferMax; 87 | bool downstream; 88 | vector Buffers; 89 | vector linkRxTx; 90 | LinkState currentState; 91 | }; 92 | 93 | } 94 | 95 | #endif -------------------------------------------------------------------------------- /sources/TranStatistic.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef TRANSTATISTIC_H 13 | #define TRANSTATISTIC_H 14 | 15 | //TranStatistic.h 16 | 17 | #include //vector 18 | #include //ostream 19 | #include //uint64_t 20 | 21 | #include "ConfigValue.h" 22 | 23 | using namespace std; 24 | 25 | namespace CasHMC 26 | { 27 | 28 | class TranStatistic 29 | { 30 | public: 31 | TranStatistic() { 32 | readPerLink = vector(1, 0); 33 | writePerLink = vector(1, 0); 34 | atomicPerLink = vector(1, 0); 35 | reqPerLink = vector(1, 0); 36 | resPerLink = vector(1, 0); 37 | flowPerLink = vector(1, 0); 38 | errorPerLink = vector(1, 0); 39 | retryFailPerLink = vector(1, 0); 40 | 41 | hmcTransmitSize = 0; 42 | downLinkTransmitSize = vector(1, 0); 43 | upLinkTransmitSize = vector(1, 0); 44 | downLinkDataSize = vector(1, 0); 45 | upLinkDataSize = vector(1, 0); 46 | 47 | tranFullSum = 0; linkFullSum = 0; vaultFullSum = 0; errorRetrySum = 0; 48 | totalTranCount = 0; totalErrorCount = 0; 49 | totalTranFullSum = 0; totalLinkFullSum = 0; totalVaultFullSum = 0; totalErrorRetrySum = 0; 50 | 51 | totalReadPerLink = vector(1, 0); 52 | totalWritePerLink = vector(1, 0); 53 | totalAtomicPerLink = vector(1, 0); 54 | totalReqPerLink = vector(1, 0); 55 | totalResPerLink = vector(1, 0); 56 | totalFlowPerLink = vector(1, 0); 57 | totalErrorPerLink = vector(1, 0); 58 | 59 | totalTranFullMax = 0; totalTranFullMin = -1; 60 | totalLinkFullMax = 0; totalLinkFullMin = -1; 61 | totalVaultFullMax = 0; totalVaultFullMin = -1; 62 | totalErrorRetryMax = 0; totalErrorRetryMin = -1; 63 | totalTranStdSum = 0; totalLinkStdSum = 0; totalVaultStdSum = 0; totalErrorStdSum = 0; 64 | 65 | totalHmcTransmitSize = 0; 66 | totalDownLinkTransmitSize = vector(1, 0); 67 | totalUpLinkTransmitSize = vector(1, 0); 68 | totalDownLinkDataSize = vector(1, 0); 69 | totalUpLinkDataSize = vector(1, 0); 70 | } 71 | virtual ~TranStatistic() { 72 | tranFullLat.clear(); 73 | linkFullLat.clear(); 74 | vaultFullLat.clear(); 75 | errorRetryLat.clear(); 76 | } 77 | void PushStatisPerLink() { 78 | for(int i=0; i tranFullLat; 119 | vector linkFullLat; 120 | vector vaultFullLat; 121 | vector errorRetryLat; 122 | 123 | vector readPerLink; 124 | vector writePerLink; 125 | vector atomicPerLink; 126 | vector reqPerLink; 127 | vector resPerLink; 128 | vector flowPerLink; 129 | vector errorPerLink; 130 | vector retryFailPerLink; 131 | 132 | uint64_t hmcTransmitSize; //[Byte] 133 | vector downLinkTransmitSize; //[Byte] 134 | vector upLinkTransmitSize; //[Byte] 135 | vector downLinkDataSize; //[Byte] 136 | vector upLinkDataSize; //[Byte] 137 | 138 | uint64_t tranFullSum; 139 | uint64_t linkFullSum; 140 | uint64_t vaultFullSum; 141 | uint64_t errorRetrySum; 142 | 143 | //Accumulate statistics 144 | uint64_t totalTranCount; 145 | uint64_t totalErrorCount; 146 | uint64_t totalTranFullSum; 147 | uint64_t totalLinkFullSum; 148 | uint64_t totalVaultFullSum; 149 | uint64_t totalErrorRetrySum; 150 | 151 | vector totalReadPerLink; 152 | vector totalWritePerLink; 153 | vector totalAtomicPerLink; 154 | vector totalReqPerLink; 155 | vector totalResPerLink; 156 | vector totalFlowPerLink; 157 | vector totalErrorPerLink; 158 | 159 | unsigned totalTranFullMax; 160 | unsigned totalTranFullMin; 161 | unsigned totalLinkFullMax; 162 | unsigned totalLinkFullMin; 163 | unsigned totalVaultFullMax; 164 | unsigned totalVaultFullMin; 165 | unsigned totalErrorRetryMax; 166 | unsigned totalErrorRetryMin; 167 | 168 | double totalTranStdSum; 169 | double totalLinkStdSum; 170 | double totalVaultStdSum; 171 | double totalErrorStdSum; 172 | 173 | uint64_t totalHmcTransmitSize; 174 | vector totalDownLinkTransmitSize; 175 | vector totalUpLinkTransmitSize; 176 | vector totalDownLinkDataSize; 177 | vector totalUpLinkDataSize; 178 | }; 179 | 180 | } 181 | 182 | #endif -------------------------------------------------------------------------------- /sources/TranTrace.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef TRANTRACE_H 13 | #define TRANTRACE_H 14 | 15 | //TranTrace.h 16 | 17 | #include //uint64_t 18 | 19 | #include "TranStatistic.h" 20 | 21 | using namespace std; 22 | 23 | namespace CasHMC 24 | { 25 | 26 | class TranTrace 27 | { 28 | public: 29 | TranTrace(TranStatistic *sta):statis(sta) { 30 | tranTransmitTime = 0; 31 | tranFullLat = 0; 32 | linkTransmitTime = 0; 33 | linkFullLat = 0; 34 | vaultIssueTime = 0; 35 | vaultFullLat = 0; 36 | } 37 | ~TranTrace() { 38 | if(tranFullLat==0 || linkFullLat==0 || vaultFullLat==0) { 39 | ERROR(" (Trace) == Error - Full latency is '0' (tranFullLat : "<UpdateStatis(tranFullLat, linkFullLat, vaultFullLat); 45 | } 46 | } 47 | 48 | //Identifier 49 | TranStatistic *statis; 50 | 51 | //Trace latency info 52 | unsigned tranTransmitTime; //[CPU clock] Time to send transaction to HMC controller from bus 53 | unsigned tranFullLat; //[CPU clock] Total latency time flowing transaction 54 | 55 | unsigned linkTransmitTime; //[CPU clock] Time to send request packet through link 56 | unsigned linkFullLat; //[CPU clock] Total latency time from sending request to returning response packet through link 57 | 58 | unsigned vaultIssueTime; //[DRAM clock (tCK)] Time to issue ACTIVATE command corresponding to this transaction 59 | unsigned vaultFullLat; //[DRAM clock (tCK)] Total latency time from issue ACTIVATE command to return data 60 | }; 61 | 62 | } 63 | 64 | #endif -------------------------------------------------------------------------------- /sources/Transaction.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #include "Transaction.h" 13 | 14 | using namespace std; 15 | 16 | extern unsigned tranGlobalID; 17 | 18 | namespace CasHMC 19 | { 20 | 21 | Transaction::Transaction(TransactionType tranType, uint64_t addr, unsigned size, TranStatistic *statis): 22 | transactionType(tranType), 23 | address(addr), 24 | dataSize(size) 25 | { 26 | LNG = 1; 27 | transactionID = tranGlobalID++; 28 | trace = new TranTrace(statis); 29 | } 30 | 31 | Transaction::~Transaction() 32 | { 33 | } 34 | 35 | // 36 | //Reduction tranGlobalID 37 | // 38 | void Transaction::ReductGlobalID() 39 | { 40 | tranGlobalID--; 41 | } 42 | 43 | // 44 | //Defines "<<" operation for printing 45 | // 46 | ostream& operator<<(ostream &out, const Transaction &t) 47 | { 48 | string header; 49 | stringstream id; 50 | id << t.transactionID; 51 | 52 | switch(t.transactionType) { 53 | case DATA_READ: header = "[T" + id.str() + "-Read]"; break; 54 | case DATA_WRITE: header = "[T" + id.str() + "-Write]"; break; 55 | case RETURN_DATA: header = "[T" + id.str() + "-Data]"; break; 56 | //ATOMICS commands for HMC 57 | case ATM_2ADD8: header = "[T" + id.str() + "-2ADD8]"; break; case ATM_ADD16: header = "[T" + id.str() + "-ADD16]"; break; 58 | case ATM_P_2ADD8: header = "[T" + id.str() + "-P_2ADD8]"; break; case ATM_P_ADD16: header = "[T" + id.str() + "-P_ADD16]"; break; 59 | case ATM_2ADDS8R: header = "[T" + id.str() + "-2ADDS8R]"; break; case ATM_ADDS16R: header = "[T" + id.str() + "-ADDS16R]"; break; 60 | case ATM_INC8: header = "[T" + id.str() + "-INC8]"; break; case ATM_P_INC8: header = "[T" + id.str() + "-P_INC8]"; break; 61 | case ATM_XOR16: header = "[T" + id.str() + "-XOR16]"; break; case ATM_OR16: header = "[T" + id.str() + "-OR16]"; break; 62 | case ATM_NOR16: header = "[T" + id.str() + "-NOR16]"; break; case ATM_AND16: header = "[T" + id.str() + "-AND16]"; break; 63 | case ATM_NAND16: header = "[T" + id.str() + "-NAND16]"; break; case ATM_CASGT8: header = "[T" + id.str() + "-CASGT8]"; break; 64 | case ATM_CASLT8: header = "[T" + id.str() + "-CASLT8]"; break; case ATM_CASGT16: header = "[T" + id.str() + "-CASGT16]"; break; 65 | case ATM_CASLT16: header = "[T" + id.str() + "-CASLT16]"; break; case ATM_CASEQ8: header = "[T" + id.str() + "-CASEQ8]"; break; 66 | case ATM_CASZERO16: header = "[T" + id.str() + "-CASZR16]"; break; case ATM_EQ16: header = "[T" + id.str() + "-EQ16]"; break; 67 | case ATM_EQ8: header = "[T" + id.str() + "-EQ8]"; break; case ATM_BWR: header = "[T" + id.str() + "-BWR]"; break; 68 | case ATM_P_BWR: header = "[T" + id.str() + "-P_BWR]"; break; case ATM_BWR8R: header = "[T" + id.str() + "-BWR8R]"; break; 69 | case ATM_SWAP16: header = "[T" + id.str() + "-SWAP16]"; break; 70 | default: 71 | ERROR(" (TS) == Error - Trying to print unknown kind of transaction type"); 72 | ERROR(" T"< //uint64_t 18 | #include //exit(0) 19 | #include //setw() 20 | #include //ostream 21 | #include //stringstream 22 | 23 | #include "ConfigValue.h" 24 | #include "TranTrace.h" 25 | #include "TranStatistic.h" 26 | 27 | using namespace std; 28 | 29 | namespace CasHMC 30 | { 31 | 32 | enum TransactionType 33 | { 34 | DATA_READ, 35 | DATA_WRITE, 36 | RETURN_DATA, 37 | //ATOMICS commands for HMC 38 | ATM_2ADD8, ATM_ADD16, ATM_P_2ADD8, ATM_P_ADD16, ATM_2ADDS8R, ATM_ADDS16R, ATM_INC8, ATM_P_INC8, //ARITHMETIC ATOMICS 39 | ATM_XOR16, ATM_OR16, ATM_NOR16, ATM_AND16, ATM_NAND16, //BOOLEAN ATOMICS 40 | ATM_CASGT8, ATM_CASLT8, ATM_CASGT16, ATM_CASLT16, ATM_CASEQ8, ATM_CASZERO16, ATM_EQ16, ATM_EQ8, //COMPARISON ATOMICS 41 | ATM_BWR, ATM_P_BWR, ATM_BWR8R, ATM_SWAP16 //BITWISE ATOMICS 42 | }; 43 | 44 | class Transaction 45 | { 46 | public: 47 | // 48 | //Functions 49 | // 50 | Transaction(TransactionType tranType, uint64_t addr, unsigned size, TranStatistic *statis); 51 | virtual ~Transaction(); 52 | void ReductGlobalID(); 53 | 54 | // 55 | //Fields 56 | // 57 | TranTrace *trace; 58 | TransactionType transactionType; //Type of transaction (defined above) 59 | uint64_t address; //Physical address of request 60 | unsigned dataSize; //[byte] Size of data 61 | unsigned transactionID; //Unique identifier 62 | unsigned LNG; 63 | }; 64 | 65 | ostream& operator<<(ostream &out, const Transaction &t); 66 | } 67 | 68 | #endif -------------------------------------------------------------------------------- /sources/VaultController.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************* 2 | * CasHMC v1.3 - 2017.07.10 3 | * A Cycle-accurate Simulator for Hybrid Memory Cube 4 | * 5 | * Copyright 2016, Dong-Ik Jeon 6 | * Ki-Seok Chung 7 | * Hanyang University 8 | * estwings57 [at] gmail [dot] com 9 | * All rights reserved. 10 | *********************************************************************************/ 11 | 12 | #ifndef VAULTCONTROLLER_H 13 | #define VAULTCONTROLLER_H 14 | 15 | //VaultController.h 16 | 17 | #include //uint64_t 18 | #include //vector 19 | #include //ceil() 20 | 21 | #include "DualVectorObject.h" 22 | #include "ConfigValue.h" 23 | #include "DRAMCommand.h" 24 | #include "CommandQueue.h" 25 | #include "DRAM.h" 26 | using namespace std; 27 | 28 | namespace CasHMC 29 | { 30 | 31 | class VaultController : public DualVectorObject 32 | { 33 | public: 34 | // 35 | //Functions 36 | // 37 | VaultController(ofstream &debugOut_, ofstream &stateOut_, unsigned id); 38 | virtual ~VaultController(); 39 | void CallbackReceiveDown(Packet *packet, bool chkReceive); 40 | void CallbackReceiveUp(Packet *packet, bool chkReceive); 41 | void ReturnCommand(DRAMCommand *retRead); 42 | void MakeRespondPacket(DRAMCommand *retCMD); 43 | void Update(); 44 | void UpdateCountdown(); 45 | bool ConvPacketIntoCMDs(Packet *packet); 46 | void AddressMapping(uint64_t physicalAddress, unsigned &bankAdd, unsigned &colAdd, unsigned &rowAdd); 47 | void ReverseAddressMapping(uint64_t &physicalAddress, unsigned bankAdd, unsigned colAdd, unsigned rowAdd); 48 | void EnablePowerdown(); 49 | void PrintState(); 50 | 51 | // 52 | //Fields 53 | // 54 | unsigned vaultContID; 55 | unsigned refreshCountdown; 56 | bool powerDown; 57 | 58 | DRAM *dramP; 59 | CommandQueue *commandQueue; 60 | DRAMCommand *poppedCMD; 61 | DRAMCommand *atomicCMD; 62 | unsigned atomicOperLeft; 63 | unsigned pendingDataSize; 64 | vector pendingReadData; //Store Read packet TAG for return data 65 | DualVectorObject *upBufferDest; 66 | 67 | //Command and data to be transmitted to DRAM I/O 68 | DRAMCommand *cmdBus; 69 | unsigned cmdCyclesLeft; 70 | DRAMCommand *dataBus; 71 | unsigned dataCyclesLeft; 72 | vector writeDataToSend; 73 | vector writeDataCountdown; 74 | }; 75 | 76 | } 77 | 78 | #endif -------------------------------------------------------------------------------- /trace/trace.trc: -------------------------------------------------------------------------------- 1 | 20 0x120086c0 READ 2 | 210 0x120086c0 READ 3 | 215 0x120126c0 READ 4 | 218 0x120146c0 READ 5 | 220 0x120123c0 READ 6 | 225 0x120233c0 READ 7 | 228 0x120243c0 READ 8 | 230 0x12004560 READ 9 | 235 0x12004480 READ 10 | 238 0x12004480 READ 11 | 240 0x120678c0 READ 12 | 245 0x120626c0 READ 13 | 248 0x120624c0 READ 14 | 250 0x12008900 READ 15 | 255 0x12008230 READ 16 | 258 0x12008430 READ 17 | 260 0x124567c0 READ 18 | 265 0x124267c0 READ 19 | 268 0x124247c0 READ 20 | 270 0x120678c0 READ 21 | 275 0x120478c0 READ 22 | 278 0x120474c0 READ 23 | 280 0x12007890 READ 24 | 285 0x12002490 READ 25 | 288 0x12002440 READ 26 | -------------------------------------------------------------------------------- /trace/trace_generator/Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS=-O3 -g -DDEBUG_LOG 2 | EXE_NAME=TraceGen 3 | 4 | SRC = $(wildcard *.cpp) 5 | 6 | OBJ = $(subst LibraryStubs.o,,$(addsuffix .o, $(basename $(SRC)))) 7 | 8 | REBUILDABLES=$(OBJ) $(EXE_NAME) 9 | 10 | all: ${EXE_NAME} 11 | 12 | # $@ target name, $^ target deps, $< matched pattern 13 | $(EXE_NAME): $(OBJ) 14 | $(CXX) $(LINK_FLAGS) -o $@ $^ 15 | @echo "Built $@ successfully" 16 | 17 | #include the autogenerated dependency files for each .o file 18 | -include $(OBJ:.o=.dep) 19 | 20 | # build dependency list via gcc -M and save to a .dep file 21 | %.dep : %.cpp 22 | @$(CXX) -M $(CXXFLAGS) $< > $@ 23 | 24 | # build all .cpp files to .o files 25 | %.o : %.cpp 26 | g++ $(CXXFLAGS) -o $@ -c $< 27 | 28 | clean: 29 | -rm -f ${REBUILDABLES} *.dep 30 | -------------------------------------------------------------------------------- /trace/trace_generator/TraceGen.cpp: -------------------------------------------------------------------------------- 1 | #include //getopt_long 2 | #include //uint64_t 3 | #include //exit(0) 4 | #include //ofstream 5 | #include //cout 6 | #include //ofstream 7 | #include //stringstream 8 | #include //setw 9 | #include //access() 10 | 11 | using namespace std; 12 | 13 | ofstream traceOut; 14 | long numSimCycles = 100000; 15 | uint64_t lineNumber = 1; 16 | double memUtil = 0.1; 17 | double rwRatio = 80; 18 | int dataSize = 32; 19 | 20 | void help() 21 | { 22 | cout< 1) { 72 | cout< 100) { 80 | cout<