gem5  [DEVELOP-FOR-23.0]
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
hdf5.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2019 Arm Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are
16  * met: redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer;
18  * redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution;
21  * neither the name of the copyright holders nor the names of its
22  * contributors may be used to endorse or promote products derived from
23  * this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #include "base/stats/hdf5.hh"
39 
40 #include "base/logging.hh"
41 #include "base/stats/info.hh"
42 #include "base/trace.hh"
43 #include "debug/Stats.hh"
44 
45 namespace gem5
46 {
47 
51 template<typename T>
52 bool emptyStrings(const T &labels)
53 {
54  for (const auto &s : labels) {
55  if (!s.empty())
56  return false;
57  }
58  return true;
59 }
60 
61 
62 namespace statistics
63 {
64 
65 Hdf5::Hdf5(const std::string &file, unsigned chunking,
66  bool desc, bool formulas)
67  : fname(file), timeChunk(chunking),
68  enableDescriptions(desc), enableFormula(formulas),
69  dumpCount(0)
70 {
71  // Tell the library not to print exceptions by default. There are
72  // cases where we rely on exceptions to determine if we need to
73  // create a node or if we can just open it.
74  H5::Exception::dontPrint();
75 }
76 
78 {
79 }
80 
81 
82 void
84 {
85  h5File = H5::H5File(fname,
86  // Truncate the file if this is the first dump
87  dumpCount > 0 ? H5F_ACC_RDWR : H5F_ACC_TRUNC);
88  path.push(h5File.openGroup("/"));
89 }
90 
91 void
93 {
94  assert(valid());
95 
96  dumpCount++;
97 }
98 
99 bool
100 Hdf5::valid() const
101 {
102  return true;
103 }
104 
105 
106 void
107 Hdf5::beginGroup(const char *name)
108 {
109  auto base = path.top();
110 
111  // Try to open an existing stat group corresponding to the
112  // name. Create it if it doesn't exist.
113  H5::Group group;
114  try {
115  group = base.openGroup(name);
116  } catch (const H5::FileIException& e) {
117  group = base.createGroup(name);
118  } catch (const H5::GroupIException& e) {
119  group = base.createGroup(name);
120  }
121 
122  path.push(group);
123 }
124 
125 void
127 {
128  assert(!path.empty());
129  path.pop();
130 }
131 
132 void
134 {
135  // Since this stat is a scalar, we need 1-dimensional value in the
136  // stat file. The Hdf5::appendStat helper will populate the size
137  // of the first dimension (time).
138  hsize_t fdims[1] = { 0, };
139  double data[1] = { info.result(), };
140 
141  appendStat(info, 1, fdims, data);
142 }
143 
144 void
146 {
147  appendVectorInfo(info);
148 }
149 
150 void
151 Hdf5::visit(const DistInfo &info)
152 {
153  warn_once("HDF5 stat files don't support distributions.\n");
154 }
155 
156 void
158 {
159  warn_once("HDF5 stat files don't support vector distributions.\n");
160 }
161 
162 void
164 {
165  // Request a 3-dimensional stat, the first dimension will be
166  // populated by the Hdf5::appendStat() helper. The remaining two
167  // dimensions correspond to the stat instance.
168  hsize_t fdims[3] = { 0, info.x, info.y };
169  H5::DataSet data_set = appendStat(info, 3, fdims, info.cvec.data());
170 
171  if (dumpCount == 0) {
172  if (!info.subnames.empty() && !emptyStrings(info.subnames))
173  addMetaData(data_set, "subnames", info.subnames);
174 
175  if (!info.y_subnames.empty() && !emptyStrings(info.y_subnames))
176  addMetaData(data_set, "y_subnames", info.y_subnames);
177 
178  if (!info.subdescs.empty() && !emptyStrings(info.subdescs))
179  addMetaData(data_set, "subdescs", info.subdescs);
180  }
181 }
182 
183 void
185 {
186  if (!enableFormula)
187  return;
188 
189  H5::DataSet data_set = appendVectorInfo(info);
190 
191  if (dumpCount == 0)
192  addMetaData(data_set, "equation", info.str());
193 }
194 
195 void
197 {
198  warn_once("HDF5 stat files don't support sparse histograms.\n");
199 }
200 
201 H5::DataSet
203 {
204  const VResult &vr(info.result());
205  // Request a 2-dimensional stat, the first dimension will be
206  // populated by the Hdf5::appendStat() helper. The remaining
207  // dimension correspond to the stat instance.
208  hsize_t fdims[2] = { 0, vr.size() };
209  H5::DataSet data_set = appendStat(info, 2, fdims, vr.data());
210 
211  if (dumpCount == 0) {
212  if (!info.subnames.empty() && !emptyStrings(info.subnames))
213  addMetaData(data_set, "subnames", info.subnames);
214 
215  if (!info.subdescs.empty() && !emptyStrings(info.subdescs))
216  addMetaData(data_set, "subdescs", info.subdescs);
217  }
218 
219  return data_set;
220 }
221 
222 H5::DataSet
223 Hdf5::appendStat(const Info &info, int rank, hsize_t *dims, const double *data)
224 {
225  H5::Group group = path.top();
226  H5::DataSet data_set;
227  H5::DataSpace fspace;
228 
229  dims[0] = dumpCount + 1;
230 
231  if (dumpCount > 0) {
232  // Get the existing stat if we have already dumped this stat
233  // before.
234  data_set = group.openDataSet(info.name);
235  data_set.extend(dims);
236  fspace = data_set.getSpace();
237  } else {
238  // We don't have the stat already, create it.
239 
240  H5::DSetCreatPropList props;
241 
242  // Setup max dimensions based on the requested file dimensions
243  std::vector<hsize_t> max_dims(rank);
244  std::copy(dims, dims + rank, max_dims.begin());
245  max_dims[0] = H5S_UNLIMITED;
246 
247  // Setup chunking
248  std::vector<hsize_t> chunk_dims(rank);
249  std::copy(dims, dims + rank, chunk_dims.begin());
250  chunk_dims[0] = timeChunk;
251  props.setChunk(rank, chunk_dims.data());
252 
253  // Enable compression
254  props.setDeflate(1);
255 
256  fspace = H5::DataSpace(rank, dims, max_dims.data());
257  try {
258  DPRINTF(Stats, "Creating dataset %s in group %s\n",
259  info.name, group.getObjnameByIdx(group.getId()));
260  data_set = group.createDataSet(info.name,
261  H5::PredType::NATIVE_DOUBLE, fspace, props);
262  } catch (const H5::Exception &e) {
263  std::string err = "Failed creating H5::DataSet " + info.name + "; ";
264  err += e.getDetailMsg() + " in " + e.getFuncName();
265  // Rethrow std exception so that it's passed on to the Python world
266  throw std::runtime_error(err);
267  }
268 
269  if (enableDescriptions && !info.desc.empty()) {
270  addMetaData(data_set, "description", info.desc);
271  }
272  }
273 
274  // The first dimension is time which isn't included in data.
275  dims[0] = 1;
276  H5::DataSpace mspace(rank, dims);
277  std::vector<hsize_t> foffset(rank, 0);
278  foffset[0] = dumpCount;
279 
280  fspace.selectHyperslab(H5S_SELECT_SET, dims, foffset.data());
281  data_set.write(data, H5::PredType::NATIVE_DOUBLE, mspace, fspace);
282 
283  return data_set;
284 }
285 
286 void
287 Hdf5::addMetaData(H5::DataSet &loc, const char *name,
288  const std::vector<const char *> &values)
289 {
290  H5::StrType type(H5::PredType::C_S1, H5T_VARIABLE);
291  hsize_t dims[1] = { values.size(), };
292  H5::DataSpace space(1, dims);
293  H5::Attribute attribute = loc.createAttribute(name, type, space);
294  attribute.write(type, values.data());
295 }
296 
297 void
298 Hdf5::addMetaData(H5::DataSet &loc, const char *name,
299  const std::vector<std::string> &values)
300 {
301  std::vector<const char *> cstrs(values.size());
302  for (int i = 0; i < values.size(); ++i)
303  cstrs[i] = values[i].c_str();
304 
305  addMetaData(loc, name, cstrs);
306 }
307 
308 void
309 Hdf5::addMetaData(H5::DataSet &loc, const char *name,
310  const std::string &value)
311 {
312  H5::StrType type(H5::PredType::C_S1, value.length() + 1);
313  hsize_t dims[1] = { 1, };
314  H5::DataSpace space(1, dims);
315  H5::Attribute attribute = loc.createAttribute(name, type, space);
316  attribute.write(type, value.c_str());
317 }
318 
319 void
320 Hdf5::addMetaData(H5::DataSet &loc, const char *name, double value)
321 {
322  hsize_t dims[1] = { 1, };
323  H5::DataSpace space(1, dims);
324  H5::Attribute attribute = loc.createAttribute(
325  name, H5::PredType::NATIVE_DOUBLE, space);
326  attribute.write(H5::PredType::NATIVE_DOUBLE, &value);
327 }
328 
329 
330 std::unique_ptr<Output>
331 initHDF5(const std::string &filename, unsigned chunking,
332  bool desc, bool formulas)
333 {
334  return std::unique_ptr<Output>(
335  new Hdf5(simout.resolve(filename), chunking, desc, formulas));
336 }
337 
338 }; // namespace statistics
339 } // namespace gem5
gem5::VegaISA::s
Bitfield< 1 > s
Definition: pagetable.hh:64
gem5::statistics::VectorInfo::subdescs
std::vector< std::string > subdescs
Definition: info.hh:188
gem5::statistics::DistInfo
Definition: info.hh:200
gem5::statistics::Hdf5::visit
void visit(const ScalarInfo &info) override
Definition: hdf5.cc:133
data
const char data[]
Definition: circlebuf.test.cc:48
gem5::statistics::VectorInfo
Definition: info.hh:183
warn_once
#define warn_once(...)
Definition: logging.hh:260
gem5::emptyStrings
bool emptyStrings(const T &labels)
Check if all strings in a container are empty.
Definition: hdf5.cc:52
gem5::statistics::Hdf5::~Hdf5
~Hdf5()
Definition: hdf5.cc:77
gem5::statistics::VectorInfo::result
virtual const VResult & result() const =0
gem5::ArmISA::err
Bitfield< 6 > err
Definition: misc_types.hh:892
gem5::ArmISA::e
Bitfield< 9 > e
Definition: misc_types.hh:65
gem5::simout
OutputDirectory simout
Definition: output.cc:62
gem5::statistics::Hdf5::endGroup
void endGroup() override
Definition: hdf5.cc:126
gem5::statistics::Hdf5::enableDescriptions
const bool enableDescriptions
Definition: hdf5.hh:147
gem5::statistics::Vector2dInfo::y_subnames
std::vector< std::string > y_subnames
Definition: info.hh:231
gem5::statistics::ScalarInfo
Definition: info.hh:175
std::vector< Result >
gem5::statistics::Hdf5::dumpCount
unsigned dumpCount
Definition: hdf5.hh:152
gem5::statistics::Hdf5::end
void end() override
Definition: hdf5.cc:92
gem5::X86ISA::base
Bitfield< 51, 12 > base
Definition: pagetable.hh:141
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
gem5::statistics::Vector2dInfo::subdescs
std::vector< std::string > subdescs
Definition: info.hh:230
gem5::statistics::Hdf5::enableFormula
const bool enableFormula
Definition: hdf5.hh:148
gem5::statistics::Hdf5::appendVectorInfo
H5::DataSet appendVectorInfo(const VectorInfo &info)
Helper function to append vector stats and set their metadata.
Definition: hdf5.cc:202
gem5::statistics::ScalarInfo::result
virtual Result result() const =0
gem5::statistics::Hdf5::begin
void begin() override
Definition: hdf5.cc:83
gem5::statistics::Hdf5::fname
const std::string fname
Definition: hdf5.hh:145
info.hh
gem5::statistics::Hdf5::appendStat
H5::DataSet appendStat(const Info &info, int rank, hsize_t *dims, const double *data)
Helper function to append an n-dimensional double stat to the file.
Definition: hdf5.cc:223
gem5::statistics::Hdf5::path
std::stack< H5::Group > path
Definition: hdf5.hh:150
gem5::statistics::Vector2dInfo::cvec
VCounter cvec
Local storage for the entry values, used for printing.
Definition: info.hh:237
gem5::statistics::Hdf5::Hdf5
Hdf5()=delete
gem5::statistics::SparseHistInfo
Definition: info.hh:250
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:210
gem5::statistics::FormulaInfo::str
virtual std::string str() const =0
gem5::statistics::Hdf5::h5File
H5::H5File h5File
Definition: hdf5.hh:153
gem5::X86ISA::type
type
Definition: misc.hh:734
gem5::OutputDirectory::resolve
std::string resolve(const std::string &name) const
Returns relative file names prepended with name of this directory.
Definition: output.cc:204
gem5::statistics::initHDF5
std::unique_ptr< Output > initHDF5(const std::string &filename, unsigned chunking, bool desc, bool formulas)
Definition: hdf5.cc:331
gem5::statistics::Hdf5::addMetaData
void addMetaData(H5::DataSet &loc, const char *name, const std::vector< const char * > &values)
Helper function to add a string vector attribute to a stat.
Definition: hdf5.cc:287
gem5::statistics::Vector2dInfo::y
size_type y
Definition: info.hh:234
name
const std::string & name()
Definition: trace.cc:48
gem5::statistics::Hdf5
Definition: hdf5.hh:59
gem5::statistics::VectorDistInfo
Definition: info.hh:207
gem5::statistics::Hdf5::valid
bool valid() const override
Definition: hdf5.cc:100
gem5::statistics::Info::desc
std::string desc
The description of the stat.
Definition: info.hh:89
gem5::statistics::Vector2dInfo::x
size_type x
Definition: info.hh:233
logging.hh
trace.hh
hdf5.hh
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::statistics::Hdf5::timeChunk
const hsize_t timeChunk
Definition: hdf5.hh:146
gem5::statistics::Vector2dInfo::subnames
std::vector< std::string > subnames
Names and descriptions of subfields.
Definition: info.hh:229
gem5::statistics::VectorInfo::subnames
std::vector< std::string > subnames
Names and descriptions of subfields.
Definition: info.hh:187
gem5::statistics::Info::name
std::string name
The name of the stat.
Definition: info.hh:83
gem5::statistics::FormulaInfo
Definition: info.hh:244
gem5::statistics::Vector2dInfo
Definition: info.hh:225
gem5::statistics::Hdf5::beginGroup
void beginGroup(const char *name) override
Definition: hdf5.cc:107
gem5::statistics::Info
Definition: info.hh:79

Generated on Sun Jul 30 2023 01:56:51 for gem5 by doxygen 1.8.17