@specy/risc-v 3.7.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +208 -15
- package/dist/index.d.mts +233 -79
- package/dist/index.d.ts +233 -79
- package/dist/index.js +12127 -13081
- package/dist/index.mjs +12126 -13081
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -44,17 +44,70 @@ type JsInstructionToken = {
|
|
|
44
44
|
value: string;
|
|
45
45
|
type: string;
|
|
46
46
|
};
|
|
47
|
+
/**
|
|
48
|
+
* Why a run call (`step`, `simulate`, `simulateWithLimit`, `simulateWithBreakpoints`,
|
|
49
|
+
* `simulateWithBreakpointsAndLimit`) stopped. The same enum, with the same values, as
|
|
50
|
+
* `@specy/mips`'s.
|
|
51
|
+
*/
|
|
47
52
|
declare enum StopReason {
|
|
48
|
-
|
|
53
|
+
/** No run call has stopped since the program was initialized; only `getStopReason` reports it. */
|
|
54
|
+
NONE = -1,
|
|
55
|
+
/** A breakpoint address or an `ebreak` was reached. */
|
|
49
56
|
BREAKPOINT = 0,
|
|
57
|
+
/** Never returned: a runtime failure rejects the run call with a `RuntimeError` instead. */
|
|
50
58
|
EXCEPTION = 1,
|
|
51
|
-
|
|
59
|
+
/** The instruction limit was reached, which is what a single `step()` ends on. */
|
|
60
|
+
MAX_STEPS = 2,
|
|
61
|
+
/** An exit service (10 or 93) ran, or the program had already exited and nothing ran. */
|
|
52
62
|
NORMAL_TERMINATION = 3,
|
|
53
|
-
|
|
63
|
+
/** The program ran off the end of its code: there is no statement at the program counter. */
|
|
64
|
+
CLIFF_TERMINATION = 4,
|
|
65
|
+
/** Not reachable through this package. */
|
|
54
66
|
PAUSE = 5,
|
|
67
|
+
/** Not reachable through this package. */
|
|
55
68
|
STOP = 6
|
|
56
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* What a `RuntimeError` was:
|
|
72
|
+
* - `exception`: a RISC-V exception the program had no trap handler for: a misaligned or faulting
|
|
73
|
+
* access, an illegal instruction, an instruction fetch outside the program.
|
|
74
|
+
* - `syscall`: an ecall refused its service number, arguments or input, such as "invalid integer
|
|
75
|
+
* input (syscall 5)" or "invalid or unimplemented syscall service: 99".
|
|
76
|
+
* - `handler`: a host handler or memory observer threw, rejected or broke its contract; its `cause`
|
|
77
|
+
* is what it threw or rejected with.
|
|
78
|
+
* - `internal`: the simulator itself failed.
|
|
79
|
+
*/
|
|
80
|
+
type RuntimeErrorKind = 'exception' | 'syscall' | 'handler' | 'internal';
|
|
81
|
+
/**
|
|
82
|
+
* The error a run call rejects with when the program fails at runtime: an `Error` named
|
|
83
|
+
* `RuntimeError` with typed fields, so that a host never parses its text. Any other rejection,
|
|
84
|
+
* such as a run call on a program that did not assemble, is the plain error it is.
|
|
85
|
+
*/
|
|
86
|
+
interface RuntimeError extends Error {
|
|
87
|
+
readonly name: 'RuntimeError';
|
|
88
|
+
readonly kind: RuntimeErrorKind;
|
|
89
|
+
/**
|
|
90
|
+
* The address of the instruction that failed, or of the program counter that could not be
|
|
91
|
+
* fetched, as a signed 32 bit int like `JsProgramStatement.address`.
|
|
92
|
+
*/
|
|
93
|
+
readonly address: number;
|
|
94
|
+
/** The failing statement's source file, or null when there is no statement. */
|
|
95
|
+
readonly sourcePath: string | null;
|
|
96
|
+
/** The failing statement's one-based line in `sourcePath`, or null. */
|
|
97
|
+
readonly line: number | null;
|
|
98
|
+
/**
|
|
99
|
+
* RARS's own words, without the location: "Runtime exception at 0x00400004: invalid or
|
|
100
|
+
* unimplemented syscall service: 99", "Handler readInt did not return a string".
|
|
101
|
+
*/
|
|
102
|
+
readonly message: string;
|
|
103
|
+
/** For a `handler` failure, what the handler threw or rejected with. */
|
|
104
|
+
readonly cause?: unknown;
|
|
105
|
+
}
|
|
106
|
+
/** Whether a run call's rejection is a typed `RuntimeError`. */
|
|
107
|
+
declare function isRuntimeError(error: unknown): error is RuntimeError;
|
|
108
|
+
/** The kind of message dialog syscall 55 asks for; any other value of a1 asks for a plain message. */
|
|
57
109
|
declare enum DialogType {
|
|
110
|
+
PLAIN_MESSAGE = -1,
|
|
58
111
|
ERROR_MESSAGE = 0,
|
|
59
112
|
INFORMATION_MESSAGE = 1,
|
|
60
113
|
WARNING_MESSAGE = 2,
|
|
@@ -65,97 +118,114 @@ declare enum ConfirmResult {
|
|
|
65
118
|
NO = 1,
|
|
66
119
|
CANCEL = 2
|
|
67
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* The handlers a program's syscalls reach the outside world through, each as its arguments and its
|
|
123
|
+
* answer. The syscalls own each service's semantics, as RARS defines them: they format what they
|
|
124
|
+
* print and parse what they read, so a handler only moves text and bytes. Bytes cross as plain
|
|
125
|
+
* arrays of numbers from 0 to 255.
|
|
126
|
+
*/
|
|
68
127
|
type HandlerMap = {
|
|
128
|
+
/**
|
|
129
|
+
* Syscall 1024: open a file, with `flags` 0 to read and 1 to write, `append` set for flags 9. The
|
|
130
|
+
* path is the program's string decoded from UTF-8. Answer with the new file descriptor, or -1
|
|
131
|
+
* when the file cannot be opened.
|
|
132
|
+
*/
|
|
69
133
|
openFile: {
|
|
70
134
|
in: [filename: string, flags: number, append: boolean];
|
|
71
135
|
out: number;
|
|
72
136
|
};
|
|
137
|
+
/** Syscall 57: close a file descriptor that `openFile` returned. */
|
|
73
138
|
closeFile: {
|
|
74
139
|
in: [fileDescriptor: number];
|
|
75
140
|
out: void;
|
|
76
141
|
};
|
|
142
|
+
/**
|
|
143
|
+
* Syscall 64 on a file descriptor that `openFile` returned: write the bytes. Answer with the
|
|
144
|
+
* number of bytes written, or -1 when the write failed; the program receives it in a0.
|
|
145
|
+
*/
|
|
77
146
|
writeFile: {
|
|
78
147
|
in: [fileDescriptor: number, buffer: number[]];
|
|
79
|
-
out:
|
|
148
|
+
out: number;
|
|
80
149
|
};
|
|
150
|
+
/**
|
|
151
|
+
* Syscall 63 on a file descriptor that `openFile` returned: read at most `length` bytes. Answer
|
|
152
|
+
* with `[count, bytes]`, where a count of 0 is the end of the file and -1 a failed read.
|
|
153
|
+
*/
|
|
81
154
|
readFile: {
|
|
82
|
-
in: [fileDescriptor: number,
|
|
83
|
-
out: [
|
|
155
|
+
in: [fileDescriptor: number, length: number];
|
|
156
|
+
out: [count: number, buffer: number[]];
|
|
84
157
|
};
|
|
158
|
+
/**
|
|
159
|
+
* Syscall 50: a Yes, No and Cancel question. Cancel reaches the program as 2. Every dialog's
|
|
160
|
+
* message is the program's string at a0, decoded from UTF-8.
|
|
161
|
+
*/
|
|
85
162
|
confirm: {
|
|
86
163
|
in: [message: string];
|
|
87
164
|
out: ConfirmResult;
|
|
88
165
|
};
|
|
166
|
+
/**
|
|
167
|
+
* Syscalls 51 to 54: ask for a line of text. Answer with the text, or null when the user cancels,
|
|
168
|
+
* which the program receives as status -2. The syscall parses the text itself, as RARS does;
|
|
169
|
+
* 54 stores it as UTF-8, measuring the buffer in bytes.
|
|
170
|
+
*/
|
|
89
171
|
inputDialog: {
|
|
90
172
|
in: [message: string];
|
|
91
|
-
out: string;
|
|
173
|
+
out: string | null;
|
|
92
174
|
};
|
|
175
|
+
/** Syscalls 55, 56 and 58 to 60: show a message. The program waits until the handler settles. */
|
|
93
176
|
outputDialog: {
|
|
94
177
|
in: [message: string, type: DialogType];
|
|
95
178
|
out: void;
|
|
96
179
|
};
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
in: [message: string];
|
|
103
|
-
out: number;
|
|
104
|
-
};
|
|
105
|
-
askInt: {
|
|
106
|
-
in: [message: string];
|
|
107
|
-
out: number;
|
|
108
|
-
};
|
|
109
|
-
askString: {
|
|
110
|
-
in: [message: string];
|
|
111
|
-
out: string;
|
|
112
|
-
};
|
|
113
|
-
readDouble: {
|
|
180
|
+
/**
|
|
181
|
+
* Syscall 5: the line typed. The syscall trims it and parses it as Java's `Integer.parseInt`
|
|
182
|
+
* does; anything else stops the program with "invalid integer input (syscall 5)".
|
|
183
|
+
*/
|
|
184
|
+
readInt: {
|
|
114
185
|
in: [];
|
|
115
|
-
out:
|
|
186
|
+
out: string;
|
|
116
187
|
};
|
|
188
|
+
/**
|
|
189
|
+
* Syscall 6: the line typed. The syscall trims it and parses it as Java's `Float.parseFloat`
|
|
190
|
+
* does; anything else stops the program with "invalid float input (syscall 6)".
|
|
191
|
+
*/
|
|
117
192
|
readFloat: {
|
|
118
193
|
in: [];
|
|
119
|
-
out:
|
|
194
|
+
out: string;
|
|
120
195
|
};
|
|
121
|
-
|
|
196
|
+
/**
|
|
197
|
+
* Syscall 7: the line typed. The syscall trims it and parses it as Java's `Double.parseDouble`
|
|
198
|
+
* does; anything else stops the program with "invalid double input (syscall 7)".
|
|
199
|
+
*/
|
|
200
|
+
readDouble: {
|
|
122
201
|
in: [];
|
|
123
|
-
out:
|
|
202
|
+
out: string;
|
|
124
203
|
};
|
|
204
|
+
/**
|
|
205
|
+
* Syscall 8: the line typed. The syscall stores it as UTF-8, as RARS does: at most the buffer's
|
|
206
|
+
* length less one characters, then at most that many bytes of them, so a character can be cut
|
|
207
|
+
* where the buffer ends.
|
|
208
|
+
*/
|
|
125
209
|
readString: {
|
|
126
210
|
in: [];
|
|
127
211
|
out: string;
|
|
128
212
|
};
|
|
213
|
+
/**
|
|
214
|
+
* Syscall 12: the character typed, Enter as `"\n"`. The syscall takes the first UTF-16 unit of the
|
|
215
|
+
* answer, as RARS does (`é` reads as 233, an emoji as its high surrogate); an empty answer stops
|
|
216
|
+
* the program with "invalid char input (syscall 12)".
|
|
217
|
+
*/
|
|
129
218
|
readChar: {
|
|
130
219
|
in: [];
|
|
131
220
|
out: string;
|
|
132
221
|
};
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
in: [message: string];
|
|
139
|
-
out: void;
|
|
140
|
-
};
|
|
141
|
-
printChar: {
|
|
142
|
-
in: [c: string];
|
|
143
|
-
out: void;
|
|
144
|
-
};
|
|
145
|
-
printDouble: {
|
|
146
|
-
in: [d: number];
|
|
147
|
-
out: void;
|
|
148
|
-
};
|
|
149
|
-
printFloat: {
|
|
150
|
-
in: [f: number];
|
|
151
|
-
out: void;
|
|
152
|
-
};
|
|
153
|
-
printInt: {
|
|
154
|
-
in: [i: number];
|
|
155
|
-
out: void;
|
|
156
|
-
};
|
|
222
|
+
/**
|
|
223
|
+
* Program output: the text every print syscall (1 to 4, 11 and 34 to 36) formats, exactly as
|
|
224
|
+
* RARS prints it on Java 21, so a float prints `1.0` and `1.0E-5`. Print string (4) decodes the
|
|
225
|
+
* string from UTF-8; print char (11) prints the character numbered by the low byte of a0.
|
|
226
|
+
*/
|
|
157
227
|
printString: {
|
|
158
|
-
in: [
|
|
228
|
+
in: [text: string];
|
|
159
229
|
out: void;
|
|
160
230
|
};
|
|
161
231
|
/**
|
|
@@ -167,9 +237,10 @@ type HandlerMap = {
|
|
|
167
237
|
out: void;
|
|
168
238
|
};
|
|
169
239
|
/**
|
|
170
|
-
* Syscall 30
|
|
171
|
-
*
|
|
172
|
-
*
|
|
240
|
+
* Syscall 30, and every instruction that reads the `time` CSR (or `timeh`, its upper half on
|
|
241
|
+
* RV32): the program time in milliseconds. The syscall splits it into a0 (low word) and a1 (high
|
|
242
|
+
* word). Answer with `Date.now()` for a live run, or with a virtual clock for a scripted one, so
|
|
243
|
+
* that elapsed-time output stays reproducible.
|
|
173
244
|
*/
|
|
174
245
|
time: {
|
|
175
246
|
in: [];
|
|
@@ -181,7 +252,7 @@ type HandlerMap = {
|
|
|
181
252
|
* of input and -1 a failed read. Return a promise to wait for the user.
|
|
182
253
|
*/
|
|
183
254
|
stdIn: {
|
|
184
|
-
in: [
|
|
255
|
+
in: [length: number];
|
|
185
256
|
out: [count: number, buffer: number[]];
|
|
186
257
|
};
|
|
187
258
|
/**
|
|
@@ -192,14 +263,30 @@ type HandlerMap = {
|
|
|
192
263
|
in: [fileDescriptor: number, offset: number, whence: number];
|
|
193
264
|
out: number;
|
|
194
265
|
};
|
|
266
|
+
/** Syscall 64 on descriptor 1: the bytes written to standard output. */
|
|
195
267
|
stdOut: {
|
|
196
268
|
in: [buffer: number[]];
|
|
197
269
|
out: void;
|
|
198
270
|
};
|
|
271
|
+
/** Syscall 64 on descriptor 2: the bytes written to standard error. */
|
|
199
272
|
stdErr: {
|
|
200
273
|
in: [buffer: number[]];
|
|
201
274
|
out: void;
|
|
202
275
|
};
|
|
276
|
+
/**
|
|
277
|
+
* Syscalls 41 to 44, on the first use of a generator the program has not seeded with service
|
|
278
|
+
* 40: the seed it starts from, as `new java.util.Random(seed)` takes it, a whole number from 0
|
|
279
|
+
* to 2^48 - 1 (every seed a Java long can hold scrambles to the state one of these does).
|
|
280
|
+
* `index` is the generator's number from a0. Answer with host randomness for a live run, or
|
|
281
|
+
* with a fixed seed for a scripted one, so that a Testcase gets the same numbers every time.
|
|
282
|
+
*
|
|
283
|
+
* Optional: without it a generator starts from host randomness, as in RARS. The generators
|
|
284
|
+
* implement `java.util.Random` exactly, so a seeded program prints the numbers RARS prints.
|
|
285
|
+
*/
|
|
286
|
+
randomSeed: {
|
|
287
|
+
in: [index: number];
|
|
288
|
+
out: number;
|
|
289
|
+
};
|
|
203
290
|
};
|
|
204
291
|
/**
|
|
205
292
|
* Notified after a write anywhere in an observed address range.
|
|
@@ -361,12 +448,26 @@ declare enum BackStepAction {
|
|
|
361
448
|
* A whole Poke: every value one `beginPoke`/`endPoke` transaction wrote, restored together.
|
|
362
449
|
* A Poke is a single back step, so it takes one slot of the undo size whatever it wrote.
|
|
363
450
|
*/
|
|
364
|
-
POKE = 13
|
|
451
|
+
POKE = 13,
|
|
452
|
+
/**
|
|
453
|
+
* An exit service (10 or 93): undoing it leaves the program running on the ecall again.
|
|
454
|
+
* `param1` is 1 if the program had already exited (never, as nothing runs after an exit),
|
|
455
|
+
* `oldValue` the exit code it replaced and `newValue` the code the exit set.
|
|
456
|
+
*/
|
|
457
|
+
EXIT_RESTORE = 14,
|
|
458
|
+
/**
|
|
459
|
+
* A random service (40 to 44) advanced or reseeded generator `param1`: undoing it puts the
|
|
460
|
+
* generator back, so that stepping the service again draws the same number. The generator's
|
|
461
|
+
* state is the simulator's own, so `param2`, `oldValue` and `newValue` are 0.
|
|
462
|
+
*/
|
|
463
|
+
RANDOM_STREAM_RESTORE = 15
|
|
365
464
|
}
|
|
366
465
|
/**
|
|
367
466
|
* Represents a back step in the simulation undo stack.
|
|
368
467
|
*/
|
|
369
468
|
interface JsBackStep {
|
|
469
|
+
/** Opaque decimal identity, unique across Undo, initialize and reassembly in this module. */
|
|
470
|
+
readonly serial: string;
|
|
370
471
|
/**
|
|
371
472
|
* The action performed (e.g., register write, memory write).
|
|
372
473
|
*/
|
|
@@ -396,8 +497,10 @@ interface JsBackStep {
|
|
|
396
497
|
* was made, in the low order bits.
|
|
397
498
|
* - `PC_RESTORE`: the address the restore puts back - the same value as `param1`, which is
|
|
398
499
|
* where this action has always kept it, its `param2` being unused and 0.
|
|
500
|
+
* - `EXIT_RESTORE`: the exit code the exit replaced.
|
|
399
501
|
* - `'0'` for `CONTROL_AND_STATUS_COUNTERS_DECREMENT`, `DO_NOTHING` and `POKE`, which replace
|
|
400
502
|
* no single value; a Poke reports both sides of everything it wrote through its own `writes`.
|
|
503
|
+
* Also for `RANDOM_STREAM_RESTORE`, whose generator state is the simulator's own.
|
|
401
504
|
*/
|
|
402
505
|
readonly oldValue: string;
|
|
403
506
|
/**
|
|
@@ -407,9 +510,9 @@ interface JsBackStep {
|
|
|
407
510
|
*
|
|
408
511
|
* `CONTROL_AND_STATUS_REGISTER_BACKDOOR` is the simulator sampling the wall clock into `time`
|
|
409
512
|
* rather than a program writing a register, but it is a write all the same and reports the
|
|
410
|
-
* millisecond reading it stored. `'0'` for
|
|
411
|
-
* `DO_NOTHING`, which write no value of their own,
|
|
412
|
-
* sides already
|
|
513
|
+
* millisecond reading it stored. `EXIT_RESTORE` reports the exit code the exit set. `'0'` for
|
|
514
|
+
* `CONTROL_AND_STATUS_COUNTERS_DECREMENT` and `DO_NOTHING`, which write no value of their own,
|
|
515
|
+
* for `POKE`, whose `writes` carry both sides already, and for `RANDOM_STREAM_RESTORE`.
|
|
413
516
|
*/
|
|
414
517
|
readonly newValue: string;
|
|
415
518
|
/**
|
|
@@ -469,6 +572,8 @@ type JsUndoGroup = JsInstructionUndoGroup | JsPokeUndoGroup;
|
|
|
469
572
|
* overwrote, and the `cycle`/`instret` decrement every instruction pushes on top of them.
|
|
470
573
|
*/
|
|
471
574
|
type JsInstructionUndoGroup = {
|
|
575
|
+
/** Opaque decimal identity, unique across Undo, initialize and reassembly in this module. */
|
|
576
|
+
readonly serial: string;
|
|
472
577
|
readonly kind: 'instruction';
|
|
473
578
|
readonly pc: number;
|
|
474
579
|
/** The instruction's back steps, newest first. */
|
|
@@ -483,6 +588,8 @@ type JsInstructionUndoGroup = {
|
|
|
483
588
|
* alone.
|
|
484
589
|
*/
|
|
485
590
|
type JsPokeUndoGroup = {
|
|
591
|
+
/** Opaque decimal identity, unique across Undo, initialize and reassembly in this module. */
|
|
592
|
+
readonly serial: string;
|
|
486
593
|
readonly kind: 'poke';
|
|
487
594
|
readonly pc: -1;
|
|
488
595
|
/** The single back step the Poke is: one slot of the history, whatever the Poke wrote. */
|
|
@@ -546,8 +653,13 @@ type HandlerName = keyof HandlerMap;
|
|
|
546
653
|
* user, reading a file, awaiting a worker) without blocking the event loop. If the promise
|
|
547
654
|
* rejects, the pending `step`/`simulate*` call rejects too.
|
|
548
655
|
*/
|
|
656
|
+
type HandlerFn<K extends HandlerName> = (...args: HandlerMap[K]['in']) => HandlerMap[K]['out'] | Promise<HandlerMap[K]['out']>;
|
|
657
|
+
/** The handlers a host may leave out: the simulator then does what RARS does on its own. */
|
|
658
|
+
type OptionalHandlerName = 'randomSeed';
|
|
549
659
|
type HandlerMapFns = {
|
|
550
|
-
[K in HandlerName]:
|
|
660
|
+
[K in Exclude<HandlerName, OptionalHandlerName>]: HandlerFn<K>;
|
|
661
|
+
} & {
|
|
662
|
+
[K in OptionalHandlerName]?: HandlerFn<K>;
|
|
551
663
|
};
|
|
552
664
|
declare function registerHandlers(riscv: JsRiscV, handlers: HandlerMapFns): void;
|
|
553
665
|
declare function unimplementedHandler(name: HandlerName): () => never;
|
|
@@ -560,23 +672,39 @@ interface JsRiscV {
|
|
|
560
672
|
*/
|
|
561
673
|
assemble(): RISCVAssembleResult;
|
|
562
674
|
/**
|
|
563
|
-
* Initializes the simulator
|
|
675
|
+
* Initializes the simulator for a new run: the registers, the program counter, and the state
|
|
676
|
+
* of the run - not exited, exit code 0, no stop reason, and the random generators forgotten, so
|
|
677
|
+
* that each starts from a new seed on its first use. Assembling leaves the run state alone.
|
|
564
678
|
* @param startAtMain If true, starts execution at the 'main' label. Otherwise, starts at the first instruction.
|
|
565
679
|
*/
|
|
566
680
|
initialize(startAtMain: boolean): void;
|
|
567
681
|
/**
|
|
568
|
-
*
|
|
682
|
+
* Why the last run call stopped: `NONE` when none has since the program was initialized, and
|
|
683
|
+
* `EXCEPTION` after one rejected with a `RuntimeError`. Undo does not change it; read
|
|
684
|
+
* `terminated` for whether the program can run.
|
|
569
685
|
*/
|
|
570
686
|
getStopReason(): StopReason;
|
|
687
|
+
/**
|
|
688
|
+
* The program's exit code: exit2's (93) operand once it has run, 0 otherwise - after exit (10),
|
|
689
|
+
* after running off the end, while the program runs. `initialize` resets it to 0, and undoing
|
|
690
|
+
* the exit puts back the code before it.
|
|
691
|
+
*/
|
|
692
|
+
readonly exitCode: number;
|
|
571
693
|
/**
|
|
572
694
|
* Executes a single instruction.
|
|
573
695
|
*
|
|
574
|
-
*
|
|
575
|
-
*
|
|
696
|
+
* Resolves to why it stopped: `MAX_STEPS` normally, `NORMAL_TERMINATION` for an exit,
|
|
697
|
+
* `CLIFF_TERMINATION` when the instruction was the program's last (or there was none to run),
|
|
698
|
+
* `BREAKPOINT` for an `ebreak`. A program that has exited runs nothing more and resolves to
|
|
699
|
+
* `NORMAL_TERMINATION` again. Rejects with a `RuntimeError` when the program fails. The
|
|
700
|
+
* promise settles on a microtask unless an IO handler returned a promise, in which case it
|
|
701
|
+
* settles once that handler and the rest of the instruction have finished.
|
|
576
702
|
*/
|
|
577
703
|
step(): Promise<StopReason>;
|
|
578
704
|
/**
|
|
579
|
-
* Sets the
|
|
705
|
+
* Sets the maximum raw restore slots, before assembly. A Poke uses one slot; instructions
|
|
706
|
+
* use one slot per restore. Oldest instructions are evicted whole. An instruction larger
|
|
707
|
+
* than the capacity is discarded whole. Zero retains no history; negative sizes throw.
|
|
580
708
|
* @param size
|
|
581
709
|
*/
|
|
582
710
|
setUndoSize(size: number): void;
|
|
@@ -617,32 +745,45 @@ interface JsRiscV {
|
|
|
617
745
|
getLabelAtAddress(address: number): string | null;
|
|
618
746
|
/** Address of a defined label/alias, or -1 if absent. Requires successful assembly. */
|
|
619
747
|
getAddressOfLabel(label: string): number;
|
|
748
|
+
/**
|
|
749
|
+
* Where the program's heap, and so the first block sbrk (9) hands out, starts. RARS's heap base,
|
|
750
|
+
* 0x10040000, unless the program is a `gnu-compiler-v1` Build whose static data (`.data`,
|
|
751
|
+
* `.rodata`, `.bss`, common symbols) reaches past it: then the heap starts at the first 4 KiB page
|
|
752
|
+
* after static data, where ld and a kernel put the break. A RARS-dialect program keeps the heap
|
|
753
|
+
* base whatever its size, as RARS does. Requires successful assembly; `initialize` empties the
|
|
754
|
+
* heap again.
|
|
755
|
+
*/
|
|
756
|
+
getHeapStart(): number;
|
|
620
757
|
/**
|
|
621
758
|
* Sets whether the undo feature is enabled.
|
|
622
759
|
* @param enabled True to enable the undo feature, false to disable it.
|
|
623
760
|
*/
|
|
624
761
|
setUndoEnabled(enabled: boolean): void;
|
|
625
762
|
/**
|
|
626
|
-
* Simulates until the
|
|
763
|
+
* Simulates until the program stops: an exit, running off the end, an `ebreak`, or a failure,
|
|
764
|
+
* which rejects with a `RuntimeError`.
|
|
627
765
|
*/
|
|
628
766
|
simulate(): Promise<StopReason>;
|
|
629
767
|
/**
|
|
630
768
|
* Simulates the program for a limited number of instructions.
|
|
631
769
|
* @param limit The maximum number of instructions to execute.
|
|
632
|
-
* @returns A promise resolving to the reason the simulation stopped
|
|
770
|
+
* @returns A promise resolving to the reason the simulation stopped (`MAX_STEPS` when the
|
|
771
|
+
* limit did), rejecting with a `RuntimeError` when the program fails.
|
|
633
772
|
*/
|
|
634
773
|
simulateWithLimit(limit: number): Promise<StopReason>;
|
|
635
774
|
/**
|
|
636
775
|
* Simulates the program until a breakpoint is reached.
|
|
637
776
|
* @param breakpoints An array of memory addresses where the simulation should pause.
|
|
638
|
-
* @returns A promise resolving to the reason the simulation stopped
|
|
777
|
+
* @returns A promise resolving to the reason the simulation stopped, rejecting with a
|
|
778
|
+
* `RuntimeError` when the program fails.
|
|
639
779
|
*/
|
|
640
780
|
simulateWithBreakpoints(breakpoints: number[]): Promise<StopReason>;
|
|
641
781
|
/**
|
|
642
782
|
* Simulates the program with both breakpoints and a limit.
|
|
643
783
|
* @param breakpoints An array of memory addresses where the simulation should pause.
|
|
644
784
|
* @param limit The maximum number of instructions to execute.
|
|
645
|
-
* @returns A promise resolving to the reason the simulation stopped
|
|
785
|
+
* @returns A promise resolving to the reason the simulation stopped, rejecting with a
|
|
786
|
+
* `RuntimeError` when the program fails.
|
|
646
787
|
*/
|
|
647
788
|
simulateWithBreakpointsAndLimit(breakpoints: number[], limit: number): Promise<StopReason>;
|
|
648
789
|
/**
|
|
@@ -658,11 +799,12 @@ interface JsRiscV {
|
|
|
658
799
|
*/
|
|
659
800
|
getRegisterValueLong(register: RegisterName): string;
|
|
660
801
|
/**
|
|
661
|
-
* Registers a handler function for a specific event or condition.
|
|
802
|
+
* Registers a handler function for a specific event or condition. Handlers are shared by every
|
|
803
|
+
* `JsRiscV` instance. An optional handler (`randomSeed`) is removed by registering `undefined`.
|
|
662
804
|
* @param name The name of the event or condition.
|
|
663
805
|
* @param handler The handler function to be called when the event occurs. The function signature depends on the event name.
|
|
664
806
|
*/
|
|
665
|
-
registerHandler<T extends HandlerName>(name: T, handler:
|
|
807
|
+
registerHandler<T extends HandlerName>(name: T, handler: HandlerFn<T> | (T extends OptionalHandlerName ? undefined : never)): void;
|
|
666
808
|
/**
|
|
667
809
|
* Gets the current value of the stack pointer.
|
|
668
810
|
* @returns The value of the stack pointer.
|
|
@@ -753,6 +895,15 @@ interface JsRiscV {
|
|
|
753
895
|
* carries what it changed, with the old and the new value of each write.
|
|
754
896
|
*/
|
|
755
897
|
getUndoGroups(): JsUndoGroup[];
|
|
898
|
+
/**
|
|
899
|
+
* The current dynamic instruction's serial, or null outside execution. Read it inside a host
|
|
900
|
+
* handler to journal an effect under the same identity its eventual Undo group carries. It
|
|
901
|
+
* remains stable while an async handler waits. Failures and exits have identities too.
|
|
902
|
+
* Serials are allocated even with Undo disabled; such runs retain no groups. Treat the decimal
|
|
903
|
+
* string as opaque (or compare with BigInt), never convert it to a JS number. Serials never
|
|
904
|
+
* rewind or alias after Undo, initialize or reassembly; initialize clears retained history.
|
|
905
|
+
*/
|
|
906
|
+
getCurrentInstructionSerial(): string | null;
|
|
756
907
|
/**
|
|
757
908
|
* The newest `max` entries of `getUndoGroups`, read from the top of the history without
|
|
758
909
|
* grouping the rest of it: what a panel showing the latest steps of a large history wants.
|
|
@@ -860,9 +1011,10 @@ interface JsRiscV {
|
|
|
860
1011
|
countMemoryObservers(): number;
|
|
861
1012
|
/**
|
|
862
1013
|
* Gets the next statement to be executed.
|
|
863
|
-
* @returns The next `JsProgramStatement
|
|
1014
|
+
* @returns The next `JsProgramStatement`, or null once the program has ended (`terminated`):
|
|
1015
|
+
* after an exit the statement that follows the ecall is not one the program will run.
|
|
864
1016
|
*/
|
|
865
|
-
getNextStatement(): JsProgramStatement;
|
|
1017
|
+
getNextStatement(): JsProgramStatement | null;
|
|
866
1018
|
/**
|
|
867
1019
|
* Sets the value of a register. Outside a Poke the write is direct: it records no undo step.
|
|
868
1020
|
* Inside a Poke it joins the open transaction, except for `zero`, which holds no value and so
|
|
@@ -872,10 +1024,12 @@ interface JsRiscV {
|
|
|
872
1024
|
*/
|
|
873
1025
|
setRegisterValue(register: RegisterName, high: number, low: number): void;
|
|
874
1026
|
/**
|
|
875
|
-
*
|
|
876
|
-
*
|
|
1027
|
+
* Whether the program has ended, read from its state rather than from the last run call, so
|
|
1028
|
+
* that it is right after `undo()` too: an exit service has run, or there is no statement at
|
|
1029
|
+
* the program counter because execution ran off the end. It is true as soon as the last
|
|
1030
|
+
* instruction has run. A runtime failure does not set it: the run call's rejection reports it.
|
|
877
1031
|
*/
|
|
878
|
-
terminated: boolean;
|
|
1032
|
+
readonly terminated: boolean;
|
|
879
1033
|
}
|
|
880
1034
|
/**
|
|
881
1035
|
* Creates a RISC-V simulator from a virtual source tree and its entry file.
|
|
@@ -900,4 +1054,4 @@ declare function bigintToHighLow(value: bigint): [high: number, low: number];
|
|
|
900
1054
|
*/
|
|
901
1055
|
declare function highLowToBigint(high: number, low: number): bigint;
|
|
902
1056
|
|
|
903
|
-
export { type AssemblerProfile, type AssemblyOptions, BackStepAction, ConfirmResult, type CsrRegisterName, DialogType, type FloatingPointRegisterName, type GnuUnitSymbols, type HandlerMap, type HandlerMapFns, type JsBackStep, type JsInstruction, type JsInstructionToken, type JsInstructionUndoGroup, type JsPokeMemoryWrite, type JsPokeRegisterWrite, type JsPokeUndoGroup, type JsPokeWrite, type JsProgramStatement, type JsRiscV, type JsRiscVStackFrame, type JsUndoGroup, type MemoryAccessObserver, type MemoryObserverHandle, type MemoryWriteObserver, RISCV, type RISCVAssembleError, type RISCVAssembleResult, RISCVRegisters, type RISCVSourceLocation, type RISCVSourceSet, RISCV_CSR_REGISTERS, RISCV_FLOATING_POINT_REGISTERS, RISCV_REGISTERS, type RegisterName, type RiscvTokenizedLine, type RuntimeLibrary, StopReason, bigintToHighLow, highLowToBigint, makeRiscVFromFiles, registerHandlers, unimplementedHandler };
|
|
1057
|
+
export { type AssemblerProfile, type AssemblyOptions, BackStepAction, ConfirmResult, type CsrRegisterName, DialogType, type FloatingPointRegisterName, type GnuUnitSymbols, type HandlerMap, type HandlerMapFns, type JsBackStep, type JsInstruction, type JsInstructionToken, type JsInstructionUndoGroup, type JsPokeMemoryWrite, type JsPokeRegisterWrite, type JsPokeUndoGroup, type JsPokeWrite, type JsProgramStatement, type JsRiscV, type JsRiscVStackFrame, type JsUndoGroup, type MemoryAccessObserver, type MemoryObserverHandle, type MemoryWriteObserver, type OptionalHandlerName, RISCV, type RISCVAssembleError, type RISCVAssembleResult, RISCVRegisters, type RISCVSourceLocation, type RISCVSourceSet, RISCV_CSR_REGISTERS, RISCV_FLOATING_POINT_REGISTERS, RISCV_REGISTERS, type RegisterName, type RiscvTokenizedLine, type RuntimeError, type RuntimeErrorKind, type RuntimeLibrary, StopReason, bigintToHighLow, highLowToBigint, isRuntimeError, makeRiscVFromFiles, registerHandlers, unimplementedHandler };
|