testers: move testers to a new directory
[gem5.git] / util / m5 / m5.c
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 * Authors: Nathan Binkert
29 */
30
31 #ifdef linux
32 #define _GNU_SOURCE
33 #include <sched.h>
34 #endif
35
36 #include <inttypes.h>
37 #include <err.h>
38 #include <fcntl.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43
44 #include "m5op.h"
45
46 char *progname;
47 char *command = "unspecified";
48 void usage();
49
50 void
51 parse_int_args(int argc, char *argv[], uint64_t ints[], int len)
52 {
53 if (argc > len)
54 usage();
55
56 int i;
57 for (i = 0; i < len; ++i)
58 ints[i] = (i < argc) ? strtoul(argv[i], NULL, 0) : 0;
59 }
60
61 int
62 read_file(int dest_fid)
63 {
64 char buf[256*1024];
65 int offset = 0;
66 int len;
67
68 // Touch all buffer pages to ensure they are mapped in the
69 // page table. This is required in the case of X86_FS, where
70 // Linux does demand paging.
71 memset(buf, 0, sizeof(buf));
72
73 while ((len = m5_readfile(buf, sizeof(buf), offset)) > 0) {
74 write(dest_fid, buf, len);
75 offset += len;
76 }
77 }
78
79 void
80 do_exit(int argc, char *argv[])
81 {
82 if (argc > 1)
83 usage();
84
85 m5_exit((argc > 0) ? strtoul(argv[0], NULL, 0) : 0);
86 }
87
88 void
89 do_reset_stats(int argc, char *argv[])
90 {
91 uint64_t ints[2];
92 parse_int_args(argc, argv, ints, 2);
93 m5_reset_stats(ints[0], ints[1]);
94 }
95
96 void
97 do_dump_stats(int argc, char *argv[])
98 {
99 uint64_t ints[2];
100 parse_int_args(argc, argv, ints, 2);
101 m5_dump_stats(ints[0], ints[1]);
102 }
103
104 void
105 do_dump_reset_stats(int argc, char *argv[])
106 {
107 uint64_t ints[2];
108 parse_int_args(argc, argv, ints, 2);
109 m5_dumpreset_stats(ints[0], ints[1]);
110 }
111
112 void
113 do_read_file(int argc, char *argv[])
114 {
115 if (argc > 0)
116 usage();
117
118 read_file(STDOUT_FILENO);
119 }
120
121 void
122 do_exec_file(int argc, char *argv[])
123 {
124 if (argc > 0)
125 usage();
126
127 const char *destname = "/tmp/execfile";
128
129 int fid = open(destname, O_WRONLY, 0777);
130 int len = read_file(fid);
131 close(fid);
132 if (len > 0) {
133 execl(destname, "execfile", NULL);
134 err(1, "execl failed!");
135 }
136 }
137
138 void
139 do_checkpoint(int argc, char *argv[])
140 {
141 uint64_t ints[2];
142 parse_int_args(argc, argv, ints, 2);
143 m5_checkpoint(ints[0], ints[1]);
144 }
145
146 void
147 do_load_symbol(int argc, char *argv[])
148 {
149 if (argc != 2)
150 usage();
151
152 uint64_t addr = strtoul(argv[0], NULL, 0);
153 char *symbol = argv[1];
154 m5_loadsymbol(addr, symbol);
155 }
156
157 void
158 do_initparam(int argc, char *argv[])
159 {
160 if (argc != 0)
161 usage();
162
163
164 printf("%ld", m5_initparam());
165 }
166
167 void
168 do_sw99param(int argc, char *argv[])
169 {
170 if (argc != 0)
171 usage();
172
173 uint64_t param = m5_initparam();
174
175 // run-time, rampup-time, rampdown-time, warmup-time, connections
176 printf("%d %d %d %d %d", (param >> 48) & 0xfff,
177 (param >> 36) & 0xfff, (param >> 24) & 0xfff,
178 (param >> 12) & 0xfff, (param >> 0) & 0xfff);
179 }
180
181 #ifdef linux
182 void
183 do_pin(int argc, char *argv[])
184 {
185 if (argc < 2)
186 usage();
187
188 cpu_set_t mask;
189 CPU_ZERO(&mask);
190
191 const char *sep = ",";
192 char *target = strtok(argv[0], sep);
193 while (target) {
194 CPU_SET(atoi(target), &mask);
195 target = strtok(NULL, sep);
196 }
197
198 if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) < 0)
199 err(1, "setaffinity");
200
201 execvp(argv[1], &argv[1]);
202 err(1, "execvp failed!");
203 }
204 #endif
205
206 struct MainFunc
207 {
208 char *name;
209 void (*func)(int argc, char *argv[]);
210 char *usage;
211 };
212
213 struct MainFunc mainfuncs[] = {
214 { "exit", do_exit, "[delay]" },
215 { "resetstats", do_reset_stats, "[delay [period]]" },
216 { "dumpstats", do_dump_stats, "[delay [period]]" },
217 { "dumpresetstats", do_dump_reset_stats, "[delay [period]]" },
218 { "readfile", do_read_file, "[filename]" },
219 { "execfile", do_exec_file, "<filename>" },
220 { "checkpoint", do_checkpoint, "[delay [period]]" },
221 { "loadsymbol", do_load_symbol, "<address> <symbol>" },
222 { "initparam", do_initparam, "" },
223 { "sw99param", do_sw99param, "" },
224 #ifdef linux
225 { "pin", do_pin, "<cpu> <program> [args ...]" }
226 #endif
227 };
228 int numfuncs = sizeof(mainfuncs) / sizeof(mainfuncs[0]);
229
230 void
231 usage()
232 {
233 int i;
234
235 for (i = 0; i < numfuncs; ++i) {
236 char *header = i ? "" : "usage:";
237 fprintf(stderr, "%-6s %s %s %s\n",
238 header, progname, mainfuncs[i].name, mainfuncs[i].usage);
239 }
240 fprintf(stderr, "\n");
241 fprintf(stderr, "All times in nanoseconds!\n");
242
243 exit(1);
244 }
245
246 int
247 main(int argc, char *argv[])
248 {
249 progname = argv[0];
250 if (argc < 2)
251 usage(1);
252
253 command = argv[1];
254
255 argv += 2;
256 argc -= 2;
257
258 int i;
259 for (i = 0; i < numfuncs; ++i) {
260 if (strcmp(command, mainfuncs[i].name) != 0)
261 continue;
262
263 mainfuncs[i].func(argc, argv);
264 exit(0);
265 }
266
267 usage(1);
268 }