serialize.cc revision 11077
12SN/A/*
210905Sandreas.sandberg@arm.com * Copyright (c) 2015 ARM Limited
310905Sandreas.sandberg@arm.com * All rights reserved
410905Sandreas.sandberg@arm.com *
510905Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall
610905Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual
710905Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating
810905Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software
910905Sandreas.sandberg@arm.com * licensed hereunder.  You may use the software subject to the license
1010905Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated
1110905Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software,
1210905Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form.
1310905Sandreas.sandberg@arm.com *
141762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
159983Sstever@gmail.com * Copyright (c) 2013 Advanced Micro Devices, Inc.
169983Sstever@gmail.com * Copyright (c) 2013 Mark D. Hill and David A. Wood
172SN/A * All rights reserved.
182SN/A *
192SN/A * Redistribution and use in source and binary forms, with or without
202SN/A * modification, are permitted provided that the following conditions are
212SN/A * met: redistributions of source code must retain the above copyright
222SN/A * notice, this list of conditions and the following disclaimer;
232SN/A * redistributions in binary form must reproduce the above copyright
242SN/A * notice, this list of conditions and the following disclaimer in the
252SN/A * documentation and/or other materials provided with the distribution;
262SN/A * neither the name of the copyright holders nor the names of its
272SN/A * contributors may be used to endorse or promote products derived from
282SN/A * this software without specific prior written permission.
292SN/A *
302SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
312SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
322SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
332SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
342SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
352SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
362SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
372SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
382SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
392SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
402SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
412665Ssaidi@eecs.umich.edu *
422760Sbinkertn@umich.edu * Authors: Nathan Binkert
432760Sbinkertn@umich.edu *          Erik Hallnor
442665Ssaidi@eecs.umich.edu *          Steve Reinhardt
4510905Sandreas.sandberg@arm.com *          Andreas Sandberg
462SN/A */
472SN/A
488229Snate@binkert.org#include <sys/stat.h>
492SN/A#include <sys/time.h>
50363SN/A#include <sys/types.h>
512SN/A
528229Snate@binkert.org#include <cerrno>
532SN/A#include <fstream>
542SN/A#include <list>
552SN/A#include <string>
562SN/A#include <vector>
572SN/A
5810907Sandreas.sandberg@arm.com#include "base/framebuffer.hh"
59363SN/A#include "base/inifile.hh"
6056SN/A#include "base/misc.hh"
611388SN/A#include "base/output.hh"
62217SN/A#include "base/str.hh"
63363SN/A#include "base/trace.hh"
6410905Sandreas.sandberg@arm.com#include "debug/Checkpoint.hh"
6556SN/A#include "sim/eventq.hh"
6656SN/A#include "sim/serialize.hh"
6756SN/A#include "sim/sim_events.hh"
681638SN/A#include "sim/sim_exit.hh"
6956SN/A#include "sim/sim_object.hh"
702SN/A
712356SN/A// For stat reset hack
722356SN/A#include "sim/stat_control.hh"
732356SN/A
742SN/Ausing namespace std;
752SN/A
764762Snate@binkert.org//
774762Snate@binkert.org// The base implementations use to_number for parsing and '<<' for
784762Snate@binkert.org// displaying, suitable for integer types.
794762Snate@binkert.org//
804762Snate@binkert.orgtemplate <class T>
814762Snate@binkert.orgbool
824762Snate@binkert.orgparseParam(const string &s, T &value)
834762Snate@binkert.org{
844762Snate@binkert.org    return to_number(s, value);
854762Snate@binkert.org}
864762Snate@binkert.org
874762Snate@binkert.orgtemplate <class T>
884762Snate@binkert.orgvoid
8910905Sandreas.sandberg@arm.comshowParam(CheckpointOut &os, const T &value)
904762Snate@binkert.org{
914762Snate@binkert.org    os << value;
924762Snate@binkert.org}
934762Snate@binkert.org
944762Snate@binkert.org//
954762Snate@binkert.org// Template specializations:
964762Snate@binkert.org// - char (8-bit integer)
974762Snate@binkert.org// - floating-point types
984762Snate@binkert.org// - bool
994762Snate@binkert.org// - string
1004762Snate@binkert.org//
1014762Snate@binkert.org
1024762Snate@binkert.org// Treat 8-bit ints (chars) as ints on output, not as chars
1034762Snate@binkert.orgtemplate <>
1044762Snate@binkert.orgvoid
10510905Sandreas.sandberg@arm.comshowParam(CheckpointOut &os, const char &value)
1067494Ssteve.reinhardt@amd.com{
1077494Ssteve.reinhardt@amd.com    os << (int)value;
1087494Ssteve.reinhardt@amd.com}
1097494Ssteve.reinhardt@amd.com
1107494Ssteve.reinhardt@amd.com
1117494Ssteve.reinhardt@amd.comtemplate <>
1127494Ssteve.reinhardt@amd.comvoid
11310905Sandreas.sandberg@arm.comshowParam(CheckpointOut &os, const signed char &value)
1144762Snate@binkert.org{
1154762Snate@binkert.org    os << (int)value;
1164762Snate@binkert.org}
1174762Snate@binkert.org
1184762Snate@binkert.org
1194762Snate@binkert.orgtemplate <>
1204762Snate@binkert.orgvoid
12110905Sandreas.sandberg@arm.comshowParam(CheckpointOut &os, const unsigned char &value)
1224762Snate@binkert.org{
1234762Snate@binkert.org    os << (unsigned int)value;
1244762Snate@binkert.org}
1254762Snate@binkert.org
1264762Snate@binkert.org
1274762Snate@binkert.orgtemplate <>
1284762Snate@binkert.orgbool
1294762Snate@binkert.orgparseParam(const string &s, float &value)
1304762Snate@binkert.org{
13110386Sandreas.hansson@arm.com    return to_number(s, value);
1324762Snate@binkert.org}
1334762Snate@binkert.org
1344762Snate@binkert.orgtemplate <>
1354762Snate@binkert.orgbool
1364762Snate@binkert.orgparseParam(const string &s, double &value)
1374762Snate@binkert.org{
13810386Sandreas.hansson@arm.com    return to_number(s, value);
1394762Snate@binkert.org}
1404762Snate@binkert.org
1414762Snate@binkert.orgtemplate <>
1424762Snate@binkert.orgbool
1434762Snate@binkert.orgparseParam(const string &s, bool &value)
1444762Snate@binkert.org{
14510386Sandreas.hansson@arm.com    return to_bool(s, value);
1464762Snate@binkert.org}
1474762Snate@binkert.org
1484762Snate@binkert.org// Display bools as strings
1494762Snate@binkert.orgtemplate <>
1504762Snate@binkert.orgvoid
15110905Sandreas.sandberg@arm.comshowParam(CheckpointOut &os, const bool &value)
1524762Snate@binkert.org{
1534762Snate@binkert.org    os << (value ? "true" : "false");
1544762Snate@binkert.org}
1554762Snate@binkert.org
1564762Snate@binkert.org
1574762Snate@binkert.org// String requires no processing to speak of
1584762Snate@binkert.orgtemplate <>
1594762Snate@binkert.orgbool
1604762Snate@binkert.orgparseParam(const string &s, string &value)
1614762Snate@binkert.org{
1624762Snate@binkert.org    value = s;
1634762Snate@binkert.org    return true;
1644762Snate@binkert.org}
1654762Snate@binkert.org
1662287SN/Aint Serializable::ckptMaxCount = 0;
1672287SN/Aint Serializable::ckptCount = 0;
1682287SN/Aint Serializable::ckptPrevCount = -1;
16910905Sandreas.sandberg@arm.comstd::stack<std::string> Serializable::path;
1702SN/A
171217SN/Atemplate <class T>
1722SN/Avoid
17310905Sandreas.sandberg@arm.comparamOut(CheckpointOut &os, const string &name, const T &param)
1742SN/A{
175217SN/A    os << name << "=";
176217SN/A    showParam(os, param);
177217SN/A    os << "\n";
1782SN/A}
1792SN/A
1804841Ssaidi@eecs.umich.edutemplate <class T>
1814841Ssaidi@eecs.umich.eduvoid
18210905Sandreas.sandberg@arm.comarrayParamOut(CheckpointOut &os, const string &name, const vector<T> &param)
1834841Ssaidi@eecs.umich.edu{
1846227Snate@binkert.org    typename vector<T>::size_type size = param.size();
1854841Ssaidi@eecs.umich.edu    os << name << "=";
1864841Ssaidi@eecs.umich.edu    if (size > 0)
1874841Ssaidi@eecs.umich.edu        showParam(os, param[0]);
1886227Snate@binkert.org    for (typename vector<T>::size_type i = 1; i < size; ++i) {
1894841Ssaidi@eecs.umich.edu        os << " ";
1904841Ssaidi@eecs.umich.edu        showParam(os, param[i]);
1914841Ssaidi@eecs.umich.edu    }
1924841Ssaidi@eecs.umich.edu    os << "\n";
1934841Ssaidi@eecs.umich.edu}
1944841Ssaidi@eecs.umich.edu
1957948SAli.Saidi@ARM.comtemplate <class T>
1967948SAli.Saidi@ARM.comvoid
19710905Sandreas.sandberg@arm.comarrayParamOut(CheckpointOut &os, const string &name, const list<T> &param)
1987948SAli.Saidi@ARM.com{
1997948SAli.Saidi@ARM.com    typename list<T>::const_iterator it = param.begin();
2007948SAli.Saidi@ARM.com
2017948SAli.Saidi@ARM.com    os << name << "=";
2027948SAli.Saidi@ARM.com    if (param.size() > 0)
2037948SAli.Saidi@ARM.com        showParam(os, *it);
2047948SAli.Saidi@ARM.com    it++;
2057948SAli.Saidi@ARM.com    while (it != param.end()) {
2067948SAli.Saidi@ARM.com        os << " ";
2077948SAli.Saidi@ARM.com        showParam(os, *it);
2087948SAli.Saidi@ARM.com        it++;
2097948SAli.Saidi@ARM.com    }
2107948SAli.Saidi@ARM.com    os << "\n";
2117948SAli.Saidi@ARM.com}
212217SN/A
213217SN/Atemplate <class T>
214217SN/Avoid
21511076SCurtis.Dunham@arm.comarrayParamOut(CheckpointOut &os, const string &name, const set<T> &param)
21611076SCurtis.Dunham@arm.com{
21711076SCurtis.Dunham@arm.com    typename set<T>::const_iterator it = param.begin();
21811076SCurtis.Dunham@arm.com
21911076SCurtis.Dunham@arm.com    os << name << "=";
22011076SCurtis.Dunham@arm.com    if (param.size() > 0)
22111076SCurtis.Dunham@arm.com        showParam(os, *it);
22211076SCurtis.Dunham@arm.com    it++;
22311076SCurtis.Dunham@arm.com    while (it != param.end()) {
22411076SCurtis.Dunham@arm.com        os << " ";
22511076SCurtis.Dunham@arm.com        showParam(os, *it);
22611076SCurtis.Dunham@arm.com        it++;
22711076SCurtis.Dunham@arm.com    }
22811076SCurtis.Dunham@arm.com    os << "\n";
22911076SCurtis.Dunham@arm.com}
23011076SCurtis.Dunham@arm.com
23111076SCurtis.Dunham@arm.comtemplate <class T>
23211076SCurtis.Dunham@arm.comvoid
23310905Sandreas.sandberg@arm.comparamIn(CheckpointIn &cp, const string &name, T &param)
2342SN/A{
23510905Sandreas.sandberg@arm.com    const string &section(Serializable::currentSection());
2366225Snate@binkert.org    string str;
23710905Sandreas.sandberg@arm.com    if (!cp.find(section, name, str) || !parseParam(str, param)) {
238217SN/A        fatal("Can't unserialize '%s:%s'\n", section, name);
239217SN/A    }
2402SN/A}
2412SN/A
2426820SLisa.Hsu@amd.comtemplate <class T>
2436820SLisa.Hsu@amd.combool
24411075SCurtis.Dunham@arm.comoptParamIn(CheckpointIn &cp, const string &name, T &param, bool warn)
2456820SLisa.Hsu@amd.com{
24610905Sandreas.sandberg@arm.com    const string &section(Serializable::currentSection());
2476820SLisa.Hsu@amd.com    string str;
24810905Sandreas.sandberg@arm.com    if (!cp.find(section, name, str) || !parseParam(str, param)) {
24911075SCurtis.Dunham@arm.com        if (warn)
25011075SCurtis.Dunham@arm.com            warn("optional parameter %s:%s not present\n", section, name);
2516820SLisa.Hsu@amd.com        return false;
2526820SLisa.Hsu@amd.com    } else {
2536820SLisa.Hsu@amd.com        return true;
2546820SLisa.Hsu@amd.com    }
2556820SLisa.Hsu@amd.com}
256217SN/A
257217SN/Atemplate <class T>
258217SN/Avoid
25910905Sandreas.sandberg@arm.comarrayParamOut(CheckpointOut &os, const string &name,
26010905Sandreas.sandberg@arm.com              const T *param, unsigned size)
261217SN/A{
262217SN/A    os << name << "=";
263217SN/A    if (size > 0)
264217SN/A        showParam(os, param[0]);
2656227Snate@binkert.org    for (unsigned i = 1; i < size; ++i) {
266217SN/A        os << " ";
267217SN/A        showParam(os, param[i]);
268217SN/A    }
269217SN/A    os << "\n";
270217SN/A}
271217SN/A
272217SN/A
273217SN/Atemplate <class T>
274217SN/Avoid
27510905Sandreas.sandberg@arm.comarrayParamIn(CheckpointIn &cp, const string &name, T *param, unsigned size)
276217SN/A{
27710905Sandreas.sandberg@arm.com    const string &section(Serializable::currentSection());
2786225Snate@binkert.org    string str;
27910905Sandreas.sandberg@arm.com    if (!cp.find(section, name, str)) {
280217SN/A        fatal("Can't unserialize '%s:%s'\n", section, name);
281217SN/A    }
282217SN/A
283217SN/A    // code below stolen from VectorParam<T>::parse().
284217SN/A    // it would be nice to unify these somehow...
285217SN/A
286217SN/A    vector<string> tokens;
287217SN/A
288217SN/A    tokenize(tokens, str, ' ');
289217SN/A
290217SN/A    // Need this if we were doing a vector
291217SN/A    // value.resize(tokens.size());
292217SN/A
293217SN/A    if (tokens.size() != size) {
294217SN/A        fatal("Array size mismatch on %s:%s'\n", section, name);
295217SN/A    }
296217SN/A
2976227Snate@binkert.org    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
298217SN/A        // need to parse into local variable to handle vector<bool>,
299217SN/A        // for which operator[] returns a special reference class
300217SN/A        // that's not the same as 'bool&', (since it's a packed
301217SN/A        // vector)
30210905Sandreas.sandberg@arm.com        T scalar_value;
303217SN/A        if (!parseParam(tokens[i], scalar_value)) {
304217SN/A            string err("could not parse \"");
305217SN/A
306217SN/A            err += str;
307217SN/A            err += "\"";
308217SN/A
309217SN/A            fatal(err);
310217SN/A        }
311217SN/A
312217SN/A        // assign parsed value to vector
313217SN/A        param[i] = scalar_value;
314217SN/A    }
315217SN/A}
316217SN/A
3174841Ssaidi@eecs.umich.edutemplate <class T>
3184841Ssaidi@eecs.umich.eduvoid
31910905Sandreas.sandberg@arm.comarrayParamIn(CheckpointIn &cp, const string &name, vector<T> &param)
3204841Ssaidi@eecs.umich.edu{
32110905Sandreas.sandberg@arm.com    const string &section(Serializable::currentSection());
3226225Snate@binkert.org    string str;
32310905Sandreas.sandberg@arm.com    if (!cp.find(section, name, str)) {
3244841Ssaidi@eecs.umich.edu        fatal("Can't unserialize '%s:%s'\n", section, name);
3254841Ssaidi@eecs.umich.edu    }
3264841Ssaidi@eecs.umich.edu
3274841Ssaidi@eecs.umich.edu    // code below stolen from VectorParam<T>::parse().
3284841Ssaidi@eecs.umich.edu    // it would be nice to unify these somehow...
3294841Ssaidi@eecs.umich.edu
3304841Ssaidi@eecs.umich.edu    vector<string> tokens;
3314841Ssaidi@eecs.umich.edu
3324841Ssaidi@eecs.umich.edu    tokenize(tokens, str, ' ');
3334841Ssaidi@eecs.umich.edu
3344841Ssaidi@eecs.umich.edu    // Need this if we were doing a vector
3354841Ssaidi@eecs.umich.edu    // value.resize(tokens.size());
3364841Ssaidi@eecs.umich.edu
3374841Ssaidi@eecs.umich.edu    param.resize(tokens.size());
3384841Ssaidi@eecs.umich.edu
3396227Snate@binkert.org    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
3404841Ssaidi@eecs.umich.edu        // need to parse into local variable to handle vector<bool>,
3414841Ssaidi@eecs.umich.edu        // for which operator[] returns a special reference class
3424841Ssaidi@eecs.umich.edu        // that's not the same as 'bool&', (since it's a packed
3434841Ssaidi@eecs.umich.edu        // vector)
34410905Sandreas.sandberg@arm.com        T scalar_value;
3454841Ssaidi@eecs.umich.edu        if (!parseParam(tokens[i], scalar_value)) {
3464841Ssaidi@eecs.umich.edu            string err("could not parse \"");
3474841Ssaidi@eecs.umich.edu
3484841Ssaidi@eecs.umich.edu            err += str;
3494841Ssaidi@eecs.umich.edu            err += "\"";
3504841Ssaidi@eecs.umich.edu
3514841Ssaidi@eecs.umich.edu            fatal(err);
3524841Ssaidi@eecs.umich.edu        }
3534841Ssaidi@eecs.umich.edu
3544841Ssaidi@eecs.umich.edu        // assign parsed value to vector
3554841Ssaidi@eecs.umich.edu        param[i] = scalar_value;
3564841Ssaidi@eecs.umich.edu    }
3574841Ssaidi@eecs.umich.edu}
3584841Ssaidi@eecs.umich.edu
3597948SAli.Saidi@ARM.comtemplate <class T>
3607948SAli.Saidi@ARM.comvoid
36110905Sandreas.sandberg@arm.comarrayParamIn(CheckpointIn &cp, const string &name, list<T> &param)
3627948SAli.Saidi@ARM.com{
36310905Sandreas.sandberg@arm.com    const string &section(Serializable::currentSection());
3647948SAli.Saidi@ARM.com    string str;
36510905Sandreas.sandberg@arm.com    if (!cp.find(section, name, str)) {
3667948SAli.Saidi@ARM.com        fatal("Can't unserialize '%s:%s'\n", section, name);
3677948SAli.Saidi@ARM.com    }
3687948SAli.Saidi@ARM.com    param.clear();
3697948SAli.Saidi@ARM.com
3707948SAli.Saidi@ARM.com    vector<string> tokens;
3717948SAli.Saidi@ARM.com    tokenize(tokens, str, ' ');
3727948SAli.Saidi@ARM.com
3737948SAli.Saidi@ARM.com    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
37410905Sandreas.sandberg@arm.com        T scalar_value;
3757948SAli.Saidi@ARM.com        if (!parseParam(tokens[i], scalar_value)) {
3767948SAli.Saidi@ARM.com            string err("could not parse \"");
3777948SAli.Saidi@ARM.com
3787948SAli.Saidi@ARM.com            err += str;
3797948SAli.Saidi@ARM.com            err += "\"";
3807948SAli.Saidi@ARM.com
3817948SAli.Saidi@ARM.com            fatal(err);
3827948SAli.Saidi@ARM.com        }
3837948SAli.Saidi@ARM.com
3847948SAli.Saidi@ARM.com        // assign parsed value to vector
3857948SAli.Saidi@ARM.com        param.push_back(scalar_value);
3867948SAli.Saidi@ARM.com    }
3877948SAli.Saidi@ARM.com}
3887948SAli.Saidi@ARM.com
38911076SCurtis.Dunham@arm.comtemplate <class T>
39011076SCurtis.Dunham@arm.comvoid
39111076SCurtis.Dunham@arm.comarrayParamIn(CheckpointIn &cp, const string &name, set<T> &param)
39211076SCurtis.Dunham@arm.com{
39311076SCurtis.Dunham@arm.com    const string &section(Serializable::currentSection());
39411076SCurtis.Dunham@arm.com    string str;
39511076SCurtis.Dunham@arm.com    if (!cp.find(section, name, str)) {
39611076SCurtis.Dunham@arm.com        fatal("Can't unserialize '%s:%s'\n", section, name);
39711076SCurtis.Dunham@arm.com    }
39811076SCurtis.Dunham@arm.com    param.clear();
39911076SCurtis.Dunham@arm.com
40011076SCurtis.Dunham@arm.com    vector<string> tokens;
40111076SCurtis.Dunham@arm.com    tokenize(tokens, str, ' ');
40211076SCurtis.Dunham@arm.com
40311076SCurtis.Dunham@arm.com    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
40411076SCurtis.Dunham@arm.com        T scalar_value;
40511076SCurtis.Dunham@arm.com        if (!parseParam(tokens[i], scalar_value)) {
40611076SCurtis.Dunham@arm.com            string err("could not parse \"");
40711076SCurtis.Dunham@arm.com
40811076SCurtis.Dunham@arm.com            err += str;
40911076SCurtis.Dunham@arm.com            err += "\"";
41011076SCurtis.Dunham@arm.com
41111076SCurtis.Dunham@arm.com            fatal(err);
41211076SCurtis.Dunham@arm.com        }
41311076SCurtis.Dunham@arm.com
41411076SCurtis.Dunham@arm.com        // assign parsed value to vector
41511076SCurtis.Dunham@arm.com        param.insert(scalar_value);
41611076SCurtis.Dunham@arm.com    }
41711076SCurtis.Dunham@arm.com}
41811076SCurtis.Dunham@arm.com
4197948SAli.Saidi@ARM.com
420237SN/Avoid
42110905Sandreas.sandberg@arm.comobjParamIn(CheckpointIn &cp, const string &name, SimObject * &param)
422237SN/A{
42310905Sandreas.sandberg@arm.com    const string &section(Serializable::currentSection());
42410905Sandreas.sandberg@arm.com    if (!cp.findObj(section, name, param)) {
425237SN/A        fatal("Can't unserialize '%s:%s'\n", section, name);
426237SN/A    }
427237SN/A}
428237SN/A
429237SN/A
4305543Ssaidi@eecs.umich.edu#define INSTANTIATE_PARAM_TEMPLATES(type)                               \
43110905Sandreas.sandberg@arm.com    template void                                                       \
43210905Sandreas.sandberg@arm.com    paramOut(CheckpointOut &os, const string &name, type const &param); \
43310905Sandreas.sandberg@arm.com    template void                                                       \
43410905Sandreas.sandberg@arm.com    paramIn(CheckpointIn &cp, const string &name, type & param);        \
43510905Sandreas.sandberg@arm.com    template bool                                                       \
43611075SCurtis.Dunham@arm.com    optParamIn(CheckpointIn &cp, const string &name, type & param,      \
43711075SCurtis.Dunham@arm.com               bool warn);                                              \
43810905Sandreas.sandberg@arm.com    template void                                                       \
43910905Sandreas.sandberg@arm.com    arrayParamOut(CheckpointOut &os, const string &name,                \
44010905Sandreas.sandberg@arm.com                  type const *param, unsigned size);                    \
44110905Sandreas.sandberg@arm.com    template void                                                       \
44210905Sandreas.sandberg@arm.com    arrayParamIn(CheckpointIn &cp, const string &name,                  \
44310905Sandreas.sandberg@arm.com                 type *param, unsigned size);                           \
44410905Sandreas.sandberg@arm.com    template void                                                       \
44510905Sandreas.sandberg@arm.com    arrayParamOut(CheckpointOut &os, const string &name,                \
44610905Sandreas.sandberg@arm.com                  const vector<type> &param);                           \
44710905Sandreas.sandberg@arm.com    template void                                                       \
44810905Sandreas.sandberg@arm.com    arrayParamIn(CheckpointIn &cp, const string &name,                  \
44910905Sandreas.sandberg@arm.com                 vector<type> &param);                                  \
45010905Sandreas.sandberg@arm.com    template void                                                       \
45110905Sandreas.sandberg@arm.com    arrayParamOut(CheckpointOut &os, const string &name,                \
45210905Sandreas.sandberg@arm.com                  const list<type> &param);                             \
45310905Sandreas.sandberg@arm.com    template void                                                       \
45410905Sandreas.sandberg@arm.com    arrayParamIn(CheckpointIn &cp, const string &name,                  \
45510905Sandreas.sandberg@arm.com                 list<type> &param);
456217SN/A
4577494Ssteve.reinhardt@amd.comINSTANTIATE_PARAM_TEMPLATES(char)
4581642SN/AINSTANTIATE_PARAM_TEMPLATES(signed char)
4591642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned char)
4601642SN/AINSTANTIATE_PARAM_TEMPLATES(signed short)
4611642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned short)
4621642SN/AINSTANTIATE_PARAM_TEMPLATES(signed int)
4631642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned int)
4641642SN/AINSTANTIATE_PARAM_TEMPLATES(signed long)
4651642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned long)
4661642SN/AINSTANTIATE_PARAM_TEMPLATES(signed long long)
4671642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned long long)
468219SN/AINSTANTIATE_PARAM_TEMPLATES(bool)
4695992Snate@binkert.orgINSTANTIATE_PARAM_TEMPLATES(float)
4705992Snate@binkert.orgINSTANTIATE_PARAM_TEMPLATES(double)
471217SN/AINSTANTIATE_PARAM_TEMPLATES(string)
47210907Sandreas.sandberg@arm.comINSTANTIATE_PARAM_TEMPLATES(Pixel)
473217SN/A
47411076SCurtis.Dunham@arm.com// set is only used with strings and furthermore doesn't agree with Pixel
47511076SCurtis.Dunham@arm.comtemplate void
47611076SCurtis.Dunham@arm.comarrayParamOut(CheckpointOut &, const string &, const set<string> &);
47711076SCurtis.Dunham@arm.comtemplate void
47811076SCurtis.Dunham@arm.comarrayParamIn(CheckpointIn &, const string &, set<string> &);
479217SN/A
480395SN/A/////////////////////////////
481395SN/A
482395SN/A/// Container for serializing global variables (not associated with
483395SN/A/// any serialized object).
484395SN/Aclass Globals : public Serializable
4852SN/A{
486395SN/A  public:
48710905Sandreas.sandberg@arm.com    Globals()
48810905Sandreas.sandberg@arm.com        : unserializedCurTick(0) {}
48910905Sandreas.sandberg@arm.com
49010905Sandreas.sandberg@arm.com    void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE;
49110905Sandreas.sandberg@arm.com    void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE;
49210905Sandreas.sandberg@arm.com
49310905Sandreas.sandberg@arm.com    Tick unserializedCurTick;
494395SN/A};
4952SN/A
496395SN/A/// The one and only instance of the Globals class.
497395SN/AGlobals globals;
4982SN/A
49911077SCurtis.Dunham@arm.com/// The version tags for this build of the simulator, to be stored in the
50011077SCurtis.Dunham@arm.com/// Globals section during serialization and compared upon unserialization.
50111077SCurtis.Dunham@arm.comextern std::set<std::string> version_tags;
50211077SCurtis.Dunham@arm.com
50310905Sandreas.sandberg@arm.comvoid
50410905Sandreas.sandberg@arm.comGlobals::serialize(CheckpointOut &cp) const
5052SN/A{
50610905Sandreas.sandberg@arm.com    paramOut(cp, "curTick", curTick());
50711077SCurtis.Dunham@arm.com    SERIALIZE_CONTAINER(version_tags);
5082SN/A}
5092SN/A
5102SN/Avoid
51110905Sandreas.sandberg@arm.comGlobals::unserialize(CheckpointIn &cp)
5122SN/A{
51310905Sandreas.sandberg@arm.com    paramIn(cp, "curTick", unserializedCurTick);
51411077SCurtis.Dunham@arm.com
51511077SCurtis.Dunham@arm.com    const std::string &section(Serializable::currentSection());
51611077SCurtis.Dunham@arm.com    std::string str;
51711077SCurtis.Dunham@arm.com    if (!cp.find(section, "version_tags", str)) {
51811077SCurtis.Dunham@arm.com        warn("**********************************************************\n");
51911077SCurtis.Dunham@arm.com        warn("!!!! Checkpoint uses an old versioning scheme.        !!!!\n");
52011077SCurtis.Dunham@arm.com        warn("Run the checkpoint upgrader (util/cpt_upgrader.py) on your "
52111077SCurtis.Dunham@arm.com             "checkpoint\n");
52211077SCurtis.Dunham@arm.com        warn("**********************************************************\n");
52311077SCurtis.Dunham@arm.com        return;
52411077SCurtis.Dunham@arm.com    }
52511077SCurtis.Dunham@arm.com
52611077SCurtis.Dunham@arm.com    std::set<std::string> cpt_tags;
52711077SCurtis.Dunham@arm.com    arrayParamIn(cp, "version_tags", cpt_tags); // UNSERIALIZE_CONTAINER
52811077SCurtis.Dunham@arm.com
52911077SCurtis.Dunham@arm.com    bool err = false;
53011077SCurtis.Dunham@arm.com    for (const auto& t : version_tags) {
53111077SCurtis.Dunham@arm.com        if (cpt_tags.find(t) == cpt_tags.end()) {
53211077SCurtis.Dunham@arm.com            // checkpoint is missing tag that this binary has
53311077SCurtis.Dunham@arm.com            if (!err) {
53411077SCurtis.Dunham@arm.com                warn("*****************************************************\n");
53511077SCurtis.Dunham@arm.com                warn("!!!! Checkpoint is missing the following version tags:\n");
53611077SCurtis.Dunham@arm.com                err = true;
53711077SCurtis.Dunham@arm.com            }
53811077SCurtis.Dunham@arm.com            warn("  %s\n", t);
53911077SCurtis.Dunham@arm.com        }
54011077SCurtis.Dunham@arm.com    }
54111077SCurtis.Dunham@arm.com    if (err) {
54211077SCurtis.Dunham@arm.com        warn("You might experience some issues when restoring and should run "
54311077SCurtis.Dunham@arm.com             "the checkpoint upgrader (util/cpt_upgrader.py) on your "
54411077SCurtis.Dunham@arm.com             "checkpoint\n");
54511077SCurtis.Dunham@arm.com        warn("**********************************************************\n");
54611077SCurtis.Dunham@arm.com    }
54711077SCurtis.Dunham@arm.com
54811077SCurtis.Dunham@arm.com    err = false;
54911077SCurtis.Dunham@arm.com    for (const auto& t : cpt_tags) {
55011077SCurtis.Dunham@arm.com        if (version_tags.find(t) == version_tags.end()) {
55111077SCurtis.Dunham@arm.com            // gem5 binary is missing tag that this checkpoint has
55211077SCurtis.Dunham@arm.com            if (!err) {
55311077SCurtis.Dunham@arm.com                warn("*****************************************************\n");
55411077SCurtis.Dunham@arm.com                warn("!!!! gem5 is missing the following version tags:\n");
55511077SCurtis.Dunham@arm.com                err = true;
55611077SCurtis.Dunham@arm.com            }
55711077SCurtis.Dunham@arm.com            warn("  %s\n", t);
55811077SCurtis.Dunham@arm.com        }
55911077SCurtis.Dunham@arm.com    }
56011077SCurtis.Dunham@arm.com    if (err) {
56111077SCurtis.Dunham@arm.com        warn("Running a checkpoint with incompatible version tags is not "
56211077SCurtis.Dunham@arm.com             "supported. While it might work, you may experience incorrect "
56311077SCurtis.Dunham@arm.com             "behavior or crashes.\n");
56411077SCurtis.Dunham@arm.com        warn("**********************************************************\n");
56511077SCurtis.Dunham@arm.com     }
5662SN/A}
5672SN/A
5685739Snate@binkert.orgSerializable::Serializable()
5695739Snate@binkert.org{
5705739Snate@binkert.org}
5715739Snate@binkert.org
5725739Snate@binkert.orgSerializable::~Serializable()
5735739Snate@binkert.org{
5745739Snate@binkert.org}
5755739Snate@binkert.org
5765739Snate@binkert.orgvoid
57710905Sandreas.sandberg@arm.comSerializable::serializeSection(CheckpointOut &cp, const char *name) const
5785739Snate@binkert.org{
57910905Sandreas.sandberg@arm.com    Serializable::ScopedCheckpointSection sec(cp, name);
58010905Sandreas.sandberg@arm.com    serialize(cp);
5815739Snate@binkert.org}
5825739Snate@binkert.org
5835739Snate@binkert.orgvoid
58410905Sandreas.sandberg@arm.comSerializable::serializeSectionOld(CheckpointOut &cp, const char *name)
5855739Snate@binkert.org{
58610905Sandreas.sandberg@arm.com    Serializable::ScopedCheckpointSection sec(cp, name);
58710905Sandreas.sandberg@arm.com    serializeOld(cp);
58810905Sandreas.sandberg@arm.com}
58910905Sandreas.sandberg@arm.com
59010905Sandreas.sandberg@arm.comvoid
59110905Sandreas.sandberg@arm.comSerializable::unserializeSection(CheckpointIn &cp, const char *name)
59210905Sandreas.sandberg@arm.com{
59310905Sandreas.sandberg@arm.com    Serializable::ScopedCheckpointSection sec(cp, name);
59410905Sandreas.sandberg@arm.com    unserialize(cp);
5955739Snate@binkert.org}
5965739Snate@binkert.org
5972SN/Avoid
5986225Snate@binkert.orgSerializable::serializeAll(const string &cpt_dir)
5992SN/A{
60010905Sandreas.sandberg@arm.com    string dir = CheckpointIn::setDir(cpt_dir);
601363SN/A    if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
602449SN/A            fatal("couldn't mkdir %s\n", dir);
603363SN/A
60410905Sandreas.sandberg@arm.com    string cpt_file = dir + CheckpointIn::baseFilename;
605395SN/A    ofstream outstream(cpt_file.c_str());
6062SN/A    time_t t = time(NULL);
6075581Ssaidi@eecs.umich.edu    if (!outstream.is_open())
6085581Ssaidi@eecs.umich.edu        fatal("Unable to open file %s for writing\n", cpt_file.c_str());
6096818SLisa.Hsu@amd.com    outstream << "## checkpoint generated: " << ctime(&t);
6102SN/A
61110905Sandreas.sandberg@arm.com    globals.serializeSection(outstream, "Globals");
61210905Sandreas.sandberg@arm.com
613395SN/A    SimObject::serializeAll(outstream);
614395SN/A}
6152SN/A
6162797Sktlim@umich.eduvoid
61710905Sandreas.sandberg@arm.comSerializable::unserializeGlobals(CheckpointIn &cp)
618395SN/A{
61910905Sandreas.sandberg@arm.com    globals.unserializeSection(cp, "Globals");
62010905Sandreas.sandberg@arm.com
62111072Sandreas.sandberg@arm.com    for (uint32_t i = 0; i < numMainEventQueues; ++i)
62210905Sandreas.sandberg@arm.com        mainEventQueue[i]->setCurTick(globals.unserializedCurTick);
62310905Sandreas.sandberg@arm.com}
62410905Sandreas.sandberg@arm.com
62510905Sandreas.sandberg@arm.comSerializable::ScopedCheckpointSection::~ScopedCheckpointSection()
62610905Sandreas.sandberg@arm.com{
62710905Sandreas.sandberg@arm.com    assert(!path.empty());
62810905Sandreas.sandberg@arm.com    DPRINTF(Checkpoint, "Popping: %s\n", path.top());
62910905Sandreas.sandberg@arm.com    path.pop();
63010905Sandreas.sandberg@arm.com}
63110905Sandreas.sandberg@arm.com
63210905Sandreas.sandberg@arm.comvoid
63310905Sandreas.sandberg@arm.comSerializable::ScopedCheckpointSection::pushName(const char *obj_name)
63410905Sandreas.sandberg@arm.com{
63510905Sandreas.sandberg@arm.com    if (path.empty()) {
63610905Sandreas.sandberg@arm.com        path.push(obj_name);
63710905Sandreas.sandberg@arm.com    } else {
63810905Sandreas.sandberg@arm.com        path.push(csprintf("%s.%s", path.top(), obj_name));
63910905Sandreas.sandberg@arm.com    }
64010905Sandreas.sandberg@arm.com    DPRINTF(Checkpoint, "ScopedCheckpointSection::pushName: %s\n", obj_name);
64110905Sandreas.sandberg@arm.com}
64210905Sandreas.sandberg@arm.com
64310905Sandreas.sandberg@arm.comvoid
64410905Sandreas.sandberg@arm.comSerializable::ScopedCheckpointSection::nameOut(CheckpointOut &cp)
64510905Sandreas.sandberg@arm.com{
64610905Sandreas.sandberg@arm.com    DPRINTF(Checkpoint, "ScopedCheckpointSection::nameOut: %s\n",
64710905Sandreas.sandberg@arm.com            Serializable::currentSection());
64810905Sandreas.sandberg@arm.com    cp << "\n[" << Serializable::currentSection() << "]\n";
649395SN/A}
6502SN/A
6512SN/Avoid
6526225Snate@binkert.orgdebug_serialize(const string &cpt_dir)
6532SN/A{
6542868Sktlim@umich.edu    Serializable::serializeAll(cpt_dir);
6552SN/A}
6562SN/A
65710905Sandreas.sandberg@arm.comconst std::string &
65810905Sandreas.sandberg@arm.comSerializable::currentSection()
65910905Sandreas.sandberg@arm.com{
66010905Sandreas.sandberg@arm.com    assert(!path.empty());
66110905Sandreas.sandberg@arm.com
66210905Sandreas.sandberg@arm.com    return path.top();
66310905Sandreas.sandberg@arm.com}
664237SN/A
66510905Sandreas.sandberg@arm.comconst char *CheckpointIn::baseFilename = "m5.cpt";
6667491Ssteve.reinhardt@amd.com
66710905Sandreas.sandberg@arm.comstring CheckpointIn::currentDirectory;
6687491Ssteve.reinhardt@amd.com
6697491Ssteve.reinhardt@amd.comstring
67010905Sandreas.sandberg@arm.comCheckpointIn::setDir(const string &name)
6717491Ssteve.reinhardt@amd.com{
6727823Ssteve.reinhardt@amd.com    // use csprintf to insert curTick() into directory name if it
6737491Ssteve.reinhardt@amd.com    // appears to have a format placeholder in it.
6747491Ssteve.reinhardt@amd.com    currentDirectory = (name.find("%") != string::npos) ?
6757823Ssteve.reinhardt@amd.com        csprintf(name, curTick()) : name;
6767491Ssteve.reinhardt@amd.com    if (currentDirectory[currentDirectory.size() - 1] != '/')
6777491Ssteve.reinhardt@amd.com        currentDirectory += "/";
6787491Ssteve.reinhardt@amd.com    return currentDirectory;
6797491Ssteve.reinhardt@amd.com}
6807491Ssteve.reinhardt@amd.com
6817491Ssteve.reinhardt@amd.comstring
68210905Sandreas.sandberg@arm.comCheckpointIn::dir()
6837491Ssteve.reinhardt@amd.com{
6847491Ssteve.reinhardt@amd.com    return currentDirectory;
6857491Ssteve.reinhardt@amd.com}
6867491Ssteve.reinhardt@amd.com
6877491Ssteve.reinhardt@amd.com
68810905Sandreas.sandberg@arm.comCheckpointIn::CheckpointIn(const string &cpt_dir, SimObjectResolver &resolver)
68910453SAndrew.Bardsley@arm.com    : db(new IniFile), objNameResolver(resolver), cptDir(setDir(cpt_dir))
690237SN/A{
69110905Sandreas.sandberg@arm.com    string filename = cptDir + "/" + CheckpointIn::baseFilename;
692237SN/A    if (!db->load(filename)) {
693237SN/A        fatal("Can't load checkpoint file '%s'\n", filename);
694237SN/A    }
695237SN/A}
696237SN/A
69710905Sandreas.sandberg@arm.comCheckpointIn::~CheckpointIn()
6989086Sandreas.hansson@arm.com{
6999086Sandreas.hansson@arm.com    delete db;
7009086Sandreas.hansson@arm.com}
701237SN/A
702237SN/Abool
70310905Sandreas.sandberg@arm.comCheckpointIn::find(const string &section, const string &entry, string &value)
704237SN/A{
705237SN/A    return db->find(section, entry, value);
706237SN/A}
707237SN/A
708237SN/A
709237SN/Abool
71010905Sandreas.sandberg@arm.comCheckpointIn::findObj(const string &section, const string &entry,
7114000Ssaidi@eecs.umich.edu                    SimObject *&value)
712237SN/A{
713237SN/A    string path;
714237SN/A
715237SN/A    if (!db->find(section, entry, path))
716237SN/A        return false;
717237SN/A
71810453SAndrew.Bardsley@arm.com    value = objNameResolver.resolveSimObject(path);
7194000Ssaidi@eecs.umich.edu    return true;
720237SN/A}
721304SN/A
722304SN/A
723304SN/Abool
72410905Sandreas.sandberg@arm.comCheckpointIn::sectionExists(const string &section)
725304SN/A{
726304SN/A    return db->sectionExists(section);
727304SN/A}
728