diff --git a/DRAMSys/DRAMSys.pro b/DRAMSys/DRAMSys.pro index 71f57bdc..0852d9e4 100644 --- a/DRAMSys/DRAMSys.pro +++ b/DRAMSys/DRAMSys.pro @@ -1,8 +1,7 @@ TEMPLATE = subdirs thermalsim = $$(THERMALSIM) -isEmpty(thermalsim) -{ +isEmpty(thermalsim) { thermalsim = false } @@ -16,6 +15,19 @@ SUBDIRS += simulator/library.pro SUBDIRS += simulator/simulator.pro SUBDIRS += analyzer/traceAnalyzer.pro + +# Check if gem5 is installed: +gem5 = $$(GEM5) +isEmpty(gem5) { + message(GEM5 environment variable not found) + message(Gem5 Simulation Disabled) +} else { + message(Gem5 Simulation Feature Enabled) + message(Gem5 home is $${gem5}) + DEFINES += DRAMSYS_GEM5 + SUBDIRS += gem5/gem5.pro +} + # Build Sub Projects in the order given above CONFIG += ordered diff --git a/DRAMSys/analyzer/scripts/scripts.pri b/DRAMSys/analyzer/scripts/scripts.pri index 2e78599c..2e99f781 100644 --- a/DRAMSys/analyzer/scripts/scripts.pri +++ b/DRAMSys/analyzer/scripts/scripts.pri @@ -5,4 +5,5 @@ OTHER_FILES += scripts/memUtil.py OTHER_FILES += scripts/metrics.py OTHER_FILES += scripts/tests.py OTHER_FILES += scripts/plots.py +OTHER_FILES += scripts/sonification.pl diff --git a/DRAMSys/analyzer/scripts/sonification.pl b/DRAMSys/analyzer/scripts/sonification.pl new file mode 100644 index 00000000..75f5d615 --- /dev/null +++ b/DRAMSys/analyzer/scripts/sonification.pl @@ -0,0 +1,84 @@ +#!/bin/perl -w +use MIDI; # ...which "use"s MIDI::Track et al +use DBI; +use Data::Dumper; +use warnings; +use strict; + +my $dbfile = shift || die("No File"); +my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile","",""); + + +# Get time: +my $sth = $dbh->prepare("SELECT clk FROM GeneralInfo"); +$sth->execute(); +my $result = $sth->fetch; +my $timebase = $result->[0]; + +$sth = $dbh->prepare("SELECT p.PhaseName, p.PhaseBegin, p.PhaseEnd, t.TBank + FROM Phases p, Transactions t + WHERE (p.PhaseName = 'WR' OR p.PhaseName = 'RD') + AND p.Transact = t.ID + ORDER BY PhaseBegin"); +$sth->execute(); + +my @score; + +push(\@score, ['text_event', 0, 'Sonification']); +push(\@score, ['patch_change', 0, 1, 8]); +push(\@score, ['instrument_name', 0, 81]); + +while(my @row = $sth->fetchrow_array) +{ + #print $row[0]."\t".$row[1]."\t".$row[2]."\t".$row[3]."\n"; + # ('note', starttime, duration, channel, note, velocity) + my $note; + if($row[3] == 0) + { + $note = 72; #C + } + elsif($row[3] == 1) + { + $note = 75; #Eb + } + elsif($row[3] == 2) + { + $note = 76; #E + } + elsif($row[3] == 3) + { + $note = 77; #F + } + elsif($row[3] == 4) + { + $note = 78; #Gb + } + elsif($row[3] == 5) + { + $note = 79; #G + } + elsif($row[3] == 6) + { + $note = 82; #Bb + } + elsif($row[3] == 7) + { + $note = 84; #C + } + push(\@score, ['note', $row[1]/$timebase, 1, 1, $note, 96]); +} + +#print Dumper(\@score); + +#MIDI::Score::dump_score( \@score ); + +my $track = MIDI::Track->new; +my @events = @{MIDI::Score::score_r_to_events_r( \@score )}; + +$track->events(@events); +#$track->dump(); + +my $opus = MIDI::Opus->new({ 'format' => 0, 'ticks' => 240, 'tracks' => [ $track ] }); +$opus->write_to_file('cowbell.mid'); + + diff --git a/DRAMSys/gem5/gem5.pro b/DRAMSys/gem5/gem5.pro new file mode 100644 index 00000000..cb3dcc2d --- /dev/null +++ b/DRAMSys/gem5/gem5.pro @@ -0,0 +1,75 @@ +TARGET = DRAMSys_gem5 +TEMPLATE = app +CONFIG += console +CONFIG -= app_bundle +CONFIG -= qt + +# gem5 parameters: +gem5_arch = 'ARM' +gem5_variant = 'opt' +gem5_root = $$(GEM5) + +systemc_home = $$(SYSTEMC_HOME) +isEmpty(systemc_home) { + systemc_home = /opt/systemc +} +message(SystemC home is $${systemc_home}) + +systemc_target_arch = $$(SYSTEMC_TARGET_ARCH) +isEmpty(systemc_target_arch) { + systemc_target_arch = linux64 +} + +message(SystemC target architecture is $${systemc_target_arch}) + +unix:!macx { + message(Building on a GNU/Linux) + QMAKE_RPATHDIR += $${systemc_home}/lib-$${systemc_target_arch} + message(Linker options QMAKE_RPATHDIR is $${QMAKE_RPATHDIR}) +} + +DEFINES += TIXML_USE_STL +DEFINES += SC_INCLUDE_DYNAMIC_PROCESSES +DEFINES += DRAMSYS_GEM5 + +unix:!macx { + QMAKE_CXXFLAGS += -std=c++11 -O0 -g +} + +macx: { + CONFIG += c++11 + QMAKE_CXXFLAGS += -std=c++0x -stdlib=libc++ -O0 -g +} + +INCLUDEPATH += ../simulator/src/simulation/ +INCLUDEPATH += $${systemc_home}/include +INCLUDEPATH += ../simulator/src/common/third_party/DRAMPower/src +INCLUDEPATH += ../simulator/src/common/third_party/DRAMPower/src/libdrampower +INCLUDEPATH += $${gem5_root}/build/$${gem5_arch}/ +INCLUDEPATH += $${gem5_root}/util/tlm/examples/slave_port +INCLUDEPATH += $${gem5_root}/util/tlm/examples/common +INCLUDEPATH += $${gem5_root}/util/tlm/ +INCLUDEPATH += $${gem5_root}/util/systemc + +LIBS += -L$${systemc_home}/lib-$${systemc_target_arch} -lsystemc +LIBS += ../simulator/libDRAMSys.a +LIBS += ../../DRAMSys/simulator/src/common/third_party/DRAMPower/src/libdrampower.a +LIBS += -lsqlite3 +LIBS += -L$${gem5_root}/build/$${gem5_arch} -lgem5_$${gem5_variant} + +SOURCES += $${gem5_root}/util/systemc/sc_gem5_control.cc +SOURCES += $${gem5_root}/util/systemc/sc_logger.cc +SOURCES += $${gem5_root}/util/systemc/sc_module.cc +SOURCES += $${gem5_root}/util/systemc/stats.cc +SOURCES += $${gem5_root}/util/tlm/examples/common/cli_parser.cc +SOURCES += $${gem5_root}/util/tlm/examples/common/report_handler.cc +SOURCES += $${gem5_root}/util/tlm/master_transactor.cc +SOURCES += $${gem5_root}/util/tlm/sc_master_port.cc +SOURCES += $${gem5_root}/util/tlm/sc_slave_port.cc +SOURCES += $${gem5_root}/util/tlm/slave_transactor.cc +SOURCES += $${gem5_root}/util/tlm/sc_ext.cc +SOURCES += $${gem5_root}/util/tlm/sc_mm.cc +SOURCES += $${gem5_root}/util/tlm/sim_control.cc + +SOURCES += main.cpp + diff --git a/DRAMSys/gem5/main.cpp b/DRAMSys/gem5/main.cpp new file mode 100644 index 00000000..a7dc0d21 --- /dev/null +++ b/DRAMSys/gem5/main.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2015, University of Kaiserslautern + * Copyright (c) 2016, Dresden University of Technology (TU Dresden) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Matthias Jung + * Christian Menard + * Abdul Mutaal Ahmad + */ + +#include +#include +#include +#include + +#include "DRAMSys.h" +#include "TraceSetup.h" + +#include "report_handler.hh" +#include "sc_target.hh" +#include "sim_control.hh" +#include "slave_transactor.hh" +#include "stats.hh" + +using namespace std; + +class Gem5SimControlDRAMsys: public Gem5SystemC::Gem5SimControl +{ +public: + Gem5SimControlDRAMsys(string configFile) : + Gem5SystemC::Gem5SimControl("gem5",configFile,0,"") + { + } + + void afterSimulate() + { + sc_stop(); + } +}; + +string pathOfFile(string file) +{ + return file.substr(0, file.find_last_of('/')); +} + +int sc_main(int argc, char **argv) +{ + SC_REPORT_INFO("sc_main", "Simulation Setup"); + + string SimulationXML; + string gem5ConfigFile; + string resources; + + if(argc > 1) + { + // Get path of resources: + resources = pathOfFile(argv[0]) + + string("/../../DRAMSys/simulator/resources/"); + + SimulationXML = argv[1]; + gem5ConfigFile = argv[2]; + } + else + { + SC_REPORT_FATAL("sc_main","Please provide configuration files"); + } + + // Instantiate DRAMSys: + DRAMSys dramSys("DRAMSys", SimulationXML, resources); + + // Instantiate gem5: + Gem5SimControlDRAMsys sim_control(gem5ConfigFile); + Gem5SystemC::Gem5SlaveTransactor transactor("transactor", "transactor"); + + transactor.socket.bind(dramSys.tSocket); + transactor.sim_control.bind(sim_control); + + SC_REPORT_INFO("sc_main", "Start of Simulation"); + + sc_core::sc_set_stop_mode(SC_STOP_FINISH_DELTA); + sc_core::sc_start(); + + if (!sc_core::sc_end_of_simulation_invoked()) + { + SC_REPORT_INFO("sc_main","Simulation stopped without explicit sc_stop()"); + sc_core::sc_stop(); + } + + SC_REPORT_INFO("sc_main", "End of Simulation"); + + return EXIT_SUCCESS; +} diff --git a/DRAMSys/simulator/library.pro b/DRAMSys/simulator/library.pro index 5a25d3ff..8a17d847 100644 --- a/DRAMSys/simulator/library.pro +++ b/DRAMSys/simulator/library.pro @@ -28,6 +28,17 @@ $$eval(dramsys_pct) { DEFINES += DRAMSYS_PCT } +# Check if gem5 should be used +gem5 = $$(GEM5) +isEmpty(gem5) { + message(GEM5 environment variable not found) + message(Gem5 Simulation Disabled) +} else { + message(Gem5 Simulation Feature Enabled) + message(Gem5 home is $${gem5}) + DEFINES += DRAMSYS_GEM5 +} + message(SystemC home is $${systemc_home}) systemc_target_arch = $$(SYSTEMC_TARGET_ARCH) @@ -100,7 +111,10 @@ SOURCES += \ src/controller/core/powerdown/PowerDownManagerTimeoutBankwise.cpp \ src/simulation/TraceSetup.cpp \ src/simulation/DRAMSys.cpp \ - src/simulation/Setup.cpp + src/simulation/Setup.cpp \ + src/error/ECC/Bit.cpp \ + src/error/ECC/ECC.cpp \ + src/error/ECC/Word.cpp HEADERS += \ src/common/third_party/tinyxml2/tinyxml2.h \ @@ -164,7 +178,10 @@ HEADERS += \ src/simulation/TraceSetup.h \ src/simulation/DRAMSys.h \ src/simulation/Setup.h \ - src/error/controllerECC.h + src/error/controllerECC.h \ + src/error/ECC/Bit.h \ + src/error/ECC/ECC.h \ + src/error/ECC/Word.h thermalsim = $$(THERMALSIM) isEmpty(thermalsim) { diff --git a/DRAMSys/simulator/resources/configs/memspecs/MICRON_1Gb_DDR3-1600_8bit_G_less_refresh.xml b/DRAMSys/simulator/resources/configs/memspecs/MICRON_1Gb_DDR3-1600_8bit_G_less_refresh.xml new file mode 100644 index 00000000..7a94a932 --- /dev/null +++ b/DRAMSys/simulator/resources/configs/memspecs/MICRON_1Gb_DDR3-1600_8bit_G_less_refresh.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/simulator/resources/configs/memspecs/wideio.xml b/DRAMSys/simulator/resources/configs/memspecs/wideio.xml index 3ab07172..fbe252d6 100644 --- a/DRAMSys/simulator/resources/configs/memspecs/wideio.xml +++ b/DRAMSys/simulator/resources/configs/memspecs/wideio.xml @@ -24,7 +24,7 @@ - + diff --git a/DRAMSys/simulator/resources/configs/simulator/ddr3-single-device.xml b/DRAMSys/simulator/resources/configs/simulator/ddr3-single-device.xml index 3dec948e..35fd3dec 100644 --- a/DRAMSys/simulator/resources/configs/simulator/ddr3-single-device.xml +++ b/DRAMSys/simulator/resources/configs/simulator/ddr3-single-device.xml @@ -10,4 +10,5 @@ + diff --git a/DRAMSys/simulator/resources/configs/simulator/ddr3.xml b/DRAMSys/simulator/resources/configs/simulator/ddr3.xml index d13a4acc..9e322605 100644 --- a/DRAMSys/simulator/resources/configs/simulator/ddr3.xml +++ b/DRAMSys/simulator/resources/configs/simulator/ddr3.xml @@ -10,4 +10,10 @@ + + diff --git a/DRAMSys/simulator/resources/configs/simulator/ddr3_ecc.xml b/DRAMSys/simulator/resources/configs/simulator/ddr3_ecc.xml new file mode 100644 index 00000000..f1f7bcf8 --- /dev/null +++ b/DRAMSys/simulator/resources/configs/simulator/ddr3_ecc.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + diff --git a/DRAMSys/simulator/resources/configs/simulator/wideio.xml b/DRAMSys/simulator/resources/configs/simulator/wideio.xml index c811e71a..8ba8f3ba 100644 --- a/DRAMSys/simulator/resources/configs/simulator/wideio.xml +++ b/DRAMSys/simulator/resources/configs/simulator/wideio.xml @@ -7,7 +7,7 @@ - + diff --git a/DRAMSys/simulator/resources/simulations/ddr3-ecc.xml b/DRAMSys/simulator/resources/simulations/ddr3-ecc.xml new file mode 100644 index 00000000..5760612c --- /dev/null +++ b/DRAMSys/simulator/resources/simulations/ddr3-ecc.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + test_ecc.stl + + diff --git a/DRAMSys/simulator/resources/simulations/wideio-example.xml b/DRAMSys/simulator/resources/simulations/wideio-example.xml index 8c068c25..c0847e17 100644 --- a/DRAMSys/simulator/resources/simulations/wideio-example.xml +++ b/DRAMSys/simulator/resources/simulations/wideio-example.xml @@ -4,7 +4,7 @@ - + diff --git a/DRAMSys/simulator/src/controller/core/ControllerCore.cpp b/DRAMSys/simulator/src/controller/core/ControllerCore.cpp index d8650e70..45b3bd47 100644 --- a/DRAMSys/simulator/src/controller/core/ControllerCore.cpp +++ b/DRAMSys/simulator/src/controller/core/ControllerCore.cpp @@ -160,11 +160,16 @@ void ControllerCore::scheduleRequest(Command command, tlm::tlm_generic_payload & sc_time start = clkAlign(sc_time_stamp()); state->cleanUp(start); ScheduledCommand scheduledCommand = schedule(command, start, payload); - if(!((command == Command::Precharge || command == Command::Activate) - && refreshManager->hasCollision(scheduledCommand))) - { + if (config.ControllerCoreDisableRefresh == true) { state->change(scheduledCommand); controller.send(scheduledCommand, payload); + } else { + if(!((command == Command::Precharge || command == Command::Activate) + && refreshManager->hasCollision(scheduledCommand))) + { + state->change(scheduledCommand); + controller.send(scheduledCommand, payload); + } } } diff --git a/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp b/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp index 85f0a250..3598217b 100644 --- a/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp +++ b/DRAMSys/simulator/src/controller/core/configuration/Configuration.cpp @@ -73,6 +73,11 @@ int string2int(string s) return std::stoi(s); } +unsigned long long string2ull(string s) +{ + return std::stoull(s); +} + StorageMode string2StoreMode(string s) { if(s == "NoStorage") @@ -185,6 +190,15 @@ void Configuration::setParameter(std::string name, std::string value) SC_REPORT_FATAL("Configuration", ("Invalid value for parameter " + name + ". This parameter must be at least one.").c_str()); } else NumberOfDevicesOnDIMM = string2int(value); + else if(name == "AddressOffset") + { +#ifdef DRAMSYS_GEM5 + AddressOffset = string2ull(value); +#else + AddressOffset = 0; +#endif + cout << "Address Offset: " << AddressOffset << endl; + } else if(name == "CheckTLM2Protocol") CheckTLM2Protocol = string2bool(value); else if(name == "EnableControllerECC") diff --git a/DRAMSys/simulator/src/controller/core/configuration/Configuration.h b/DRAMSys/simulator/src/controller/core/configuration/Configuration.h index bff51af5..1e5326c9 100644 --- a/DRAMSys/simulator/src/controller/core/configuration/Configuration.h +++ b/DRAMSys/simulator/src/controller/core/configuration/Configuration.h @@ -82,6 +82,8 @@ struct Configuration unsigned int NumberOfDevicesOnDIMM = 1; bool CheckTLM2Protocol = false; bool EnableControllerECC = false; + bool gem5 = false; + unsigned long long int AddressOffset = 0; // MemSpec (from DRAM-Power XML) MemSpec memSpec; diff --git a/DRAMSys/simulator/src/error/ECC/Bit.cpp b/DRAMSys/simulator/src/error/ECC/Bit.cpp index b5faee9a..55f28ebf 100644 --- a/DRAMSys/simulator/src/error/ECC/Bit.cpp +++ b/DRAMSys/simulator/src/error/ECC/Bit.cpp @@ -1,6 +1,8 @@ -#include "stdafx.h" #include "Bit.h" +#include + +using std::cout; CBit::CBit(VALUE nVal) { @@ -16,10 +18,10 @@ void CBit::Print() { if (m_nValue == ZERO) { - printf("0"); + cout <<"0"; } else { - printf("1"); + cout << "1"; } } diff --git a/DRAMSys/simulator/src/error/ECC/Bit.h b/DRAMSys/simulator/src/error/ECC/Bit.h index 74aec5da..bfdda476 100644 --- a/DRAMSys/simulator/src/error/ECC/Bit.h +++ b/DRAMSys/simulator/src/error/ECC/Bit.h @@ -17,10 +17,17 @@ public: inline void Set() { m_nValue = ONE; }; inline void Clear() { m_nValue = ZERO; }; + inline unsigned Get() + { + if(m_nValue == ONE) + return 1; + else + return 0; + }; void Print(); - CBit& operator=(DWORD d) + CBit& operator=(unsigned d) { if (d == 0 ) { diff --git a/DRAMSys/simulator/src/error/ECC/ECC.cpp b/DRAMSys/simulator/src/error/ECC/ECC.cpp index bbd230ba..b8e15743 100644 --- a/DRAMSys/simulator/src/error/ECC/ECC.cpp +++ b/DRAMSys/simulator/src/error/ECC/ECC.cpp @@ -1,5 +1,3 @@ -#include "stdafx.h" - #include "ECC.h" unsigned ECC::GetNumParityBits(unsigned nDataBits) @@ -31,14 +29,20 @@ void ECC::ExtendWord(CWord & v) void ECC::CalculateCheckbits(CWord & v, CWord & p) { - // Hamming-Code Prüfbits füllen + // Hamming-Code Prüfbits füllen unsigned i = 1, l = 0; - while (i < v.GetLength()) + + // Last bit is the parity bit - don't use this in the algorithm for hamming code + unsigned len = v.GetLength()-1; + + while (i < len) { - for (unsigned j = (i - 1); j < v.GetLength(); j += (i << 1)) + for (unsigned j = (i - 1); j < len; j += (i << 1)) { for (unsigned k = 0; k < (i); k++) { + if(j + k >= len) + break; p[l] ^= v[j + k]; } } @@ -49,9 +53,9 @@ void ECC::CalculateCheckbits(CWord & v, CWord & p) void ECC::InsertCheckbits(CWord& v, CWord p) { - // Prüfbits einfügen + // Prüfbits einfügen unsigned i = 1, j = 0; - while (i <= v.GetLength()) + while (i <= v.GetLength()-1) { v[i - 1] = p[j++]; i <<= 1; @@ -61,9 +65,9 @@ void ECC::InsertCheckbits(CWord& v, CWord p) void ECC::ExtractCheckbits(CWord v, CWord & p) { - // Prüfbits extrahieren + // Prüfbits extrahieren unsigned i = 1, j = 0; - while(i <= v.GetLength()) + while(i <= v.GetLength()-1) { p[j++] = v[i - 1]; i <<= 1; diff --git a/DRAMSys/simulator/src/error/ECC/Word.cpp b/DRAMSys/simulator/src/error/ECC/Word.cpp index a94bdad7..f260d76c 100644 --- a/DRAMSys/simulator/src/error/ECC/Word.cpp +++ b/DRAMSys/simulator/src/error/ECC/Word.cpp @@ -1,6 +1,8 @@ -#include "stdafx.h" #include "Word.h" +#include + +using std::cout; CWord::CWord(unsigned nBitLength) : m_nBitLength(nBitLength) @@ -23,7 +25,7 @@ CBit * CWord::GetAt(unsigned nBitPos) return nullptr; } -void CWord::Set(DWORD data) +void CWord::Set(unsigned data) { deque::iterator it; if (m_nBitLength < sizeof(data)) @@ -45,6 +47,29 @@ void CWord::Set(DWORD data) } } +void CWord::Set(unsigned char* data, unsigned lengthInBits) +{ + deque::iterator it; + if (m_nBitLength < lengthInBits) + { + it = m_word.begin(); + for (unsigned pos = 0; pos < m_nBitLength; pos++) + { + (*it) = data[pos>>3] & (1 << (7-(pos&7))); + it++; + } + } + else + { + unsigned pos = 0; + for (it = m_word.begin(); it != m_word.end(); it++) + { + (*it) = data[pos>>3] & (1 << (7-(pos&7))); + ++pos; + } + } +} + void CWord::Rotate() { deque buffer = m_word; @@ -113,5 +138,15 @@ void CWord::Print() { (*it).Print(); } - printf("\r\n"); + cout << "\r\n"; +} + +void CWord::Copy(unsigned char* ptr) +{ + unsigned pos = 0; + for(auto it = m_word.begin(); it != m_word.end(); it++) + { + ptr[pos>>3] |= (*it).Get() << (7-(pos&7)); + ++pos; + } } diff --git a/DRAMSys/simulator/src/error/ECC/Word.h b/DRAMSys/simulator/src/error/ECC/Word.h index e3ae7c66..f21432cb 100644 --- a/DRAMSys/simulator/src/error/ECC/Word.h +++ b/DRAMSys/simulator/src/error/ECC/Word.h @@ -20,12 +20,15 @@ public: CBit* GetAt(unsigned nBitPos); - void Set(DWORD data); + void Set(unsigned data); + void Set(unsigned char* data, unsigned lengthInBits); void Rotate(); bool Insert(unsigned npos, CBit b); bool Delete(unsigned npos); + void Copy(unsigned char* ptr); + void Append(CBit b); void Resize(unsigned nsize); @@ -36,7 +39,7 @@ public: void Print(); - CWord& operator=(DWORD d) + CWord& operator=(unsigned d) { Set(d); return *this; diff --git a/DRAMSys/simulator/src/error/controllerECC.h b/DRAMSys/simulator/src/error/controllerECC.h index 0a33c1c1..509e1036 100644 --- a/DRAMSys/simulator/src/error/controllerECC.h +++ b/DRAMSys/simulator/src/error/controllerECC.h @@ -3,6 +3,8 @@ #include +#include "ECC/ECC.h" + #include "../common/xmlAddressdecoder.h" #include "../common/DebugManager.h" @@ -29,15 +31,85 @@ public: // Forward interface virtual tlm::tlm_sync_enum nb_transport_fw( int id, tlm::tlm_generic_payload& trans, tlm::tlm_phase& phase, sc_time& delay ) { - if(trans.get_command() == TLM_WRITE_COMMAND) - { - // Allocate memory if necessary - if(m_mBuffer[trans.get_address()].size() != trans.get_data_length()) - m_mBuffer[trans.get_address()].resize(trans.get_data_length()); + if(trans.get_command() == TLM_WRITE_COMMAND && trans.get_response_status() == TLM_INCOMPLETE_RESPONSE) + { + // Get data and length + unsigned nDataLength = trans.get_data_length(); + unsigned char* pData = trans.get_data_ptr(); - // Copy data - memcpy(m_mBuffer[trans.get_address()].data(), trans.get_data_ptr(), trans.get_data_length()); + // Calculate how many 64 bit blocks are there + unsigned nBlocks = nDataLength>>3; + + // Create new data array for data with ECC + unsigned char* pDataECC = new unsigned char[nBlocks*9]; + memset(pDataECC, 0x0, nBlocks*9*sizeof(unsigned char)); + + // Create ECC data for every block + for(unsigned i = 0; i < nBlocks; i++) + { + // Create all variables needed for calulation + CWord dataword(64); + CWord checkbits(8); + + // Fill in current data block + dataword.Set(&pData[i<<3], 64); + + // Extend data word + ECC::ExtendWord(dataword); + + checkbits = 0; + + // Calculate Checkbits + ECC::CalculateCheckbits(dataword, checkbits); + ECC::InsertCheckbits(dataword, checkbits); + + // Calculate Parity + ECC::CalculateParityBit(dataword, checkbits[7]); + + // Copy old data + memcpy(&pDataECC[i*9], &pData[i<<3], 8); + + // Save new data + checkbits.Copy(&pDataECC[i*9+8]); + } + + // Print all +// for(unsigned i = 0; i < nBlocks; i++) +// { +// for(unsigned j = 0; j < 9; j++) +// { +// cout << setw(2) << setfill('0') << hex << uppercase << (int)pDataECC[i*9+j]; +// } +// cout << endl; +// } +// cout << endl; + + // Change transport data length + trans.set_data_length(nBlocks*9); + + // delete old data + delete[] trans.get_data_ptr(); + + // Set new data + trans.set_data_ptr(pDataECC); } + else if(trans.get_response_status() == TLM_INCOMPLETE_RESPONSE) + { + // 64 -> 72 + + // Get data length + unsigned nDataLength = trans.get_data_length(); + + // delete old data + delete[] trans.get_data_ptr(); + + // Set new data + nDataLength += nDataLength>>3; + trans.set_data_ptr(new unsigned char [nDataLength]); + + // Change transport data length + trans.set_data_length(nDataLength); + } return i_socket[id]->nb_transport_fw( trans, phase, delay ); } @@ -47,27 +119,108 @@ public: { if(trans.get_command() == TLM_READ_COMMAND && phase == 3) { - if(m_mBuffer[trans.get_address()].size() == trans.get_data_length()) - { - // Data can be compared, they got the same size - int error = memcmp(m_mBuffer[trans.get_address()].data(), trans.get_data_ptr(), trans.get_data_length()); - if(error) - { - // Data not equal - cout << "\nError Detected: Address: 0x" << hex << trans.get_address(); + // Get data and length + unsigned nDataLength = trans.get_data_length(); + unsigned char* pData = trans.get_data_ptr(); - for(unsigned n = 0; n < trans.get_data_length(); n++) - { - if(m_mBuffer[trans.get_address()].data()[n] != trans.get_data_ptr()[n]) - { - cout << "\n\t\tError Byte " << dec << n << " Orig: 0x" << hex << (int)m_mBuffer[trans.get_address()].data()[n] - << " Read: 0x" << hex << (int)trans.get_data_ptr()[n]; - } - } - cout << endl; - } - } - } + // Calculate how many 72 bit blocks are there + unsigned nBlocks = nDataLength/9; + + // Print all +// for(unsigned i = 0; i < nBlocks; i++) +// { +// for(unsigned j = 0; j < 9; j++) +// { +// cout << setw(2) << setfill('0') << hex << uppercase << (int)pData[i*9+j]; +// } +// cout << endl; +// } +// cout << endl; + + // Verify ECC data for every block + for(unsigned i = 0; i < nBlocks; i++) + { + // Create all variables needed for calulation + CWord dataword(64); + CWord checkbits(8); + + // Fill in current data block + dataword.Set(&pData[i*9], 64); + checkbits.Set(&pData[i*9+8], 8); + + // Extend data word + ECC::ExtendWord(dataword); + + // Insert old checkbits + ECC::InsertCheckbits(dataword, checkbits); + ECC::InsertParityBit(dataword, checkbits[7]); + + checkbits = 0; + + // Calculate Checkbits + ECC::CalculateCheckbits(dataword, checkbits); + + // Calculate Parity + ECC::CalculateParityBit(dataword, checkbits[7]); + + // Translate Checkbits + bool bParity = checkbits[7] == CBit::ONE; + + unsigned char c = 0; + checkbits.Rotate(); + checkbits.Copy(&c); + c &= 0x7F; + + // Parity Error? + if(bParity) + { + // Parity Error + + if(c == 0) + { + // Only Parity Bit broken - continue + cout << "Parity Bit error" << endl; + continue; + } + else + { + // Data or Hamming Code Bit broken + cout << "Single Error Detected" << endl; + continue; + } + } + else + { + // No Parity Error + + if(c == 0) + { + // No error at all - continue + continue; + } + else + { + // Double error detected + cout << "Double Error Detected (Block " << i << ")." << endl; + continue; + } + } + } + // Change transport data length + trans.set_data_length(nBlocks<<3); + + // New Data + unsigned char* pDataECC = new unsigned char[nBlocks<<3]; + + // Copy data + memcpy(pDataECC, pData, nBlocks<<3); + + // delete old data + delete[] trans.get_data_ptr(); + + // Set new data + trans.set_data_ptr(pDataECC); + } return t_socket[id]->nb_transport_bw( trans, phase, delay ); } }; diff --git a/DRAMSys/simulator/src/error/errormodel.cpp b/DRAMSys/simulator/src/error/errormodel.cpp index 91eb789b..5ff3693f 100644 --- a/DRAMSys/simulator/src/error/errormodel.cpp +++ b/DRAMSys/simulator/src/error/errormodel.cpp @@ -49,7 +49,12 @@ void errorModel::init() burstLenght = Configuration::getInstance().memSpec.BurstLength; numberOfColumns = Configuration::getInstance().memSpec.NumberOfColumns; bytesPerColumn = xmlAddressDecoder::getInstance().amount["bytes"]; - numberOfRows = Configuration::getInstance().memSpec.NumberOfRows; + if(Configuration::getInstance().EnableControllerECC) + { + bytesPerColumn += bytesPerColumn>>3; + } + + numberOfRows = Configuration::getInstance().memSpec.NumberOfRows; numberOfBitErrorEvents = 0; diff --git a/DRAMSys/simulator/src/simulation/Arbiter.h b/DRAMSys/simulator/src/simulation/Arbiter.h index c12ff14f..114e3d03 100644 --- a/DRAMSys/simulator/src/simulation/Arbiter.h +++ b/DRAMSys/simulator/src/simulation/Arbiter.h @@ -124,13 +124,19 @@ private: { if (phase == BEGIN_REQ) { + // adjust address offset: + payload.set_address(payload.get_address() - Configuration::getInstance().AddressOffset); + // Map the payload with socket id. routeMap[&payload] = id; + // In the begin request phase the socket ID is appended to the payload. // It will extracted from the payload and used later. appendDramExtension(id, payload); payload.acquire(); - } else if (phase == END_RESP) { + } + else if (phase == END_RESP) + { // Erase before the payload is released. routeMap.erase(&payload); payload.release(); @@ -142,9 +148,11 @@ private: virtual unsigned int transport_dbg(int /*id*/, tlm::tlm_generic_payload &trans) { + // adjust address offset: + trans.set_address(trans.get_address() - Configuration::getInstance().AddressOffset); + DecodedAddress decodedAddress = xmlAddressDecoder::getInstance().decodeAddress(trans.get_address()); return iSocket[decodedAddress.channel]->transport_dbg(trans); - } void peqCallback(tlm_generic_payload& payload, const tlm_phase& phase) diff --git a/DRAMSys/simulator/src/simulation/Dram.h b/DRAMSys/simulator/src/simulation/Dram.h index 26375fcf..d641afcb 100644 --- a/DRAMSys/simulator/src/simulation/Dram.h +++ b/DRAMSys/simulator/src/simulation/Dram.h @@ -92,6 +92,9 @@ struct Dram : sc_module SC_CTOR(Dram) : tSocket("socket") { + if(Configuration::getInstance().EnableControllerECC) + bytesPerBurst += bytesPerBurst>>3; + std::uint64_t memorySize = Configuration::getInstance().getSimMemSizeInBytes(); // allocate and model storage of one DRAM channel using memory map memory = (unsigned char *)mmap(NULL, memorySize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0); @@ -390,7 +393,7 @@ struct Dram : sc_module } else if (phase == BEGIN_WR) { -#ifndef DRAMSYS_PCT +#if !defined (DRAMSYS_PCT) && !defined (DRAMSYS_GEM5) assert(payload.get_data_length() == bytesPerBurst); #endif @@ -415,7 +418,9 @@ struct Dram : sc_module } else if (phase == BEGIN_RD) { +#if !defined (DRAMSYS_PCT) && !defined (DRAMSYS_GEM5) assert(payload.get_data_length() == bytesPerBurst); +#endif numberOfTransactionsServed++; if(powerAnalysis == true){DRAMPower->doCommand(MemCommand::RD, bank, cycle);} @@ -445,7 +450,6 @@ struct Dram : sc_module } else if (StoreMode == StorageMode::Store) // Use Storage { - unsigned char *phyAddr = memory + payload.get_address(); memcpy(phyAddr, payload.get_data_ptr(), payload.get_data_length()); } @@ -550,12 +554,8 @@ struct Dram : sc_module virtual unsigned int transport_dbg(tlm::tlm_generic_payload& trans) { - printDebugMessage("transport_dgb"); - // FIXME: maybe the initiator wants to write more than burst size at once - assert(trans.get_data_length() == bytesPerBurst); - // TODO: This part is not tested yet, neither with traceplayers neither with GEM5 coupling if (StoreMode == StorageMode::NoStorage) { @@ -569,7 +569,7 @@ struct Dram : sc_module unsigned int len = trans.get_data_length(); //unsigned int bank = DramExtension::getExtension(trans).getBank().ID(); - cout << "cmd " << (cmd ? "write" : "read") << " adr " << hex << adr << " len " << len << endl; + //cout << "cmd " << (cmd ? "write" : "read") << " adr " << hex << adr << " len " << len << endl; if ( cmd == tlm::TLM_READ_COMMAND ) { diff --git a/DRAMSys/simulator/src/simulation/main.cpp b/DRAMSys/simulator/src/simulation/main.cpp index 18b474e9..0bb75469 100644 --- a/DRAMSys/simulator/src/simulation/main.cpp +++ b/DRAMSys/simulator/src/simulation/main.cpp @@ -72,7 +72,7 @@ int sc_main(int argc, char **argv) } else { - SimulationXML = resources + "simulations/wideio-ecc.xml"; + SimulationXML = resources + "simulations/ddr3-ecc.xml"; } std::vector players; diff --git a/DRAMSys/tests/error/generateErrorTest_4ch.pl b/DRAMSys/tests/error/generateErrorTest_4ch.pl new file mode 100644 index 00000000..1bad5d65 --- /dev/null +++ b/DRAMSys/tests/error/generateErrorTest_4ch.pl @@ -0,0 +1,72 @@ +#!/usr/bin/perl -w +use warnings; +use strict; + +# Assuming this address mapping: +# +# +# +# +# +# +# + +# This is how it should look like later: +# 31: write 0x0 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + +my $numberOfRows = 8192; +my $numberOfColumnsPerRow = 128; +my $bytesPerColumn = 16; +my $burstLength = 4; # burst length of 4 columns --> 4 columns written or read per access +my $dataLength = $bytesPerColumn * $burstLength; + +my $rowOffset = 0x4000; +my $colOffset = 0x80; + +# Generate Data Pattern: +my $dataPatternByte = "ff"; + +my $dataPattern = ""; +for(my $i = 0; $i < $dataLength; $i++) +{ + $dataPattern .= $dataPatternByte; +} + +my $clkCounter = 0; +my $addr = 0; + +# Generate Trace file (writes): + +for(my $ch = 0; $ch < 4; $ch++) { + $addr = 0; + $addr |= $ch << 27; + for(my $row = 0; $row < ($numberOfRows * $rowOffset); $row = $row + $rowOffset) + { + for(my $col = 0; $col < ($numberOfColumnsPerRow * $colOffset); $col = $col + ($colOffset * $burstLength)) + { + my $addrHex = sprintf("0x%x", $addr); + print "$clkCounter:\twrite\t$addrHex\t$dataPattern\n"; + $clkCounter++; + $addr += $colOffset * $burstLength; + } + } +} + +$clkCounter = 350000000; +$addr = 0; + +# Generate Trace file (reads): +for(my $ch = 0; $ch < 4; $ch++) { + $addr = 0; + $addr |= $ch << 27; + for(my $row = 0; $row < ($numberOfRows * $rowOffset); $row = $row + $rowOffset) + { + for(my $col = 0; $col < ($numberOfColumnsPerRow * $colOffset); $col = $col + ($colOffset * $burstLength)) + { + my $addrHex = sprintf("0x%x", $addr); + print "$clkCounter:\tread\t$addrHex\t$dataPattern\n"; + $clkCounter++; + $addr += $colOffset * $burstLength; + } + } +}