-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.d
executable file
·217 lines (189 loc) · 6.92 KB
/
main.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#! /usr/bin/env rdmd
import std.stdio;
import std.getopt;
import std.socket;
import std.string;
import std.file;
import std.parallelism;
import std.array;
import std.string;
import parser.parser;
import spec.avrchips;
import machine.state;
import machine.factory;
import simulator.simulator;
import spec.avrstate;
void main(string[] args) {
string filename;
bool showStatistics = true,
debugMode = false,
batchMode = false,
showHelp = false;
string machine = "atmega2560";
char batchInputSeparator = '\n';
ushort port = 3742;
size_t batchCount = -1;
string[string] memFilenames;
if(args.length < 2) {
printUsage();
return;
}
getopt(args,
"help", &showHelp,
"batch", &batchMode,
"count", &batchCount,
"debug", &debugMode,
"mcu", &machine,
"port", &port,
"stats", &showStatistics,
"memfile", &memFilenames);
if (showHelp) {
printUsage();
return;
}
File file;
try {
filename = chomp(args[args.length-1]);
file = File(filename, "r");
} catch {
stderr.writeln("File ", filename, " could not be read");
return;
}
if(!(machine in machineFactories)) {
stderr.writefln("MCU %s not known, valid options: %s", machine,
machineFactories.keys);
return;
}
ubyte[] data;
InstructionToken[] instructions = parse(file, data);
file.close();
// create and initialize simulator
auto simulatorFactory = machineFactories[machine];
auto sim = simulatorFactory.createSimulator(instructions, data);
readMemFiles(memFilenames, sim.machineState);
if (debugMode) {
auto debugSim = cast(DebugSimulator)(sim);
debugSim.file = filename;
debug writefln("Opening a socket for the debugger", port);
Socket s = new TcpSocket;
scope(exit) {
debug writeln("Closing socket");
s.close();
}
try {
s.blocking = true;
s.bind(new InternetAddress(port));
s.listen(10);
stderr.writefln("Listening on port %d", port);
while (true) {
Socket input = s.accept();
scope(exit) {
debug writeln("Closing input socket");
input.close();
}
debug stderr.writeln("accepted connection");
char[64] buffer;
ptrdiff_t len;
do {
len = input.receive(buffer);
if (len == Socket.ERROR) {
stderr.writeln("Error: " ~ input.getErrorText());
break;
}
if (len == 0) {
debug stderr.writeln("Input socket closed");
break;
}
debug stderr.writefln("%s", buffer[0 .. len]);
string response = debugSim.handleDebugCommand(buffer[0 .. len].dup);
input.send(response);
} while (len != Socket.ERROR && len != 0);
}
} catch (Throwable e) {
writeln(e);
}
} else if (batchMode) {
stderr.writeln("Starting simulation in batch mode");
char[][] inputs = [];
string line;
while((line = stdin.readln(batchInputSeparator)) !is null) {
line = chomp(line, [batchInputSeparator]);
inputs ~= cast(char[])(line);
}
if (batchCount == -1) {
batchCount = inputs.length;
}
if (inputs.length != batchCount) {
stderr.writefln("Number of inputs (%d) does not match batch count (%d)", inputs.length, batchCount);
return;
}
stderr.writeln("Creating simulators");
Simulator[] simulators = [];
for(int i = 0; i < batchCount; ++i) {
simulators ~= simulatorFactory.createSimulator(instructions, data);
}
stderr.writeln("Running simulators");
foreach (idx, simulator; parallel(simulators)) {
writeMemFiles(memFilenames, simulator.machineState);
simulator.machineState.outputBuffer = [];
simulator.machineState.inputBuffer = cast(ubyte[])(inputs[idx].dup);
simulator.run();
}
stderr.writeln("Done");
foreach (simulator; simulators) {
debug stderr.writeln("Input:");
stderr.writeln(cast(string)(simulator.machineState.inputBuffer));
debug stderr.writeln("Output:");
// FIXME this is not really how you're supposed to read from the
// stream...
stdout.writeln(cast(string)(simulator.machineState.outputBuffer));
if (showStatistics) {
debug stderr.writeln("Stats:");
stderr.writeln(simulator.state);
}
}
} else {
writeMemFiles(memFilenames, sim.machineState);
auto simulatorState = sim.run();
if(showStatistics) {
stderr.writeln(simulatorState);
}
}
}
void readMemFiles(string[string] filenames, MachineState machineState) {
foreach (string mem, string filename; filenames) {
try {
filename = chomp(filename);
machineState.memories[mem] = cast(ubyte[])(read(filename));
} catch {
stderr.writeln("Memory file ", filename, " could not be read");
}
}
}
void writeMemFiles(string[string] filenames, MachineState machineState) {
foreach(string mem, string filename; filenames) {
try {
filename = chomp(filename);
std.file.write(filename, machineState.memories[mem].data);
} catch (Exception e) {
stderr.writeln("Memory file ", filename, " could not be written:");
stderr.writeln(e.msg);
}
}
}
void printUsage() {
writeln("Usage: ./usim [OPTIONS] <objdump>");
writeln("Where <objdump> is the output of `avr-objdump -D -z <binary>`");
writeln("Options: --help Print this");
writeln(" --debug Use debug mode [false]");
writeln(" --port <nr> Debug mode: set port to listen on [3742]");
writeln(" --batch Use batch mode [false]");
writeln(" --count Batch mode: number of batches to run");
writeln(" --separator Batch mode: input separator used for dividing input");
writeln(" among batches [\\n]");
writeln(" --mcu <mcu> Select microcontroller [atmega2560]");
writefln(" One of {%-(%s,%)}", machineFactories.keys);
writeln(" --stats=false Show statistics [true]");
writeln(" --memfile <memtype=filename> Files that contain initial memory at");
writeln(" start and to which final memory contents are written");
}