-
Notifications
You must be signed in to change notification settings - Fork 0
/
microcodeWriter.js
103 lines (88 loc) · 4.17 KB
/
microcodeWriter.js
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
const util = require('./util.js')
const moveBit = util.moveBit
const argv = require('minimist')(process.argv.slice(2))
const microcode = require('./microcode.js')
const romWriter = require('./romWriter.js')
const chipIndex = argv.chip
if (chipIndex === undefined) {
throw new Error(`--chip=0..2 must be specified`)
}
const controlRoms = buildMicrocode()
writeMicrocode(chipIndex, controlRoms)
if (!argv.dry) {
romWriter.start()
}
function writeMicrocode(chipIndex, controlRoms) {
const romIndex = parseInt(chipIndex)
for (let address = 0; address <= 0x7fff; address += 1) {
if (controlRoms[address] === undefined) {
controlRoms[address] = microcode.getInactiveControlSignals()
const signal = microcode.Signals['HLT']
signal.setActive(controlRoms[address])
}
//console.log(`${leftPad(address.toString(16), 4)} := ${leftPad(byte.toString(2), 8)}`)
romWriter.write(address, controlRoms[address][romIndex])
}
}
function buildMicrocode() {
const controlRoms = []
//buildFetches(controlRoms)
buildInstructions(controlRoms)
console.log('buildMicrocode complete!\n\n')
return controlRoms
}
// every instruction's first microcode must load the next instruction into the Instruction Register,
// ...also increment the Instruction Pointer so that the next microcode instruction can read the next byte!
//function buildFetches(controlRoms) {
// for (let instructionId = 0; instructionId <= 255; instructionId += 1) {
// for (let flags = 0; flags <= microcode.FLAG_MASK; flags += 1) {
// buildInstructionStep(controlRoms, 'fetch', instructionId, flags, 0, 'MR IW II')
// }
// }
//}
function buildInstructions(controlRoms) {
for (const instructionName in microcode.Instructions) {
const instruction = microcode.Instructions[instructionName]
const idMin = instruction.id
let idMax = instruction.idMax
if (idMax === undefined) { idMax = idMin }
for (let instructionId = idMin; instructionId <= idMax; instructionId += 1) {
for (let flags = 0; flags <= microcode.FLAG_MASK; flags += 1) {
const controlSignalSequence = instruction.signals(flags)
const comment = `${instructionName} @${instructionId.toString(16)} f=${util.leftPad(flags.toString(2), 3)}`
buildInstruction(controlRoms, comment, instructionId, flags, controlSignalSequence)
}
}
}
}
function buildInstruction(controlRoms, comment, instructionId, flags, controlSignalSequence) {
for (let stepIndex = 0; stepIndex < controlSignalSequence.length + 1; stepIndex += 1) {
const isFinalStep = stepIndex === controlSignalSequence.length
let controlSignals = isFinalStep ? 'MR IW II NXT' : controlSignalSequence[stepIndex] // every instruction completes by fetching the next instruction (including jumps)
buildInstructionStep(controlRoms, `${comment} (step ${stepIndex})`, instructionId, flags, stepIndex, controlSignals)
}
}
function buildInstructionStep(controlRoms, comment, instructionId, flags, stepIndex, controlSignals) {
let address = 0
for (let instructionBit = 0; instructionBit <= 7; instructionBit += 1) {
address |= moveBit(instructionId, instructionBit, instructionBit)
}
address |= moveBit(stepIndex, 0, 8)
address |= moveBit(stepIndex, 1, 13)
address |= moveBit(stepIndex, 2, 14)
address |= moveBit(stepIndex, 3, 12)
address |= moveBit(flags, 0, 10)
address |= moveBit(flags, 1, 11)
address |= moveBit(flags, 2, 9)
if (controlRoms[address]) { throw new Error(`Logic error! Microcode collision at address ${address.toString(16)}`) }
controlRoms[address] = microcode.getInactiveControlSignals()
//console.log(`${controlRoms[address].map(n => util.leftPad(n.toString(2), 8)).join(' | ')} < starting from defaults`)
controlSignals.split(' ').forEach(signalName => {
if (!signalName) { return } // can be blank due to concatenating ' NXT' onto ''
const signal = microcode.Signals[signalName]
if (!signal) { throw new Error(`Unknown signalName '${signalName}'`) }
signal.setActive(controlRoms[address])
//console.log(`${controlRoms[address].map(n => util.leftPad(n.toString(2), 8)).join(' | ')} < after applying ${signalName}`)
})
console.log(`${util.leftPad(address.toString(16), 4)} : ${controlRoms[address].map(n => util.leftPad(n.toString(2), 8)).join(' | ')} // ${comment} // ${controlSignals.trim()}`)
}