@specy/risc-v 2.0.0 → 2.1.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 +54 -2
- package/dist/index.d.mts +94 -1
- package/dist/index.d.ts +94 -1
- package/dist/index.js +3566 -3135
- package/dist/index.mjs +3566 -3135
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -102,6 +102,52 @@ Synchronous handlers never yield to the event loop: the simulation runs straight
|
|
|
102
102
|
returned promise settles on a microtask. Overlapping calls are queued and run one after another,
|
|
103
103
|
never concurrently.
|
|
104
104
|
|
|
105
|
+
Program time is a handler too, so a run can be given a clock of its own: `sleep` answers syscall 32
|
|
106
|
+
and `time` answers syscall 30. A live run resolves `sleep` on a timer and returns `Date.now()` from
|
|
107
|
+
`time`; a scripted run can settle `sleep` immediately, advance a virtual clock by the requested
|
|
108
|
+
milliseconds and return that clock instead, which keeps elapsed-time output reproducible.
|
|
109
|
+
|
|
110
|
+
## Memory observers
|
|
111
|
+
|
|
112
|
+
A memory-mapped device - a framebuffer, a keyboard register - is modelled by observing the memory
|
|
113
|
+
the program reads and writes:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
// Every write in a framebuffer: (address, length, value), with the width of the store in bytes.
|
|
117
|
+
const frame = riscvSimulator.addMemoryWriteObserver(0x10010000, 0x10012ffc, (address, length, value) => {
|
|
118
|
+
screen.markDirty(address)
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
// One memory-mapped register: reads and writes, either of which may be null.
|
|
122
|
+
const receiver = riscvSimulator.addMemoryAccessObserver(
|
|
123
|
+
0xffff0004,
|
|
124
|
+
() => keyboard.consumeCharacter(),
|
|
125
|
+
null
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
riscvSimulator.removeMemoryObserver(frame)
|
|
129
|
+
riscvSimulator.removeMemoryObservers()
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
* Addresses must be word-aligned, `endAddress` is inclusive and covers its whole word, and a range
|
|
133
|
+
may not cross `0x80000000`; a registration that breaks any of these throws. Either form of a
|
|
134
|
+
high address is accepted: `0xffff0000` and `0xffff0000 | 0` name the same word.
|
|
135
|
+
* Handlers are given signed 32 bit integers, as the guest holds them: the register at
|
|
136
|
+
`0xffff000c` arrives as `-65524`, and a pixel word with its high bit set arrives negative.
|
|
137
|
+
Apply `>>> 0` wherever the unsigned form is wanted.
|
|
138
|
+
* Handlers run synchronously inside the instruction that caused the access, so they must be cheap
|
|
139
|
+
and must not write back into their own range. A returned promise is ignored, unlike an IO
|
|
140
|
+
handler's.
|
|
141
|
+
* An observer is notified *after* the access, with the value the program read or stored. A
|
|
142
|
+
register whose value is consumed by reading it must therefore be reloaded from the handler,
|
|
143
|
+
with `setPeripheralWord`, for the next read.
|
|
144
|
+
* Observers live on the simulator's memory, which assembling and initializing only clear the
|
|
145
|
+
contents of, so a registration survives `assemble()` and `initialize()` and - like a registered
|
|
146
|
+
IO handler - is shared by every `JsRiscV` instance. Notifications start once a program has been
|
|
147
|
+
assembled.
|
|
148
|
+
* `undo()` restores memory through the same stores, so an observed range reports the restored
|
|
149
|
+
values as ordinary writes and a device that follows notifications alone stays in step.
|
|
150
|
+
|
|
105
151
|
## API
|
|
106
152
|
|
|
107
153
|
### `RISCV` Static Class
|
|
@@ -145,8 +191,14 @@ This interface provides methods to control and interact with a RISC-V simulator
|
|
|
145
191
|
* `getConditionFlags(): number[]`: Gets the 8 condition flags (if applicable, typically related to floating-point or custom extensions).
|
|
146
192
|
* `registerHandler<T extends HandlerName>(name: T, handler: (...args: HandlerMap[T]['in']) => HandlerMap[T]['out'] | Promise<HandlerMap[T]['out']>): void`: Registers a handler function for a specific event (e.g., syscalls). See `HandlerName`, `HandlerMap` and [IO handlers](#io-handlers) for details.
|
|
147
193
|
* `getUndoStack(): JsBackStep[]`: Returns the undo stack, an array of `JsBackStep` objects representing simulation history.
|
|
148
|
-
* `readMemoryBytes(address: number, length: number): number[]`: Reads `length` bytes from memory starting at `address`. Returns an array of byte values.
|
|
149
|
-
* `setMemoryBytes(address: number, bytes: number[]): void`: Writes an array of `bytes` to memory starting at `address
|
|
194
|
+
* `readMemoryBytes(address: number, length: number): number[]`: Reads `length` bytes from memory starting at `address`. Returns an array of byte values. Notifies no memory observer: inspecting memory from the host is not the program reading it.
|
|
195
|
+
* `setMemoryBytes(address: number, bytes: number[]): void`: Writes an array of `bytes` to memory starting at `address`, the way the program does: write observers are notified and, while undo is enabled, an undo step is recorded per byte.
|
|
196
|
+
* `setPeripheralWord(address: number, value: number): void`: Writes one word-aligned word as a peripheral would, notifying no observer and recording no undo step. See [memory observers](#memory-observers).
|
|
197
|
+
* `addMemoryWriteObserver(startAddress: number, endAddress: number, handler): number`: Observes every write in an address range. See [memory observers](#memory-observers).
|
|
198
|
+
* `addMemoryAccessObserver(address: number, onRead, onWrite): number`: Observes reads and writes of one word. See [memory observers](#memory-observers).
|
|
199
|
+
* `removeMemoryObserver(handle: number): void`: Removes one registration.
|
|
200
|
+
* `removeMemoryObservers(): void`: Removes every registration.
|
|
201
|
+
* `countMemoryObservers(): number`: The number of live registrations.
|
|
150
202
|
* `getCurrentStatementIndex(): number`: Returns the index of the current instruction in the list of assembled program statements.
|
|
151
203
|
* `getNextStatement(): JsProgramStatement | null`: Returns the next `JsProgramStatement` to be executed, or `null` if at the end.
|
|
152
204
|
* `getStatementAtAddress(address: number): JsProgramStatement | null`: Gets the program statement at the given memory `address`.
|
package/dist/index.d.mts
CHANGED
|
@@ -119,10 +119,23 @@ type HandlerMap = {
|
|
|
119
119
|
in: [l: string];
|
|
120
120
|
out: void;
|
|
121
121
|
};
|
|
122
|
+
/**
|
|
123
|
+
* Syscall 32: the program asks to be suspended for this many milliseconds. Return a promise
|
|
124
|
+
* that settles when the wait is over to suspend the simulation without blocking the host.
|
|
125
|
+
*/
|
|
122
126
|
sleep: {
|
|
123
127
|
in: [milliseconds: number];
|
|
124
128
|
out: void;
|
|
125
129
|
};
|
|
130
|
+
/**
|
|
131
|
+
* Syscall 30: the program time in milliseconds, split by the syscall into a0 (low word) and
|
|
132
|
+
* a1 (high word). Answer with `Date.now()` for a live run, or with a virtual clock for a
|
|
133
|
+
* scripted one, so that elapsed-time output stays reproducible.
|
|
134
|
+
*/
|
|
135
|
+
time: {
|
|
136
|
+
in: [];
|
|
137
|
+
out: number;
|
|
138
|
+
};
|
|
126
139
|
stdIn: {
|
|
127
140
|
in: [buffer: number[], length: number];
|
|
128
141
|
out: void;
|
|
@@ -136,6 +149,27 @@ type HandlerMap = {
|
|
|
136
149
|
out: void;
|
|
137
150
|
};
|
|
138
151
|
};
|
|
152
|
+
/**
|
|
153
|
+
* Notified after a write anywhere in an observed address range.
|
|
154
|
+
*
|
|
155
|
+
* `length` is the width of the access in bytes (4, 2 or 1) and `value` is what the program stored,
|
|
156
|
+
* so a byte or halfword store reports only the bytes it touched; a peripheral that mirrors whole
|
|
157
|
+
* words should re-read the containing word with `readMemoryBytes` rather than trust `value`.
|
|
158
|
+
*
|
|
159
|
+
* Both `address` and `value` are signed 32 bit integers, as the guest holds them: the register at
|
|
160
|
+
* `0xffff000c` arrives as `-65524`, and a pixel word with its high bit set arrives negative too.
|
|
161
|
+
* Apply `>>> 0` wherever the unsigned form is wanted.
|
|
162
|
+
*/
|
|
163
|
+
type MemoryWriteObserver = (address: number, length: number, value: number) => void;
|
|
164
|
+
/**
|
|
165
|
+
* Notified after a read or a write of one observed word, with the same signed 32 bit numbers as
|
|
166
|
+
* `MemoryWriteObserver`. `value` is the value the program read or stored; on a read it is what
|
|
167
|
+
* memory held *before* the observer ran, so a register whose value is consumed by reading it must
|
|
168
|
+
* be reloaded from the handler for the next read.
|
|
169
|
+
*/
|
|
170
|
+
type MemoryAccessObserver = (address: number, value: number) => void;
|
|
171
|
+
/** Identifies one registration, for `removeMemoryObserver`. */
|
|
172
|
+
type MemoryObserverHandle = number;
|
|
139
173
|
type JsInstruction = {
|
|
140
174
|
name: string;
|
|
141
175
|
example: string;
|
|
@@ -158,7 +192,10 @@ type RISCVAssembleError = {
|
|
|
158
192
|
type RISCVAssembleResult = {
|
|
159
193
|
report: string;
|
|
160
194
|
errors: RISCVAssembleError[];
|
|
195
|
+
/** True only when at least one diagnostic is a real error; warnings alone leave the assembled program runnable. */
|
|
161
196
|
hasErrors: boolean;
|
|
197
|
+
/** True when at least one diagnostic is a warning. */
|
|
198
|
+
hasWarnings: boolean;
|
|
162
199
|
};
|
|
163
200
|
declare class RISCV {
|
|
164
201
|
static makeRiscVFromSource: typeof makeRiscVfromSource;
|
|
@@ -456,6 +493,9 @@ interface JsRiscV {
|
|
|
456
493
|
getUndoStack(): JsBackStep[];
|
|
457
494
|
/**
|
|
458
495
|
* Reads a sequence of bytes from memory.
|
|
496
|
+
*
|
|
497
|
+
* Reading through this method notifies no memory observer: inspecting memory from the host is
|
|
498
|
+
* not the program reading it, so a memory viewer never drives a memory-mapped register.
|
|
459
499
|
* @param address The starting memory address.
|
|
460
500
|
* @param length The number of bytes to read.
|
|
461
501
|
* @returns An array of bytes read from memory.
|
|
@@ -463,10 +503,63 @@ interface JsRiscV {
|
|
|
463
503
|
readMemoryBytes(address: number, length: number): number[];
|
|
464
504
|
/**
|
|
465
505
|
* Writes a sequence of bytes to memory.
|
|
506
|
+
*
|
|
507
|
+
* Unlike `readMemoryBytes`, this writes the way the program does: it notifies write observers
|
|
508
|
+
* and, while undo is enabled, records an undo step per byte. Use `setPeripheralWord` for a
|
|
509
|
+
* device keeping its own register up to date.
|
|
466
510
|
* @param address The starting memory address.
|
|
467
511
|
* @param bytes An array of bytes to write to memory.
|
|
468
512
|
*/
|
|
469
513
|
setMemoryBytes(address: number, bytes: number[]): void;
|
|
514
|
+
/**
|
|
515
|
+
* Writes one word as a peripheral would: no observer is notified and no undo step is recorded,
|
|
516
|
+
* because the write is not the program acting. This is how a device model refreshes a
|
|
517
|
+
* memory-mapped register - a ready bit, a pending character - without feeding its own observer
|
|
518
|
+
* or consuming undo history.
|
|
519
|
+
* @param address The word address, which must be word-aligned. Either form of a high address
|
|
520
|
+
* is accepted: `0xffff0000` and `0xffff0000 | 0` name the same word.
|
|
521
|
+
* @param value The 32 bit value to store, raw, without byte-order adjustment.
|
|
522
|
+
*/
|
|
523
|
+
setPeripheralWord(address: number, value: number): void;
|
|
524
|
+
/**
|
|
525
|
+
* Observes every write in an address range, the shape a framebuffer wants.
|
|
526
|
+
*
|
|
527
|
+
* Both addresses must be word-aligned, `endAddress` is inclusive and covers its whole word, and
|
|
528
|
+
* the range may not cross 0x80000000 (split it in two registrations instead); a range that
|
|
529
|
+
* breaks any of these throws. Either form of a high address is accepted: `0xffff0000` and
|
|
530
|
+
* `0xffff0000 | 0` name the same word. The handler runs synchronously inside the storing instruction, so
|
|
531
|
+
* it must be cheap and must not write back into its own range; a returned promise is ignored.
|
|
532
|
+
*
|
|
533
|
+
* Observers live on the simulator's memory, which assembling and initializing only clear the
|
|
534
|
+
* contents of, so a registration survives `assemble()` and `initialize()`. For the same reason
|
|
535
|
+
* it is shared by every `JsRiscV` instance: register once per page, or remove the previous
|
|
536
|
+
* registration before registering again for a newly built program.
|
|
537
|
+
*
|
|
538
|
+
* Notifications only start once a program has been assembled, and undo notifies too: restoring
|
|
539
|
+
* memory during `undo()` goes through the same stores, so an observed range reports the
|
|
540
|
+
* restored values as ordinary writes.
|
|
541
|
+
* @returns A handle for `removeMemoryObserver`.
|
|
542
|
+
*/
|
|
543
|
+
addMemoryWriteObserver(startAddress: number, endAddress: number, handler: MemoryWriteObserver): MemoryObserverHandle;
|
|
544
|
+
/**
|
|
545
|
+
* Observes reads and writes of a single word, the shape a memory-mapped register wants. The
|
|
546
|
+
* address must be word-aligned. Pass `null` for a direction you do not care about. The same
|
|
547
|
+
* lifetime and synchronous-handler rules as `addMemoryWriteObserver` apply.
|
|
548
|
+
* @returns A handle for `removeMemoryObserver`.
|
|
549
|
+
*/
|
|
550
|
+
addMemoryAccessObserver(address: number, onRead: MemoryAccessObserver | null, onWrite: MemoryAccessObserver | null): MemoryObserverHandle;
|
|
551
|
+
/**
|
|
552
|
+
* Removes one registration. An unknown handle is ignored.
|
|
553
|
+
*/
|
|
554
|
+
removeMemoryObserver(handle: MemoryObserverHandle): void;
|
|
555
|
+
/**
|
|
556
|
+
* Removes every registration.
|
|
557
|
+
*/
|
|
558
|
+
removeMemoryObservers(): void;
|
|
559
|
+
/**
|
|
560
|
+
* The number of live registrations, across every `JsRiscV` instance.
|
|
561
|
+
*/
|
|
562
|
+
countMemoryObservers(): number;
|
|
470
563
|
/**
|
|
471
564
|
* Gets the index of the current statement in the assembled program.
|
|
472
565
|
* @returns The index of the current statement.
|
|
@@ -501,4 +594,4 @@ declare function makeRiscVfromSource(source: string): JsRiscV;
|
|
|
501
594
|
declare function initializeRISCV(): void;
|
|
502
595
|
declare function bigintToHighLow(value: bigint): [high: number, low: number];
|
|
503
596
|
|
|
504
|
-
export { BackStepAction, ConfirmResult, DialogType, type HandlerMap, type HandlerMapFns, type JsBackStep, type JsInstruction, type JsInstructionToken, type JsProgramStatement, type JsRiscV, type JsRiscVStackFrame, RISCV, type RISCVAssembleError, type RISCVAssembleResult, RISCVRegisters, RISCV_REGISTERS, type RegisterName, type RiscvTokenizedLine, StopReason, bigintToHighLow, registerHandlers, unimplementedHandler };
|
|
597
|
+
export { BackStepAction, ConfirmResult, DialogType, type HandlerMap, type HandlerMapFns, type JsBackStep, type JsInstruction, type JsInstructionToken, type JsProgramStatement, type JsRiscV, type JsRiscVStackFrame, type MemoryAccessObserver, type MemoryObserverHandle, type MemoryWriteObserver, RISCV, type RISCVAssembleError, type RISCVAssembleResult, RISCVRegisters, RISCV_REGISTERS, type RegisterName, type RiscvTokenizedLine, StopReason, bigintToHighLow, registerHandlers, unimplementedHandler };
|
package/dist/index.d.ts
CHANGED
|
@@ -119,10 +119,23 @@ type HandlerMap = {
|
|
|
119
119
|
in: [l: string];
|
|
120
120
|
out: void;
|
|
121
121
|
};
|
|
122
|
+
/**
|
|
123
|
+
* Syscall 32: the program asks to be suspended for this many milliseconds. Return a promise
|
|
124
|
+
* that settles when the wait is over to suspend the simulation without blocking the host.
|
|
125
|
+
*/
|
|
122
126
|
sleep: {
|
|
123
127
|
in: [milliseconds: number];
|
|
124
128
|
out: void;
|
|
125
129
|
};
|
|
130
|
+
/**
|
|
131
|
+
* Syscall 30: the program time in milliseconds, split by the syscall into a0 (low word) and
|
|
132
|
+
* a1 (high word). Answer with `Date.now()` for a live run, or with a virtual clock for a
|
|
133
|
+
* scripted one, so that elapsed-time output stays reproducible.
|
|
134
|
+
*/
|
|
135
|
+
time: {
|
|
136
|
+
in: [];
|
|
137
|
+
out: number;
|
|
138
|
+
};
|
|
126
139
|
stdIn: {
|
|
127
140
|
in: [buffer: number[], length: number];
|
|
128
141
|
out: void;
|
|
@@ -136,6 +149,27 @@ type HandlerMap = {
|
|
|
136
149
|
out: void;
|
|
137
150
|
};
|
|
138
151
|
};
|
|
152
|
+
/**
|
|
153
|
+
* Notified after a write anywhere in an observed address range.
|
|
154
|
+
*
|
|
155
|
+
* `length` is the width of the access in bytes (4, 2 or 1) and `value` is what the program stored,
|
|
156
|
+
* so a byte or halfword store reports only the bytes it touched; a peripheral that mirrors whole
|
|
157
|
+
* words should re-read the containing word with `readMemoryBytes` rather than trust `value`.
|
|
158
|
+
*
|
|
159
|
+
* Both `address` and `value` are signed 32 bit integers, as the guest holds them: the register at
|
|
160
|
+
* `0xffff000c` arrives as `-65524`, and a pixel word with its high bit set arrives negative too.
|
|
161
|
+
* Apply `>>> 0` wherever the unsigned form is wanted.
|
|
162
|
+
*/
|
|
163
|
+
type MemoryWriteObserver = (address: number, length: number, value: number) => void;
|
|
164
|
+
/**
|
|
165
|
+
* Notified after a read or a write of one observed word, with the same signed 32 bit numbers as
|
|
166
|
+
* `MemoryWriteObserver`. `value` is the value the program read or stored; on a read it is what
|
|
167
|
+
* memory held *before* the observer ran, so a register whose value is consumed by reading it must
|
|
168
|
+
* be reloaded from the handler for the next read.
|
|
169
|
+
*/
|
|
170
|
+
type MemoryAccessObserver = (address: number, value: number) => void;
|
|
171
|
+
/** Identifies one registration, for `removeMemoryObserver`. */
|
|
172
|
+
type MemoryObserverHandle = number;
|
|
139
173
|
type JsInstruction = {
|
|
140
174
|
name: string;
|
|
141
175
|
example: string;
|
|
@@ -158,7 +192,10 @@ type RISCVAssembleError = {
|
|
|
158
192
|
type RISCVAssembleResult = {
|
|
159
193
|
report: string;
|
|
160
194
|
errors: RISCVAssembleError[];
|
|
195
|
+
/** True only when at least one diagnostic is a real error; warnings alone leave the assembled program runnable. */
|
|
161
196
|
hasErrors: boolean;
|
|
197
|
+
/** True when at least one diagnostic is a warning. */
|
|
198
|
+
hasWarnings: boolean;
|
|
162
199
|
};
|
|
163
200
|
declare class RISCV {
|
|
164
201
|
static makeRiscVFromSource: typeof makeRiscVfromSource;
|
|
@@ -456,6 +493,9 @@ interface JsRiscV {
|
|
|
456
493
|
getUndoStack(): JsBackStep[];
|
|
457
494
|
/**
|
|
458
495
|
* Reads a sequence of bytes from memory.
|
|
496
|
+
*
|
|
497
|
+
* Reading through this method notifies no memory observer: inspecting memory from the host is
|
|
498
|
+
* not the program reading it, so a memory viewer never drives a memory-mapped register.
|
|
459
499
|
* @param address The starting memory address.
|
|
460
500
|
* @param length The number of bytes to read.
|
|
461
501
|
* @returns An array of bytes read from memory.
|
|
@@ -463,10 +503,63 @@ interface JsRiscV {
|
|
|
463
503
|
readMemoryBytes(address: number, length: number): number[];
|
|
464
504
|
/**
|
|
465
505
|
* Writes a sequence of bytes to memory.
|
|
506
|
+
*
|
|
507
|
+
* Unlike `readMemoryBytes`, this writes the way the program does: it notifies write observers
|
|
508
|
+
* and, while undo is enabled, records an undo step per byte. Use `setPeripheralWord` for a
|
|
509
|
+
* device keeping its own register up to date.
|
|
466
510
|
* @param address The starting memory address.
|
|
467
511
|
* @param bytes An array of bytes to write to memory.
|
|
468
512
|
*/
|
|
469
513
|
setMemoryBytes(address: number, bytes: number[]): void;
|
|
514
|
+
/**
|
|
515
|
+
* Writes one word as a peripheral would: no observer is notified and no undo step is recorded,
|
|
516
|
+
* because the write is not the program acting. This is how a device model refreshes a
|
|
517
|
+
* memory-mapped register - a ready bit, a pending character - without feeding its own observer
|
|
518
|
+
* or consuming undo history.
|
|
519
|
+
* @param address The word address, which must be word-aligned. Either form of a high address
|
|
520
|
+
* is accepted: `0xffff0000` and `0xffff0000 | 0` name the same word.
|
|
521
|
+
* @param value The 32 bit value to store, raw, without byte-order adjustment.
|
|
522
|
+
*/
|
|
523
|
+
setPeripheralWord(address: number, value: number): void;
|
|
524
|
+
/**
|
|
525
|
+
* Observes every write in an address range, the shape a framebuffer wants.
|
|
526
|
+
*
|
|
527
|
+
* Both addresses must be word-aligned, `endAddress` is inclusive and covers its whole word, and
|
|
528
|
+
* the range may not cross 0x80000000 (split it in two registrations instead); a range that
|
|
529
|
+
* breaks any of these throws. Either form of a high address is accepted: `0xffff0000` and
|
|
530
|
+
* `0xffff0000 | 0` name the same word. The handler runs synchronously inside the storing instruction, so
|
|
531
|
+
* it must be cheap and must not write back into its own range; a returned promise is ignored.
|
|
532
|
+
*
|
|
533
|
+
* Observers live on the simulator's memory, which assembling and initializing only clear the
|
|
534
|
+
* contents of, so a registration survives `assemble()` and `initialize()`. For the same reason
|
|
535
|
+
* it is shared by every `JsRiscV` instance: register once per page, or remove the previous
|
|
536
|
+
* registration before registering again for a newly built program.
|
|
537
|
+
*
|
|
538
|
+
* Notifications only start once a program has been assembled, and undo notifies too: restoring
|
|
539
|
+
* memory during `undo()` goes through the same stores, so an observed range reports the
|
|
540
|
+
* restored values as ordinary writes.
|
|
541
|
+
* @returns A handle for `removeMemoryObserver`.
|
|
542
|
+
*/
|
|
543
|
+
addMemoryWriteObserver(startAddress: number, endAddress: number, handler: MemoryWriteObserver): MemoryObserverHandle;
|
|
544
|
+
/**
|
|
545
|
+
* Observes reads and writes of a single word, the shape a memory-mapped register wants. The
|
|
546
|
+
* address must be word-aligned. Pass `null` for a direction you do not care about. The same
|
|
547
|
+
* lifetime and synchronous-handler rules as `addMemoryWriteObserver` apply.
|
|
548
|
+
* @returns A handle for `removeMemoryObserver`.
|
|
549
|
+
*/
|
|
550
|
+
addMemoryAccessObserver(address: number, onRead: MemoryAccessObserver | null, onWrite: MemoryAccessObserver | null): MemoryObserverHandle;
|
|
551
|
+
/**
|
|
552
|
+
* Removes one registration. An unknown handle is ignored.
|
|
553
|
+
*/
|
|
554
|
+
removeMemoryObserver(handle: MemoryObserverHandle): void;
|
|
555
|
+
/**
|
|
556
|
+
* Removes every registration.
|
|
557
|
+
*/
|
|
558
|
+
removeMemoryObservers(): void;
|
|
559
|
+
/**
|
|
560
|
+
* The number of live registrations, across every `JsRiscV` instance.
|
|
561
|
+
*/
|
|
562
|
+
countMemoryObservers(): number;
|
|
470
563
|
/**
|
|
471
564
|
* Gets the index of the current statement in the assembled program.
|
|
472
565
|
* @returns The index of the current statement.
|
|
@@ -501,4 +594,4 @@ declare function makeRiscVfromSource(source: string): JsRiscV;
|
|
|
501
594
|
declare function initializeRISCV(): void;
|
|
502
595
|
declare function bigintToHighLow(value: bigint): [high: number, low: number];
|
|
503
596
|
|
|
504
|
-
export { BackStepAction, ConfirmResult, DialogType, type HandlerMap, type HandlerMapFns, type JsBackStep, type JsInstruction, type JsInstructionToken, type JsProgramStatement, type JsRiscV, type JsRiscVStackFrame, RISCV, type RISCVAssembleError, type RISCVAssembleResult, RISCVRegisters, RISCV_REGISTERS, type RegisterName, type RiscvTokenizedLine, StopReason, bigintToHighLow, registerHandlers, unimplementedHandler };
|
|
597
|
+
export { BackStepAction, ConfirmResult, DialogType, type HandlerMap, type HandlerMapFns, type JsBackStep, type JsInstruction, type JsInstructionToken, type JsProgramStatement, type JsRiscV, type JsRiscVStackFrame, type MemoryAccessObserver, type MemoryObserverHandle, type MemoryWriteObserver, RISCV, type RISCVAssembleError, type RISCVAssembleResult, RISCVRegisters, RISCV_REGISTERS, type RegisterName, type RiscvTokenizedLine, StopReason, bigintToHighLow, registerHandlers, unimplementedHandler };
|