serialize.cc revision 11793
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
4811793Sbrandon.potter@amd.com#include "sim/serialize.hh"
4911793Sbrandon.potter@amd.com
508229Snate@binkert.org#include <sys/stat.h>
512SN/A#include <sys/time.h>
52363SN/A#include <sys/types.h>
532SN/A
548229Snate@binkert.org#include <cerrno>
552SN/A#include <fstream>
562SN/A#include <list>
572SN/A#include <string>
582SN/A#include <vector>
592SN/A
6010907Sandreas.sandberg@arm.com#include "base/framebuffer.hh"
61363SN/A#include "base/inifile.hh"
6256SN/A#include "base/misc.hh"
631388SN/A#include "base/output.hh"
64217SN/A#include "base/str.hh"
65363SN/A#include "base/trace.hh"
6610905Sandreas.sandberg@arm.com#include "debug/Checkpoint.hh"
6756SN/A#include "sim/eventq.hh"
6856SN/A#include "sim/sim_events.hh"
691638SN/A#include "sim/sim_exit.hh"
7056SN/A#include "sim/sim_object.hh"
712SN/A
722356SN/A// For stat reset hack
732356SN/A#include "sim/stat_control.hh"
742356SN/A
752SN/Ausing namespace std;
762SN/A
774762Snate@binkert.org//
784762Snate@binkert.org// The base implementations use to_number for parsing and '<<' for
794762Snate@binkert.org// displaying, suitable for integer types.
804762Snate@binkert.org//
814762Snate@binkert.orgtemplate <class T>
824762Snate@binkert.orgbool
834762Snate@binkert.orgparseParam(const string &s, T &value)
844762Snate@binkert.org{
854762Snate@binkert.org    return to_number(s, value);
864762Snate@binkert.org}
874762Snate@binkert.org
884762Snate@binkert.orgtemplate <class T>
894762Snate@binkert.orgvoid
9010905Sandreas.sandberg@arm.comshowParam(CheckpointOut &os, const T &value)
914762Snate@binkert.org{
924762Snate@binkert.org    os << value;
934762Snate@binkert.org}
944762Snate@binkert.org
954762Snate@binkert.org//
964762Snate@binkert.org// Template specializations:
974762Snate@binkert.org// - char (8-bit integer)
984762Snate@binkert.org// - floating-point types
994762Snate@binkert.org// - bool
1004762Snate@binkert.org// - string
1014762Snate@binkert.org//
1024762Snate@binkert.org
1034762Snate@binkert.org// Treat 8-bit ints (chars) as ints on output, not as chars
1044762Snate@binkert.orgtemplate <>
1054762Snate@binkert.orgvoid
10610905Sandreas.sandberg@arm.comshowParam(CheckpointOut &os, const char &value)
1077494Ssteve.reinhardt@amd.com{
1087494Ssteve.reinhardt@amd.com    os << (int)value;
1097494Ssteve.reinhardt@amd.com}
1107494Ssteve.reinhardt@amd.com
1117494Ssteve.reinhardt@amd.com
1127494Ssteve.reinhardt@amd.comtemplate <>
1137494Ssteve.reinhardt@amd.comvoid
11410905Sandreas.sandberg@arm.comshowParam(CheckpointOut &os, const signed char &value)
1154762Snate@binkert.org{
1164762Snate@binkert.org    os << (int)value;
1174762Snate@binkert.org}
1184762Snate@binkert.org
1194762Snate@binkert.org
1204762Snate@binkert.orgtemplate <>
1214762Snate@binkert.orgvoid
12210905Sandreas.sandberg@arm.comshowParam(CheckpointOut &os, const unsigned char &value)
1234762Snate@binkert.org{
1244762Snate@binkert.org    os << (unsigned int)value;
1254762Snate@binkert.org}
1264762Snate@binkert.org
1274762Snate@binkert.org
1284762Snate@binkert.orgtemplate <>
1294762Snate@binkert.orgbool
1304762Snate@binkert.orgparseParam(const string &s, float &value)
1314762Snate@binkert.org{
13210386Sandreas.hansson@arm.com    return to_number(s, value);
1334762Snate@binkert.org}
1344762Snate@binkert.org
1354762Snate@binkert.orgtemplate <>
1364762Snate@binkert.orgbool
1374762Snate@binkert.orgparseParam(const string &s, double &value)
1384762Snate@binkert.org{
13910386Sandreas.hansson@arm.com    return to_number(s, value);
1404762Snate@binkert.org}
1414762Snate@binkert.org
1424762Snate@binkert.orgtemplate <>
1434762Snate@binkert.orgbool
1444762Snate@binkert.orgparseParam(const string &s, bool &value)
1454762Snate@binkert.org{
14610386Sandreas.hansson@arm.com    return to_bool(s, value);
1474762Snate@binkert.org}
1484762Snate@binkert.org
1494762Snate@binkert.org// Display bools as strings
1504762Snate@binkert.orgtemplate <>
1514762Snate@binkert.orgvoid
15210905Sandreas.sandberg@arm.comshowParam(CheckpointOut &os, const bool &value)
1534762Snate@binkert.org{
1544762Snate@binkert.org    os << (value ? "true" : "false");
1554762Snate@binkert.org}
1564762Snate@binkert.org
1574762Snate@binkert.org
1584762Snate@binkert.org// String requires no processing to speak of
1594762Snate@binkert.orgtemplate <>
1604762Snate@binkert.orgbool
1614762Snate@binkert.orgparseParam(const string &s, string &value)
1624762Snate@binkert.org{
1634762Snate@binkert.org    value = s;
1644762Snate@binkert.org    return true;
1654762Snate@binkert.org}
1664762Snate@binkert.org
1672287SN/Aint Serializable::ckptMaxCount = 0;
1682287SN/Aint Serializable::ckptCount = 0;
1692287SN/Aint Serializable::ckptPrevCount = -1;
17010905Sandreas.sandberg@arm.comstd::stack<std::string> Serializable::path;
1712SN/A
172217SN/Atemplate <class T>
1732SN/Avoid
17410905Sandreas.sandberg@arm.comparamOut(CheckpointOut &os, const string &name, const T &param)
1752SN/A{
176217SN/A    os << name << "=";
177217SN/A    showParam(os, param);
178217SN/A    os << "\n";
1792SN/A}
1802SN/A
1814841Ssaidi@eecs.umich.edutemplate <class T>
1824841Ssaidi@eecs.umich.eduvoid
18310905Sandreas.sandberg@arm.comarrayParamOut(CheckpointOut &os, const string &name, const vector<T> &param)
1844841Ssaidi@eecs.umich.edu{
1856227Snate@binkert.org    typename vector<T>::size_type size = param.size();
1864841Ssaidi@eecs.umich.edu    os << name << "=";
1874841Ssaidi@eecs.umich.edu    if (size > 0)
1884841Ssaidi@eecs.umich.edu        showParam(os, param[0]);
1896227Snate@binkert.org    for (typename vector<T>::size_type i = 1; i < size; ++i) {
1904841Ssaidi@eecs.umich.edu        os << " ";
1914841Ssaidi@eecs.umich.edu        showParam(os, param[i]);
1924841Ssaidi@eecs.umich.edu    }
1934841Ssaidi@eecs.umich.edu    os << "\n";
1944841Ssaidi@eecs.umich.edu}
1954841Ssaidi@eecs.umich.edu
1967948SAli.Saidi@ARM.comtemplate <class T>
1977948SAli.Saidi@ARM.comvoid
19810905Sandreas.sandberg@arm.comarrayParamOut(CheckpointOut &os, const string &name, const list<T> &param)
1997948SAli.Saidi@ARM.com{
2007948SAli.Saidi@ARM.com    typename list<T>::const_iterator it = param.begin();
2017948SAli.Saidi@ARM.com
2027948SAli.Saidi@ARM.com    os << name << "=";
2037948SAli.Saidi@ARM.com    if (param.size() > 0)
2047948SAli.Saidi@ARM.com        showParam(os, *it);
2057948SAli.Saidi@ARM.com    it++;
2067948SAli.Saidi@ARM.com    while (it != param.end()) {
2077948SAli.Saidi@ARM.com        os << " ";
2087948SAli.Saidi@ARM.com        showParam(os, *it);
2097948SAli.Saidi@ARM.com        it++;
2107948SAli.Saidi@ARM.com    }
2117948SAli.Saidi@ARM.com    os << "\n";
2127948SAli.Saidi@ARM.com}
213217SN/A
214217SN/Atemplate <class T>
215217SN/Avoid
21611076SCurtis.Dunham@arm.comarrayParamOut(CheckpointOut &os, const string &name, const set<T> &param)
21711076SCurtis.Dunham@arm.com{
21811076SCurtis.Dunham@arm.com    typename set<T>::const_iterator it = param.begin();
21911076SCurtis.Dunham@arm.com
22011076SCurtis.Dunham@arm.com    os << name << "=";
22111076SCurtis.Dunham@arm.com    if (param.size() > 0)
22211076SCurtis.Dunham@arm.com        showParam(os, *it);
22311076SCurtis.Dunham@arm.com    it++;
22411076SCurtis.Dunham@arm.com    while (it != param.end()) {
22511076SCurtis.Dunham@arm.com        os << " ";
22611076SCurtis.Dunham@arm.com        showParam(os, *it);
22711076SCurtis.Dunham@arm.com        it++;
22811076SCurtis.Dunham@arm.com    }
22911076SCurtis.Dunham@arm.com    os << "\n";
23011076SCurtis.Dunham@arm.com}
23111076SCurtis.Dunham@arm.com
23211076SCurtis.Dunham@arm.comtemplate <class T>
23311076SCurtis.Dunham@arm.comvoid
23410905Sandreas.sandberg@arm.comparamIn(CheckpointIn &cp, const string &name, T &param)
2352SN/A{
23610905Sandreas.sandberg@arm.com    const string &section(Serializable::currentSection());
2376225Snate@binkert.org    string str;
23810905Sandreas.sandberg@arm.com    if (!cp.find(section, name, str) || !parseParam(str, param)) {
239217SN/A        fatal("Can't unserialize '%s:%s'\n", section, name);
240217SN/A    }
2412SN/A}
2422SN/A
2436820SLisa.Hsu@amd.comtemplate <class T>
2446820SLisa.Hsu@amd.combool
24511075SCurtis.Dunham@arm.comoptParamIn(CheckpointIn &cp, const string &name, T &param, bool warn)
2466820SLisa.Hsu@amd.com{
24710905Sandreas.sandberg@arm.com    const string &section(Serializable::currentSection());
2486820SLisa.Hsu@amd.com    string str;
24910905Sandreas.sandberg@arm.com    if (!cp.find(section, name, str) || !parseParam(str, param)) {
25011075SCurtis.Dunham@arm.com        if (warn)
25111075SCurtis.Dunham@arm.com            warn("optional parameter %s:%s not present\n", section, name);
2526820SLisa.Hsu@amd.com        return false;
2536820SLisa.Hsu@amd.com    } else {
2546820SLisa.Hsu@amd.com        return true;
2556820SLisa.Hsu@amd.com    }
2566820SLisa.Hsu@amd.com}
257217SN/A
258217SN/Atemplate <class T>
259217SN/Avoid
26010905Sandreas.sandberg@arm.comarrayParamOut(CheckpointOut &os, const string &name,
26110905Sandreas.sandberg@arm.com              const T *param, unsigned size)
262217SN/A{
263217SN/A    os << name << "=";
264217SN/A    if (size > 0)
265217SN/A        showParam(os, param[0]);
2666227Snate@binkert.org    for (unsigned i = 1; i < size; ++i) {
267217SN/A        os << " ";
268217SN/A        showParam(os, param[i]);
269217SN/A    }
270217SN/A    os << "\n";
271217SN/A}
272217SN/A
273217SN/A
274217SN/Atemplate <class T>
275217SN/Avoid
27610905Sandreas.sandberg@arm.comarrayParamIn(CheckpointIn &cp, const string &name, T *param, unsigned size)
277217SN/A{
27810905Sandreas.sandberg@arm.com    const string &section(Serializable::currentSection());
2796225Snate@binkert.org    string str;
28010905Sandreas.sandberg@arm.com    if (!cp.find(section, name, str)) {
281217SN/A        fatal("Can't unserialize '%s:%s'\n", section, name);
282217SN/A    }
283217SN/A
284217SN/A    // code below stolen from VectorParam<T>::parse().
285217SN/A    // it would be nice to unify these somehow...
286217SN/A
287217SN/A    vector<string> tokens;
288217SN/A
289217SN/A    tokenize(tokens, str, ' ');
290217SN/A
291217SN/A    // Need this if we were doing a vector
292217SN/A    // value.resize(tokens.size());
293217SN/A
294217SN/A    if (tokens.size() != size) {
295217SN/A        fatal("Array size mismatch on %s:%s'\n", section, name);
296217SN/A    }
297217SN/A
2986227Snate@binkert.org    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
299217SN/A        // need to parse into local variable to handle vector<bool>,
300217SN/A        // for which operator[] returns a special reference class
301217SN/A        // that's not the same as 'bool&', (since it's a packed
302217SN/A        // vector)
30310905Sandreas.sandberg@arm.com        T scalar_value;
304217SN/A        if (!parseParam(tokens[i], scalar_value)) {
305217SN/A            string err("could not parse \"");
306217SN/A
307217SN/A            err += str;
308217SN/A            err += "\"";
309217SN/A
310217SN/A            fatal(err);
311217SN/A        }
312217SN/A
313217SN/A        // assign parsed value to vector
314217SN/A        param[i] = scalar_value;
315217SN/A    }
316217SN/A}
317217SN/A
3184841Ssaidi@eecs.umich.edutemplate <class T>
3194841Ssaidi@eecs.umich.eduvoid
32010905Sandreas.sandberg@arm.comarrayParamIn(CheckpointIn &cp, const string &name, vector<T> &param)
3214841Ssaidi@eecs.umich.edu{
32210905Sandreas.sandberg@arm.com    const string &section(Serializable::currentSection());
3236225Snate@binkert.org    string str;
32410905Sandreas.sandberg@arm.com    if (!cp.find(section, name, str)) {
3254841Ssaidi@eecs.umich.edu        fatal("Can't unserialize '%s:%s'\n", section, name);
3264841Ssaidi@eecs.umich.edu    }
3274841Ssaidi@eecs.umich.edu
3284841Ssaidi@eecs.umich.edu    // code below stolen from VectorParam<T>::parse().
3294841Ssaidi@eecs.umich.edu    // it would be nice to unify these somehow...
3304841Ssaidi@eecs.umich.edu
3314841Ssaidi@eecs.umich.edu    vector<string> tokens;
3324841Ssaidi@eecs.umich.edu
3334841Ssaidi@eecs.umich.edu    tokenize(tokens, str, ' ');
3344841Ssaidi@eecs.umich.edu
3354841Ssaidi@eecs.umich.edu    // Need this if we were doing a vector
3364841Ssaidi@eecs.umich.edu    // value.resize(tokens.size());
3374841Ssaidi@eecs.umich.edu
3384841Ssaidi@eecs.umich.edu    param.resize(tokens.size());
3394841Ssaidi@eecs.umich.edu
3406227Snate@binkert.org    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
3414841Ssaidi@eecs.umich.edu        // need to parse into local variable to handle vector<bool>,
3424841Ssaidi@eecs.umich.edu        // for which operator[] returns a special reference class
3434841Ssaidi@eecs.umich.edu        // that's not the same as 'bool&', (since it's a packed
3444841Ssaidi@eecs.umich.edu        // vector)
34510905Sandreas.sandberg@arm.com        T scalar_value;
3464841Ssaidi@eecs.umich.edu        if (!parseParam(tokens[i], scalar_value)) {
3474841Ssaidi@eecs.umich.edu            string err("could not parse \"");
3484841Ssaidi@eecs.umich.edu
3494841Ssaidi@eecs.umich.edu            err += str;
3504841Ssaidi@eecs.umich.edu            err += "\"";
3514841Ssaidi@eecs.umich.edu
3524841Ssaidi@eecs.umich.edu            fatal(err);
3534841Ssaidi@eecs.umich.edu        }
3544841Ssaidi@eecs.umich.edu
3554841Ssaidi@eecs.umich.edu        // assign parsed value to vector
3564841Ssaidi@eecs.umich.edu        param[i] = scalar_value;
3574841Ssaidi@eecs.umich.edu    }
3584841Ssaidi@eecs.umich.edu}
3594841Ssaidi@eecs.umich.edu
3607948SAli.Saidi@ARM.comtemplate <class T>
3617948SAli.Saidi@ARM.comvoid
36210905Sandreas.sandberg@arm.comarrayParamIn(CheckpointIn &cp, const string &name, list<T> &param)
3637948SAli.Saidi@ARM.com{
36410905Sandreas.sandberg@arm.com    const string &section(Serializable::currentSection());
3657948SAli.Saidi@ARM.com    string str;
36610905Sandreas.sandberg@arm.com    if (!cp.find(section, name, str)) {
3677948SAli.Saidi@ARM.com        fatal("Can't unserialize '%s:%s'\n", section, name);
3687948SAli.Saidi@ARM.com    }
3697948SAli.Saidi@ARM.com    param.clear();
3707948SAli.Saidi@ARM.com
3717948SAli.Saidi@ARM.com    vector<string> tokens;
3727948SAli.Saidi@ARM.com    tokenize(tokens, str, ' ');
3737948SAli.Saidi@ARM.com
3747948SAli.Saidi@ARM.com    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
37510905Sandreas.sandberg@arm.com        T scalar_value;
3767948SAli.Saidi@ARM.com        if (!parseParam(tokens[i], scalar_value)) {
3777948SAli.Saidi@ARM.com            string err("could not parse \"");
3787948SAli.Saidi@ARM.com
3797948SAli.Saidi@ARM.com            err += str;
3807948SAli.Saidi@ARM.com            err += "\"";
3817948SAli.Saidi@ARM.com
3827948SAli.Saidi@ARM.com            fatal(err);
3837948SAli.Saidi@ARM.com        }
3847948SAli.Saidi@ARM.com
3857948SAli.Saidi@ARM.com        // assign parsed value to vector
3867948SAli.Saidi@ARM.com        param.push_back(scalar_value);
3877948SAli.Saidi@ARM.com    }
3887948SAli.Saidi@ARM.com}
3897948SAli.Saidi@ARM.com
39011076SCurtis.Dunham@arm.comtemplate <class T>
39111076SCurtis.Dunham@arm.comvoid
39211076SCurtis.Dunham@arm.comarrayParamIn(CheckpointIn &cp, const string &name, set<T> &param)
39311076SCurtis.Dunham@arm.com{
39411076SCurtis.Dunham@arm.com    const string &section(Serializable::currentSection());
39511076SCurtis.Dunham@arm.com    string str;
39611076SCurtis.Dunham@arm.com    if (!cp.find(section, name, str)) {
39711076SCurtis.Dunham@arm.com        fatal("Can't unserialize '%s:%s'\n", section, name);
39811076SCurtis.Dunham@arm.com    }
39911076SCurtis.Dunham@arm.com    param.clear();
40011076SCurtis.Dunham@arm.com
40111076SCurtis.Dunham@arm.com    vector<string> tokens;
40211076SCurtis.Dunham@arm.com    tokenize(tokens, str, ' ');
40311076SCurtis.Dunham@arm.com
40411076SCurtis.Dunham@arm.com    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
40511076SCurtis.Dunham@arm.com        T scalar_value;
40611076SCurtis.Dunham@arm.com        if (!parseParam(tokens[i], scalar_value)) {
40711076SCurtis.Dunham@arm.com            string err("could not parse \"");
40811076SCurtis.Dunham@arm.com
40911076SCurtis.Dunham@arm.com            err += str;
41011076SCurtis.Dunham@arm.com            err += "\"";
41111076SCurtis.Dunham@arm.com
41211076SCurtis.Dunham@arm.com            fatal(err);
41311076SCurtis.Dunham@arm.com        }
41411076SCurtis.Dunham@arm.com
41511076SCurtis.Dunham@arm.com        // assign parsed value to vector
41611076SCurtis.Dunham@arm.com        param.insert(scalar_value);
41711076SCurtis.Dunham@arm.com    }
41811076SCurtis.Dunham@arm.com}
41911076SCurtis.Dunham@arm.com
4207948SAli.Saidi@ARM.com
421237SN/Avoid
42210905Sandreas.sandberg@arm.comobjParamIn(CheckpointIn &cp, const string &name, SimObject * &param)
423237SN/A{
42410905Sandreas.sandberg@arm.com    const string &section(Serializable::currentSection());
42510905Sandreas.sandberg@arm.com    if (!cp.findObj(section, name, param)) {
426237SN/A        fatal("Can't unserialize '%s:%s'\n", section, name);
427237SN/A    }
428237SN/A}
429237SN/A
430237SN/A
4315543Ssaidi@eecs.umich.edu#define INSTANTIATE_PARAM_TEMPLATES(type)                               \
43210905Sandreas.sandberg@arm.com    template void                                                       \
43310905Sandreas.sandberg@arm.com    paramOut(CheckpointOut &os, const string &name, type const &param); \
43410905Sandreas.sandberg@arm.com    template void                                                       \
43510905Sandreas.sandberg@arm.com    paramIn(CheckpointIn &cp, const string &name, type & param);        \
43610905Sandreas.sandberg@arm.com    template bool                                                       \
43711075SCurtis.Dunham@arm.com    optParamIn(CheckpointIn &cp, const string &name, type & param,      \
43811075SCurtis.Dunham@arm.com               bool warn);                                              \
43910905Sandreas.sandberg@arm.com    template void                                                       \
44010905Sandreas.sandberg@arm.com    arrayParamOut(CheckpointOut &os, const string &name,                \
44110905Sandreas.sandberg@arm.com                  type const *param, unsigned size);                    \
44210905Sandreas.sandberg@arm.com    template void                                                       \
44310905Sandreas.sandberg@arm.com    arrayParamIn(CheckpointIn &cp, const string &name,                  \
44410905Sandreas.sandberg@arm.com                 type *param, unsigned size);                           \
44510905Sandreas.sandberg@arm.com    template void                                                       \
44610905Sandreas.sandberg@arm.com    arrayParamOut(CheckpointOut &os, const string &name,                \
44710905Sandreas.sandberg@arm.com                  const vector<type> &param);                           \
44810905Sandreas.sandberg@arm.com    template void                                                       \
44910905Sandreas.sandberg@arm.com    arrayParamIn(CheckpointIn &cp, const string &name,                  \
45010905Sandreas.sandberg@arm.com                 vector<type> &param);                                  \
45110905Sandreas.sandberg@arm.com    template void                                                       \
45210905Sandreas.sandberg@arm.com    arrayParamOut(CheckpointOut &os, const string &name,                \
45310905Sandreas.sandberg@arm.com                  const list<type> &param);                             \
45410905Sandreas.sandberg@arm.com    template void                                                       \
45510905Sandreas.sandberg@arm.com    arrayParamIn(CheckpointIn &cp, const string &name,                  \
45610905Sandreas.sandberg@arm.com                 list<type> &param);
457217SN/A
4587494Ssteve.reinhardt@amd.comINSTANTIATE_PARAM_TEMPLATES(char)
4591642SN/AINSTANTIATE_PARAM_TEMPLATES(signed char)
4601642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned char)
4611642SN/AINSTANTIATE_PARAM_TEMPLATES(signed short)
4621642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned short)
4631642SN/AINSTANTIATE_PARAM_TEMPLATES(signed int)
4641642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned int)
4651642SN/AINSTANTIATE_PARAM_TEMPLATES(signed long)
4661642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned long)
4671642SN/AINSTANTIATE_PARAM_TEMPLATES(signed long long)
4681642SN/AINSTANTIATE_PARAM_TEMPLATES(unsigned long long)
469219SN/AINSTANTIATE_PARAM_TEMPLATES(bool)
4705992Snate@binkert.orgINSTANTIATE_PARAM_TEMPLATES(float)
4715992Snate@binkert.orgINSTANTIATE_PARAM_TEMPLATES(double)
472217SN/AINSTANTIATE_PARAM_TEMPLATES(string)
47310907Sandreas.sandberg@arm.comINSTANTIATE_PARAM_TEMPLATES(Pixel)
474217SN/A
47511076SCurtis.Dunham@arm.com// set is only used with strings and furthermore doesn't agree with Pixel
47611076SCurtis.Dunham@arm.comtemplate void
47711076SCurtis.Dunham@arm.comarrayParamOut(CheckpointOut &, const string &, const set<string> &);
47811076SCurtis.Dunham@arm.comtemplate void
47911076SCurtis.Dunham@arm.comarrayParamIn(CheckpointIn &, const string &, set<string> &);
480217SN/A
481395SN/A/////////////////////////////
482395SN/A
483395SN/A/// Container for serializing global variables (not associated with
484395SN/A/// any serialized object).
485395SN/Aclass Globals : public Serializable
4862SN/A{
487395SN/A  public:
48810905Sandreas.sandberg@arm.com    Globals()
48910905Sandreas.sandberg@arm.com        : unserializedCurTick(0) {}
49010905Sandreas.sandberg@arm.com
49111168Sandreas.hansson@arm.com    void serialize(CheckpointOut &cp) const override;
49211168Sandreas.hansson@arm.com    void unserialize(CheckpointIn &cp) override;
49310905Sandreas.sandberg@arm.com
49410905Sandreas.sandberg@arm.com    Tick unserializedCurTick;
495395SN/A};
4962SN/A
497395SN/A/// The one and only instance of the Globals class.
498395SN/AGlobals globals;
4992SN/A
50011077SCurtis.Dunham@arm.com/// The version tags for this build of the simulator, to be stored in the
50111077SCurtis.Dunham@arm.com/// Globals section during serialization and compared upon unserialization.
50211077SCurtis.Dunham@arm.comextern std::set<std::string> version_tags;
50311077SCurtis.Dunham@arm.com
50410905Sandreas.sandberg@arm.comvoid
50510905Sandreas.sandberg@arm.comGlobals::serialize(CheckpointOut &cp) const
5062SN/A{
50710905Sandreas.sandberg@arm.com    paramOut(cp, "curTick", curTick());
50811077SCurtis.Dunham@arm.com    SERIALIZE_CONTAINER(version_tags);
5092SN/A}
5102SN/A
5112SN/Avoid
51210905Sandreas.sandberg@arm.comGlobals::unserialize(CheckpointIn &cp)
5132SN/A{
51410905Sandreas.sandberg@arm.com    paramIn(cp, "curTick", unserializedCurTick);
51511077SCurtis.Dunham@arm.com
51611077SCurtis.Dunham@arm.com    const std::string &section(Serializable::currentSection());
51711077SCurtis.Dunham@arm.com    std::string str;
51811077SCurtis.Dunham@arm.com    if (!cp.find(section, "version_tags", str)) {
51911077SCurtis.Dunham@arm.com        warn("**********************************************************\n");
52011077SCurtis.Dunham@arm.com        warn("!!!! Checkpoint uses an old versioning scheme.        !!!!\n");
52111077SCurtis.Dunham@arm.com        warn("Run the checkpoint upgrader (util/cpt_upgrader.py) on your "
52211077SCurtis.Dunham@arm.com             "checkpoint\n");
52311077SCurtis.Dunham@arm.com        warn("**********************************************************\n");
52411077SCurtis.Dunham@arm.com        return;
52511077SCurtis.Dunham@arm.com    }
52611077SCurtis.Dunham@arm.com
52711077SCurtis.Dunham@arm.com    std::set<std::string> cpt_tags;
52811077SCurtis.Dunham@arm.com    arrayParamIn(cp, "version_tags", cpt_tags); // UNSERIALIZE_CONTAINER
52911077SCurtis.Dunham@arm.com
53011077SCurtis.Dunham@arm.com    bool err = false;
53111077SCurtis.Dunham@arm.com    for (const auto& t : version_tags) {
53211077SCurtis.Dunham@arm.com        if (cpt_tags.find(t) == cpt_tags.end()) {
53311077SCurtis.Dunham@arm.com            // checkpoint is missing tag that this binary has
53411077SCurtis.Dunham@arm.com            if (!err) {
53511077SCurtis.Dunham@arm.com                warn("*****************************************************\n");
53611077SCurtis.Dunham@arm.com                warn("!!!! Checkpoint is missing the following version tags:\n");
53711077SCurtis.Dunham@arm.com                err = true;
53811077SCurtis.Dunham@arm.com            }
53911077SCurtis.Dunham@arm.com            warn("  %s\n", t);
54011077SCurtis.Dunham@arm.com        }
54111077SCurtis.Dunham@arm.com    }
54211077SCurtis.Dunham@arm.com    if (err) {
54311077SCurtis.Dunham@arm.com        warn("You might experience some issues when restoring and should run "
54411077SCurtis.Dunham@arm.com             "the checkpoint upgrader (util/cpt_upgrader.py) on your "
54511077SCurtis.Dunham@arm.com             "checkpoint\n");
54611077SCurtis.Dunham@arm.com        warn("**********************************************************\n");
54711077SCurtis.Dunham@arm.com    }
54811077SCurtis.Dunham@arm.com
54911077SCurtis.Dunham@arm.com    err = false;
55011077SCurtis.Dunham@arm.com    for (const auto& t : cpt_tags) {
55111077SCurtis.Dunham@arm.com        if (version_tags.find(t) == version_tags.end()) {
55211077SCurtis.Dunham@arm.com            // gem5 binary is missing tag that this checkpoint has
55311077SCurtis.Dunham@arm.com            if (!err) {
55411077SCurtis.Dunham@arm.com                warn("*****************************************************\n");
55511077SCurtis.Dunham@arm.com                warn("!!!! gem5 is missing the following version tags:\n");
55611077SCurtis.Dunham@arm.com                err = true;
55711077SCurtis.Dunham@arm.com            }
55811077SCurtis.Dunham@arm.com            warn("  %s\n", t);
55911077SCurtis.Dunham@arm.com        }
56011077SCurtis.Dunham@arm.com    }
56111077SCurtis.Dunham@arm.com    if (err) {
56211077SCurtis.Dunham@arm.com        warn("Running a checkpoint with incompatible version tags is not "
56311077SCurtis.Dunham@arm.com             "supported. While it might work, you may experience incorrect "
56411077SCurtis.Dunham@arm.com             "behavior or crashes.\n");
56511077SCurtis.Dunham@arm.com        warn("**********************************************************\n");
56611077SCurtis.Dunham@arm.com     }
5672SN/A}
5682SN/A
5695739Snate@binkert.orgSerializable::Serializable()
5705739Snate@binkert.org{
5715739Snate@binkert.org}
5725739Snate@binkert.org
5735739Snate@binkert.orgSerializable::~Serializable()
5745739Snate@binkert.org{
5755739Snate@binkert.org}
5765739Snate@binkert.org
5775739Snate@binkert.orgvoid
57810905Sandreas.sandberg@arm.comSerializable::serializeSection(CheckpointOut &cp, const char *name) const
5795739Snate@binkert.org{
58010905Sandreas.sandberg@arm.com    Serializable::ScopedCheckpointSection sec(cp, name);
58110905Sandreas.sandberg@arm.com    serialize(cp);
5825739Snate@binkert.org}
5835739Snate@binkert.org
5845739Snate@binkert.orgvoid
58510905Sandreas.sandberg@arm.comSerializable::unserializeSection(CheckpointIn &cp, const char *name)
58610905Sandreas.sandberg@arm.com{
58710905Sandreas.sandberg@arm.com    Serializable::ScopedCheckpointSection sec(cp, name);
58810905Sandreas.sandberg@arm.com    unserialize(cp);
5895739Snate@binkert.org}
5905739Snate@binkert.org
5912SN/Avoid
5926225Snate@binkert.orgSerializable::serializeAll(const string &cpt_dir)
5932SN/A{
59410905Sandreas.sandberg@arm.com    string dir = CheckpointIn::setDir(cpt_dir);
595363SN/A    if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
596449SN/A            fatal("couldn't mkdir %s\n", dir);
597363SN/A
59810905Sandreas.sandberg@arm.com    string cpt_file = dir + CheckpointIn::baseFilename;
599395SN/A    ofstream outstream(cpt_file.c_str());
6002SN/A    time_t t = time(NULL);
6015581Ssaidi@eecs.umich.edu    if (!outstream.is_open())
6025581Ssaidi@eecs.umich.edu        fatal("Unable to open file %s for writing\n", cpt_file.c_str());
6036818SLisa.Hsu@amd.com    outstream << "## checkpoint generated: " << ctime(&t);
6042SN/A
60510905Sandreas.sandberg@arm.com    globals.serializeSection(outstream, "Globals");
60610905Sandreas.sandberg@arm.com
607395SN/A    SimObject::serializeAll(outstream);
608395SN/A}
6092SN/A
6102797Sktlim@umich.eduvoid
61110905Sandreas.sandberg@arm.comSerializable::unserializeGlobals(CheckpointIn &cp)
612395SN/A{
61310905Sandreas.sandberg@arm.com    globals.unserializeSection(cp, "Globals");
61410905Sandreas.sandberg@arm.com
61511072Sandreas.sandberg@arm.com    for (uint32_t i = 0; i < numMainEventQueues; ++i)
61610905Sandreas.sandberg@arm.com        mainEventQueue[i]->setCurTick(globals.unserializedCurTick);
61710905Sandreas.sandberg@arm.com}
61810905Sandreas.sandberg@arm.com
61910905Sandreas.sandberg@arm.comSerializable::ScopedCheckpointSection::~ScopedCheckpointSection()
62010905Sandreas.sandberg@arm.com{
62110905Sandreas.sandberg@arm.com    assert(!path.empty());
62210905Sandreas.sandberg@arm.com    DPRINTF(Checkpoint, "Popping: %s\n", path.top());
62310905Sandreas.sandberg@arm.com    path.pop();
62410905Sandreas.sandberg@arm.com}
62510905Sandreas.sandberg@arm.com
62610905Sandreas.sandberg@arm.comvoid
62710905Sandreas.sandberg@arm.comSerializable::ScopedCheckpointSection::pushName(const char *obj_name)
62810905Sandreas.sandberg@arm.com{
62910905Sandreas.sandberg@arm.com    if (path.empty()) {
63010905Sandreas.sandberg@arm.com        path.push(obj_name);
63110905Sandreas.sandberg@arm.com    } else {
63210905Sandreas.sandberg@arm.com        path.push(csprintf("%s.%s", path.top(), obj_name));
63310905Sandreas.sandberg@arm.com    }
63410905Sandreas.sandberg@arm.com    DPRINTF(Checkpoint, "ScopedCheckpointSection::pushName: %s\n", obj_name);
63510905Sandreas.sandberg@arm.com}
63610905Sandreas.sandberg@arm.com
63710905Sandreas.sandberg@arm.comvoid
63810905Sandreas.sandberg@arm.comSerializable::ScopedCheckpointSection::nameOut(CheckpointOut &cp)
63910905Sandreas.sandberg@arm.com{
64010905Sandreas.sandberg@arm.com    DPRINTF(Checkpoint, "ScopedCheckpointSection::nameOut: %s\n",
64110905Sandreas.sandberg@arm.com            Serializable::currentSection());
64210905Sandreas.sandberg@arm.com    cp << "\n[" << Serializable::currentSection() << "]\n";
643395SN/A}
6442SN/A
6452SN/Avoid
6466225Snate@binkert.orgdebug_serialize(const string &cpt_dir)
6472SN/A{
6482868Sktlim@umich.edu    Serializable::serializeAll(cpt_dir);
6492SN/A}
6502SN/A
65110905Sandreas.sandberg@arm.comconst std::string &
65210905Sandreas.sandberg@arm.comSerializable::currentSection()
65310905Sandreas.sandberg@arm.com{
65410905Sandreas.sandberg@arm.com    assert(!path.empty());
65510905Sandreas.sandberg@arm.com
65610905Sandreas.sandberg@arm.com    return path.top();
65710905Sandreas.sandberg@arm.com}
658237SN/A
65910905Sandreas.sandberg@arm.comconst char *CheckpointIn::baseFilename = "m5.cpt";
6607491Ssteve.reinhardt@amd.com
66110905Sandreas.sandberg@arm.comstring CheckpointIn::currentDirectory;
6627491Ssteve.reinhardt@amd.com
6637491Ssteve.reinhardt@amd.comstring
66410905Sandreas.sandberg@arm.comCheckpointIn::setDir(const string &name)
6657491Ssteve.reinhardt@amd.com{
6667823Ssteve.reinhardt@amd.com    // use csprintf to insert curTick() into directory name if it
6677491Ssteve.reinhardt@amd.com    // appears to have a format placeholder in it.
6687491Ssteve.reinhardt@amd.com    currentDirectory = (name.find("%") != string::npos) ?
6697823Ssteve.reinhardt@amd.com        csprintf(name, curTick()) : name;
6707491Ssteve.reinhardt@amd.com    if (currentDirectory[currentDirectory.size() - 1] != '/')
6717491Ssteve.reinhardt@amd.com        currentDirectory += "/";
6727491Ssteve.reinhardt@amd.com    return currentDirectory;
6737491Ssteve.reinhardt@amd.com}
6747491Ssteve.reinhardt@amd.com
6757491Ssteve.reinhardt@amd.comstring
67610905Sandreas.sandberg@arm.comCheckpointIn::dir()
6777491Ssteve.reinhardt@amd.com{
6787491Ssteve.reinhardt@amd.com    return currentDirectory;
6797491Ssteve.reinhardt@amd.com}
6807491Ssteve.reinhardt@amd.com
6817491Ssteve.reinhardt@amd.com
68210905Sandreas.sandberg@arm.comCheckpointIn::CheckpointIn(const string &cpt_dir, SimObjectResolver &resolver)
68310453SAndrew.Bardsley@arm.com    : db(new IniFile), objNameResolver(resolver), cptDir(setDir(cpt_dir))
684237SN/A{
68510905Sandreas.sandberg@arm.com    string filename = cptDir + "/" + CheckpointIn::baseFilename;
686237SN/A    if (!db->load(filename)) {
687237SN/A        fatal("Can't load checkpoint file '%s'\n", filename);
688237SN/A    }
689237SN/A}
690237SN/A
69110905Sandreas.sandberg@arm.comCheckpointIn::~CheckpointIn()
6929086Sandreas.hansson@arm.com{
6939086Sandreas.hansson@arm.com    delete db;
6949086Sandreas.hansson@arm.com}
695237SN/A
696237SN/Abool
69711655Sandreas.sandberg@arm.comCheckpointIn::entryExists(const string &section, const string &entry)
69811655Sandreas.sandberg@arm.com{
69911655Sandreas.sandberg@arm.com    return db->entryExists(section, entry);
70011655Sandreas.sandberg@arm.com}
70111655Sandreas.sandberg@arm.com
70211655Sandreas.sandberg@arm.combool
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