include: deprecate syscalls leftovers
[cavatools.git] / cachesim / cachesim.c
1 /*
2 Copyright (c) 2020 Peter Hsu. All Rights Reserved. See LICENCE file for details.
3 */
4
5 #include <stdint.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <assert.h>
12 #include <time.h>
13
14 #include "caveat.h"
15 #include "opcodes.h"
16 #include "insn.h"
17 #include "shmfifo.h"
18
19 #include "types.h"
20 #include "tagonlycache.h"
21
22
23 #define REPORT_FREQUENCY 10
24
25 #define RT_READ 0b0000000000000010L
26 #define RT_WRITE 0b0000000000000100L
27 #define RT_GETPUT 0b0000000000010000L
28 #define RT_LEVEL_SHIFT 5
29 #define RT_L0_CACHE 0b0000000000100000L
30 #define RT_L1_CACHE 0b0000000001000000L
31 #define RT_L2_CACHE 0b0000000010000000L
32 #define RT_L3_CACHE 0b0000000100000000L
33 #define RT_INSN_CACHE 0b0000001000000000L
34 #define RT_DATA_CACHE 0b0000010000000000L
35
36
37
38 struct fifo_t* fifo;
39 struct fifo_t* outbuf;
40 long report_frequency;
41
42 void allocError(uint64 n, char * thing, char * filename, int32 linenumber)
43 {
44 printf("\nmemory allocation failed trying to allocate %lld bytes for a '%s' on line %d in file %s",
45 n, thing, linenumber, filename);
46 }
47
48 int strchrs(const char* str, const char* keys)
49 {
50 for (char k=*keys++; k; k=*keys++)
51 if (strchr(str, k))
52 return 1;
53 return 0;
54 }
55
56 static const char* in_path;
57 static const char* out_path;
58 static const char* flags;
59 static long lgline, ways, lgsets;
60 static long report, quiet;
61
62 const struct options_t opt[] =
63 { { "--in=s", .s=&in_path, .ds=0, .h="Trace file =name (from caveat, pipesim, or cachesim)" },
64 { "--line=i", .i=&lgline, .di=6, .h="Cache line size is 2^ =n bytes" },
65 { "--ways=i", .i=&ways, .di=8, .h="Cache is =w ways set associativity" },
66 { "--sets=i", .i=&lgsets, .di=11, .h="Cache has 2^ =n sets per way" },
67 { "--sim=s", .s=&flags, .ds=0, .h="Simulate all access =types [iIdD0123rRwW] default all" },
68 { "--out=s", .s=&out_path, .ds=0, .h="Output next-level misses to trace =name" },
69 { "--report=i", .i=&report, .di=10, .h="Progress report every =number million instructions" },
70 { "--quiet", .b=&quiet, .bv=1, .h="Don't report progress to stderr" },
71 { "-q", .b=&quiet, .bv=1, .h="short for --quiet" },
72 { 0 }
73 };
74 const char* usage = "cachesim --in=trace [cachesim-options]";
75
76 int main(int argc, const char** argv)
77 {
78 int numopts = parse_options(argv+1);
79 if (argc == numopts+1 || !in_path)
80 help_exit();
81 cacheData* cache = (cacheData*)newCacheData();
82 configureCache(cache, (char*)"Wilson's cache", ways, lgline, lgsets);
83 long insns=0, now=0, refs=0, misses=0;
84 report_frequency = (report ? report : REPORT_FREQUENCY) * 1000000;
85 long next_report = report_frequency;
86 long filter = 0L;
87 if (flags) {
88 if (strchrs(flags, "rR") && !strchrs(flags, "wW"))
89 filter |= RT_READ;
90 else if (strchrs(flags, "wW") && !strchrs(flags, "rR"))
91 filter |= RT_WRITE;
92 else
93 filter |= RT_READ | RT_WRITE;
94
95 if (strchrs(flags, "iI") && !strchrs(flags, "dD"))
96 filter |= RT_INSN_CACHE;
97 else if (strchrs(flags, "dD") && !strchrs(flags, "iI"))
98 filter |= RT_DATA_CACHE;
99 else
100 filter |= RT_INSN_CACHE | RT_DATA_CACHE;
101
102 filter |= RT_L0_CACHE;
103 if (!strchrs(flags, "0")) {
104 filter |= RT_L1_CACHE;
105 if (!strchrs(flags, "1")) {
106 filter |= RT_L2_CACHE;
107 if (!strchrs(flags, "2"))
108 filter |= RT_L3_CACHE;
109 }
110 }
111 }
112 else
113 filter = ~0L; /* default simulate all references */
114
115 fifo = fifo_open(in_path);
116 if (out_path)
117 outbuf = fifo_create(out_path, 0);
118 clock_t start_tick = clock();
119
120 for (uint64_t tr=fifo_get(fifo); tr_code(tr)!=tr_eof; tr=fifo_get(fifo)) {
121
122 if (is_mem(tr)) {
123 long reftype;
124 if (is_ldst(tr))
125 reftype = is_write(tr) ? RT_WRITE : RT_READ;
126 else {
127 reftype = RT_GETPUT;
128 reftype |= (1L<<tr_clevel(tr)) << RT_LEVEL_SHIFT;
129 }
130 if (reftype & filter) {
131 cacheWay* way;
132 ++refs;
133 if (!lookup(is_write(tr)?'w':'r', tr_value(tr), cache, &way)) {
134 ++misses;
135 if (out_path)
136 fifo_put(outbuf, tr);
137 }
138 if (refs >= next_report && !quiet) {
139 double elapse = (clock() - start_tick) / CLOCKS_PER_SEC;
140 fprintf(stderr, "\r%3.1fB insns %3.1fB cycles %3.1fB refs %3.1f misses/Kinsns in %3.1fs for %3.1f MIPS ", insns/1e9, now/1e9, refs/1e9, misses/(insns/1e3), elapse, insns/1e6/elapse);
141 next_report += REPORT_FREQUENCY;
142 }
143 }
144 else if (out_path) /* pass to next stage */
145 fifo_put(outbuf, tr);
146 continue;
147 }
148 if (tr_code(tr) == tr_cycles) {
149 now = tr_value(tr);
150 if (out_path)
151 fifo_put(outbuf, tr);
152 continue;
153 }
154 if (tr_code(tr) == tr_icount) {
155 insns = tr_value(tr);
156 if (out_path)
157 fifo_put(outbuf, tr);
158 continue;
159 }
160 if (is_frame(tr) && out_path) {
161 fifo_put(outbuf, tr);
162 continue;
163 }
164 }
165 fprintf(stderr, "\n\n");
166 reportCacheStats(cache);
167 printf("\n");
168 if (out_path) {
169 fifo_put(outbuf, trM(tr_eof, 0));
170 fifo_finish(outbuf);
171 }
172 fifo_close(fifo);
173 return 0;
174 }