67 lines
2.4 KiB
TypeScript
67 lines
2.4 KiB
TypeScript
import { Memory, memory } from "./memory"
|
|
import { Word, wordFromString } from "./word"
|
|
|
|
export interface Ram<Width extends number> {
|
|
get(address: Word<number>): Memory<Width>
|
|
addressLength: number
|
|
values: () => Word<Width>[]
|
|
write: (value: Word<Width>, address: Word<number>) => void
|
|
read: (address: Word<number>) => Word<Width>
|
|
wordSize: Width
|
|
}
|
|
|
|
type RamDimensions<Width extends number> = { size: number, width: Width }
|
|
|
|
export function ram<Width extends number>(initialValues: string[]): Ram<Width>
|
|
export function ram<Width extends number>(initialValues: Word<Width>[]): Ram<Width>
|
|
export function ram<Width extends number>({ size, width }: RamDimensions<Width>): Ram<Width>
|
|
export function ram<Width extends number>(arg: RamDimensions<Width> | (Word<Width>[]) | string[]): Ram<Width> {
|
|
|
|
const memorySpace = unpackArgToMemoryArray(arg)
|
|
|
|
const wordSize = memorySpace[0].value().bits.length
|
|
const addressLength = Math.ceil(Math.log2(memorySpace.length))
|
|
|
|
function write(value: Word<Width>, address: Word<number>) {
|
|
memorySpace[address.toNumber()].set(value)
|
|
}
|
|
|
|
function read(address: Word<number>) {
|
|
return get(address).value()
|
|
}
|
|
|
|
function values() {
|
|
return memorySpace.map(memory => memory.value())
|
|
}
|
|
|
|
function get(address: Word<number>) {
|
|
return memorySpace[address.toNumber()]
|
|
}
|
|
|
|
return {
|
|
values,
|
|
write,
|
|
read,
|
|
get,
|
|
wordSize,
|
|
addressLength,
|
|
}
|
|
}
|
|
|
|
function unpackArgToMemoryArray<Width extends number>(arg: RamDimensions<Width> | (Word<Width>[]) | string[]) {
|
|
return isDimensionsArg(arg) ? memoryFromSizeAndWidth(arg.size, arg.width) : memoryFromArrayArg(arg)
|
|
}
|
|
|
|
function memoryFromArrayArg<Width extends number>(array: Word<Width>[] | string[]) {
|
|
const isStringArray = typeof array[0] === "string"
|
|
const words = isStringArray ? (array as string[]).map(stringValue => wordFromString(stringValue) as Word<Width>) : array as Word<Width>[]
|
|
return words.map(word => memory<Width>(word)) as Memory<Width>[]
|
|
}
|
|
|
|
function memoryFromSizeAndWidth<Width extends number>(size: number, width: Width) {
|
|
return Array(size).fill(() => 0).map(() => memory(width))
|
|
}
|
|
|
|
function isDimensionsArg<Width extends number>(arg: any): arg is RamDimensions<Width> {
|
|
return typeof arg === "object" && typeof arg.size === "number" && typeof arg.width === "number"
|
|
} |