util: Further consolidate the Args interface in the m5 utility.
[gem5.git] / util / m5 / src / commands.cc
1 /*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <err.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32
33 #include <cinttypes>
34 #include <cstdio>
35 #include <cstdlib>
36 #include <cstring>
37 #include <iostream>
38
39 #include "args.hh"
40 #include "commands.hh"
41 #include "usage.hh"
42
43 static int
44 read_file(const DispatchTable &dt, int dest_fid)
45 {
46 uint8_t buf[256*1024];
47 int offset = 0;
48 int len, ret;
49
50 // Touch all buffer pages to ensure they are mapped in the
51 // page table. This is required in the case of X86_FS, where
52 // Linux does demand paging.
53 memset(buf, 0, sizeof(buf));
54
55 while ((len = (*dt.m5_read_file)(buf, sizeof(buf), offset)) > 0) {
56 uint8_t *base = buf;
57 offset += len;
58 do {
59 ret = write(dest_fid, base, len);
60 if (ret < 0) {
61 perror("Failed to write file");
62 exit(2);
63 } else if (ret == 0) {
64 fprintf(stderr, "Failed to write file: "
65 "Unhandled short write\n");
66 exit(2);
67 }
68
69 base += ret;
70 len -= ret;
71 } while (len);
72 }
73
74 return offset;
75 }
76
77 static void
78 write_file(const DispatchTable &dt, const char *filename,
79 const char *host_filename)
80 {
81 fprintf(stderr, "opening %s\n", filename);
82 int src_fid = open(filename, O_RDONLY);
83
84 if (src_fid < 0) {
85 fprintf(stderr, "error opening %s\n", filename);
86 return;
87 }
88
89 char buf[256*1024];
90 int offset = 0;
91 int len;
92 int bytes = 0;
93
94 memset(buf, 0, sizeof(buf));
95
96 while ((len = read(src_fid, buf, sizeof(buf))) > 0) {
97 bytes += (*dt.m5_write_file)(buf, len, offset, host_filename);
98 offset += len;
99 }
100 fprintf(stderr, "written %d bytes\n", bytes);
101
102 close(src_fid);
103 }
104
105 static void
106 do_exit(const DispatchTable &dt, Args &args)
107 {
108 if (args.size() > 1)
109 usage();
110
111 uint64_t ns_delay;
112 if (!args.pop(ns_delay, 0))
113 usage();
114
115 (*dt.m5_exit)(ns_delay);
116 }
117
118 static void
119 do_fail(const DispatchTable &dt, Args &args)
120 {
121 if (args.size() > 2)
122 usage();
123
124 uint64_t ns_delay, code;
125 if (!args.pop(code) || !args.pop(ns_delay, 0))
126 usage();
127
128 (*dt.m5_fail)(ns_delay, code);
129 }
130
131 static void
132 do_reset_stats(const DispatchTable &dt, Args &args)
133 {
134 if (args.size() > 2)
135 usage();
136
137 uint64_t ns_delay, ns_period;
138 if (!args.pop(ns_delay, 0) || !args.pop(ns_period, 0))
139 usage();
140
141 (*dt.m5_reset_stats)(ns_delay, ns_period);
142 }
143
144 static void
145 do_dump_stats(const DispatchTable &dt, Args &args)
146 {
147 if (args.size() > 2)
148 usage();
149
150 uint64_t ns_delay, ns_period;
151 if (!args.pop(ns_delay, 0) || !args.pop(ns_period, 0))
152 usage();
153
154 (*dt.m5_dump_stats)(ns_delay, ns_period);
155 }
156
157 static void
158 do_dump_reset_stats(const DispatchTable &dt, Args &args)
159 {
160 if (args.size() > 2)
161 usage();
162
163 uint64_t ns_delay, ns_period;
164 if (!args.pop(ns_delay, 0) || !args.pop(ns_period, 0))
165 usage();
166
167 (*dt.m5_dump_reset_stats)(ns_delay, ns_period);
168 }
169
170 static void
171 do_read_file(const DispatchTable &dt, Args &args)
172 {
173 if (args.size() > 0)
174 usage();
175
176 read_file(dt, STDOUT_FILENO);
177 }
178
179 static void
180 do_write_file(const DispatchTable &dt, Args &args)
181 {
182 if (args.size() < 1 || args.size() > 2)
183 usage();
184
185 const std::string &filename = args.pop();
186 const std::string &host_filename = args.pop(filename);
187
188 write_file(dt, filename.c_str(), host_filename.c_str());
189 }
190
191 static void
192 do_checkpoint(const DispatchTable &dt, Args &args)
193 {
194 if (args.size() > 2)
195 usage();
196
197 uint64_t ns_delay, ns_period;
198 if (!args.pop(ns_delay, 0) || !args.pop(ns_period, 0))
199 usage();
200
201 (*dt.m5_checkpoint)(ns_delay, ns_period);
202 }
203
204 static void
205 do_addsymbol(const DispatchTable &dt, Args &args)
206 {
207 if (args.size() != 2)
208 usage();
209
210 uint64_t addr;
211 if (!args.pop(addr))
212 usage();
213 const std::string &symbol = args.pop();
214
215 (*dt.m5_add_symbol)(addr, symbol.c_str());
216 }
217
218
219 static void
220 do_loadsymbol(const DispatchTable &dt, Args &args)
221 {
222 if (args.size() > 0)
223 usage();
224
225 (*dt.m5_load_symbol)();
226 }
227
228 static void
229 do_initparam(const DispatchTable &dt, Args &args)
230 {
231 if (args.size() != 1)
232 usage();
233
234 uint64_t key_str[2];
235 if (!args.pop(key_str, 2))
236 usage();
237 uint64_t val = (*dt.m5_init_param)(key_str[0], key_str[1]);
238 std::cout << val;
239 }
240
241 CommandInfo command_table[] = {
242 { "addsymbol", do_addsymbol, "<address> <symbol> // Adds a "
243 "symbol with address \"address\" "
244 "to gem5's symbol table" },
245 { "checkpoint", do_checkpoint, "[delay [period]] // After "
246 "delay (default 0) take a "
247 "checkpoint, and then optionally "
248 "every period after" },
249 { "dumpresetstats", do_dump_reset_stats, "[delay [period]] // After "
250 "delay (default 0) dump and "
251 "reset the stats, and then "
252 "optionally every period after" },
253 { "dumpstats", do_dump_stats, "[delay [period]] // After "
254 "delay (default 0) dump the "
255 "stats, and then optionally "
256 "every period after" },
257 { "exit", do_exit, "[delay] // Exit after delay, "
258 "or immediately" },
259 { "fail", do_fail, "<code> [delay] // Exit with "
260 "failure code code after delay, "
261 "or immediately" },
262 { "initparam", do_initparam, "[key] // optional key may be at "
263 "most 16 characters long" },
264 { "loadsymbol", do_loadsymbol, "load a preselected symbol file "
265 "into gem5's symbol table" },
266 { "readfile", do_read_file, "read a preselected file from "
267 "the host and write it to "
268 "stdout" },
269 { "resetstats", do_reset_stats, "[delay [period]] // After "
270 "delay (default 0) reset the "
271 "stats, and then optionally "
272 "every period after" },
273 { "writefile", do_write_file, "<filename> [host filename] // "
274 "Write a file to the host, "
275 "optionally with a different "
276 "name" },
277 };
278
279 int num_commands = sizeof(command_table) / sizeof(CommandInfo);