move firmware files into dedicated folder

This commit is contained in:
Arthur Lu
2022-08-11 21:44:18 -07:00
parent 4dd7faf066
commit 652ecf2686
5 changed files with 1 additions and 1 deletions

138
firmware/assembler.py Normal file
View File

@@ -0,0 +1,138 @@
from re import M
import sys
from tqdm import tqdm
reg_map = {
'r0': 0,
'r1': 1,
'r2': 2,
'r3': 3,
'r4': 4,
'r5': 5,
'r6': 6,
'r7': 7,
'r8': 8,
'r9': 9,
'r10': 10,
'r11': 11,
'r12': 12,
'r13': 13,
'r14': 14,
'r15': 15
}
op_type = {
'LDI': 'I',
'PUT': 'A',
'GET': 'A',
'LDW': 'S',
'STW': 'S',
'NXT': 'S',
'CLB': 'G',
'ADD': 'A',
'SUB': 'A',
'ORR': 'A',
'AND': 'A',
'LSH': 'T',
'PTY': 'G',
'CHK': 'A',
'XOR': 'A',
'JNZ': 'G',
'JEZ': 'G',
'JMP': 'G',
'JAL': 'G'
}
op_codes = {
'LDI': 0b1_0000_0000,
'PUT': 0b0_0000_0000,
'GET': 0b0_0001_0000,
'LDW': 0b0_0010_0000,
'STW': 0b0_0010_1000,
'NXT': 0b0_0011_0000,
'CLB': 0b0_0011_1000,
'ADD': 0b0_0100_0000,
'SUB': 0b0_0101_0000,
'ORR': 0b0_0110_0000,
'AND': 0b0_0111_0000,
'LSH': 0b0_1000_0000,
'PTY': 0b0_1000_1000,
'CHK': 0b0_1001_0000,
'XOR': 0b0_1010_0000,
'JNZ': 0b0_1110_0000,
'JEZ': 0b0_1110_1000,
'JMP': 0b0_1111_0000,
'JAL': 0b0_1111_1000,
'NOP': 0b0_1000_0000
}
def get_reg(type, opcode):
if type == 'S':
return reg_map[opcode] - 8
elif type == 'G':
return reg_map[opcode]
elif type == 'A':
return reg_map[opcode]
else:
print('invalid opcode detected: ' + opcode)
exit(1)
def get_immediate(operand, labels):
if operand.startswith("#b"):
operand = operand.strip("#b")
return int(operand, 2)
elif operand.startswith("#x"):
operand = operand.strip("#x")
return int(operand, 16)
elif operand.startswith("#d"):
operand = operand.strip("#d")
return int(operand, 10)
elif operand in labels:
return labels[operand]
else:
print('invalid immediate detected: ' + operand)
exit(1)
output = sys.argv[1]
targets = sys.argv[2:]
out = open(output, "wb")
print('detected targets: ' + str(targets))
for file in targets:
print('assembing: ' + file)
no_comments = []
instructions = []
labels = {}
index = 0
raw_lines = []
instructions = []
f = open(file, 'r')
for line in f:
raw_lines.append(line)
for line in tqdm(raw_lines, desc='Preprocessing', unit=' lines'):
line = line.split('//')[0] # remove comments
if line != '':
line = line.replace('\t', '') # remove leading tabs
line = line.replace('\n', '') # remove trailing newline
if ': ' in line:
labels[line.split(': ')[0]] = index # ': ' must be used to end a label
no_comments.append(line.split(': ')[1])
else:
no_comments.append(line)
index += 1
index = 0
for line in tqdm(no_comments, desc='Operand', unit=' operands'):
line = line.split(' ')
opcode = line[0]
operand = line[1]
if op_type[opcode] == "I" or op_type[opcode] == "T":
operand = get_immediate(operand, labels)
else:
operand = get_reg(op_type[opcode], operand)
instructions.append((opcode, operand))
index += 1
for i in tqdm(range(len(instructions), 256), desc='Paging', unit='instructions'):
instructions.append(("NOP", 0b0_0000_0000)) # append many NOPs to fill up the 256 instruction program block
for inst in tqdm(instructions, desc='Assembly', unit=' instructions'):
opcode = op_codes[inst[0]]
operand = inst[1]
out.write((opcode| operand).to_bytes(length=2, byteorder='big'))

2
firmware/example.sh Normal file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
python assembler.py cse141L.bin program1.asm program2.asm program3.asm

66
firmware/program1.asm Normal file
View File

@@ -0,0 +1,66 @@
// Program 1 register use map:
// r0 is the accumulator, r1 is often used to cache temp values
// r6 is LFSR tap pattern
// r7 is LFSR state value
// r8 is the preamble counter
// r9 is the total encryption length counter
// r11 is the read pointer
// r12 is the write pointer
init: LDI #d62
PUT r8
LDW r8
PUT r6 // tap will now be in r6
LDI #d63
PUT r8
LDW r8
PUT r7 // state will now be in r7
LDI #d0
PUT r11 // init read incrementer to 0
LDI #d64
PUT r12 // init write incrementer to 64
LDI #d61
PUT r8
LDW r8
PUT r8 // init r8 decrementer with number of preamble space chars
LDI #d64
PUT r9 // init r9 decrementer to total number of possible ciphertext chars
preamble_loop: LDI #d32 // get space character decimal 32
XOR r7 // bitwise XOR the current state with plaintext space to generate ciphertext
CLB r0 // clear the leading bit of the ciphertext as in requirements
STW r12 // store ciphertext to write pointer
LDI lfsr_routine // load address for the lfsr_routine label
JAL r0 // jump to the lfsr_routine label
NXT r12 // increment write pointer
NXT r9 // decrement number of remaining ciphertext characters
LDI main_loop // load the address of label main_loop
NXT r8 // decrement preamble counter
JEZ r0 // exit preamble loop if the preamble counter has just reached 0
LDI preamble_loop // load the address of label preamble_loop
JMP r0 // jump to preamble_loop if there are more space characters to encode
main_loop: LDW r11 // load the next plaintext byte
XOR r7 // bitwise XOR the current state with plaintext space to generate ciphertext
CLB r0 // clear the leading bit of the ciphertext as in requirements
STW r12 // store ciphertext to write pointer
LDI lfsr_routine // load address for the lfsr_routine label
JAL r0 // jump to the lfsr_routine label
NXT r11 // increment read pointer
NXT r12 // increment write pointer
LDI done // load address of label done
NXT r9 // decrement number of remaining ciphertext chars
JEZ r0 // jump to end of program if all ciphertext chars have been processed
LDI main_loop // load address of main_loop
JMP r0 // jump to main_loop if there is still space for message characters
lfsr_routine: GET r7 // get previous state
AND r6 // and state with taps to get feedback pattern
PTY r0 // get feedback parity bit
PUT r1 // store feedback bit to r1 temporarily
GET r7 // get previous state again
LSH #d1 // left shift previous state by 1
ORR r1 // or with parity bit to get next state
PUT r7 // put next state to r7
GET r14 // load link register
JMP r0 // return to function call address
done: LDI #b10000000 // load the processor flag state needed to halt the program
PUT r15 // put and set the done flag to 1 to halt the PC and indicate the program has finished
LDI #d255
JMP r0

107
firmware/program2.asm Normal file
View File

@@ -0,0 +1,107 @@
// Program 2 register use map:
// r0 is the accumulator, r1 is often used to cache temp values
// r5 is the TAP LUT link register
// r6 is LFSR tap pattern
// r7 is LFSR state value
// r8 is the preamble counter
// r9 is the total encryption length counter
// r10 is the tap selection counter
// r11 is the read pointer
// r12 is the write pointer
init: LDI #d10
PUT r10 // set the tap counter to 10, which will choose tap pattern 9 to start after subtracting by 1
tap_lut: LDI tap_init
JMP r0 // goto tap_init, skipping the LUT
LDI #x60 // load tap pattern 1
JMP r5 // jump back to tap loop
LDI #x48 // load tap pattern 2
JMP r5 // jump back to tap loop
LDI #x78 // load tap pattern 3
JMP r5 // jump back to tap loop
LDI #x72 // load tap pattern 4
JMP r5 // jump back to tap loop
LDI #x6A // load tap pattern 5
JMP r5 // jump back to tap loop
LDI #x69 // load tap pattern 6
JMP r5 // jump back to tap loop
LDI #x5C // load tap pattern 7
JMP r5 // jump back to tap loop
LDI #x7E // load tap pattern 8
JMP r5 // jump back to tap loop
LDI #x7B // load tap pattern 9
JMP r5 // jump back to tap loop
tap_init: LDI #d64
PUT r11 // set read pointer to 64
LDI #d0
PUT r12 // set write pointer to 0
LDI #d10
PUT r8 // load 10 into preamble counter
LDI #d64
PUT r9 // load 64 (total encryption length) to r9
LDI done
NXT r10 // decrement tap selection by 1, starts at 9 for the first iteration
JEZ r0 // if no more taps left that didn't work, raise the done flag
LDI tap_init
PUT r5 // put the tap_loop address in r5
LDI tap_lut
ADD r10
ADD r10 // add 2*tap select to tap_lut location, results in location of selected tap pattern
JMP r0 // jump to LUT, which loads the tap pattern into r0
PUT r6 // tap pattern now in r6
LDW r11 // get the first preamble character
PUT r1 // put cipher text into r1
LDI #d32 // load expected space character
STW r12 // write initial space into memory
XOR r1 // get the initial state
PUT r7 // put initial state guess into r7
NXT r11 // increment read pointer
NXT r12 // increment write pointer
NXT r9 // decrement total encryption chars remaining
tap_loop: LDI lfsr_routine
JAL r0 // jump to lfsr routine which calculates next state in r7
LDI #d32 // load space char expected plaintext
XOR r7
CLB r0 // clear leading bit in the expected ciphertext
PUT r1 // store expected cipher text in r1
LDI tap_init
PUT r2 // load the outer loop top into r2
LDW r11 // load actual ciphertext
SUB r1 // subtract actual from expected, result of 0 means matching
JNZ r2 // jump to outer loop (picks new tap pattern) if the actual cipher was not equal to the expected
LDI #d32 // load preamble char
STW r12 // store preamble char in memory
NXT r11 // increment read pointer
NXT r12 // increment write pointer
NXT r9 // decrement total encryption chars remaining
LDI main_loop // load main_loop location into r0
NXT r8 // decrement preamble counter
JEZ r0 // if r8 (preamble counter) is zero, then all preamble have matched and current tap pattern is correct, jump to main loop
LDI tap_loop
JMP r0 // jump to tap_loop if characters matched but preamble is not over
main_loop: LDW r11 // load the next ciphertext byte
XOR r7 // bitwise XOR the current state with ciphertext space to generate plaintext
CLB r0 // clear the leading bit of the plaintext as in requirements
STW r12 // store plaintext to write pointer
LDI lfsr_routine // load address for the lfsr_routine label
JAL r0 // jump to the lfsr_routine label
NXT r11 // increment read pointer
NXT r12 // increment write pointer
LDI done // load address of label done
NXT r9 // decrement number of remaining plaintext chars
JEZ r0 // jump to end of program if all plaintext chars have been processed
LDI main_loop // load address of main_loop
JMP r0 // jump to main_loop if there is still space for message characters
lfsr_routine: GET r7 // get previous state
AND r6 // and state with taps to get feedback pattern
PTY r0 // get feedback parity bit
PUT r1 // store feedback bit to r1 temporarily
GET r7 // get previous state again
LSH #d1 // left shift previous state by 1
ORR r1 // or with parity bit to get next state
PUT r7 // put next state to r7
GET r14 // load link register
JMP r0 // return to function call address
done: LDI #b10000000 // load the processor flag state needed to halt the program
PUT r15 // put and set the done flag to 1 to halt the PC and indicate the program has finished
LDI #d255
JMP r0

115
firmware/program3.asm Normal file
View File

@@ -0,0 +1,115 @@
// Program 3 register use map:
// r0 is the accumulator, r1 and r2 is often used to cache temp values
// r5 is the TAP LUT link register
// r6 is LFSR tap pattern
// r7 is LFSR state value
// r8 is the preamble counter
// r9 is the total encryption length counter
// r10 is the tap selection counter
// r11 is the read pointer
// r12 is the write pointer
init: LDI #d10
PUT r10 // set the tap counter to 10, which will choose tap pattern 9 to start after subtracting by 1
tap_lut: LDI tap_init
JMP r0 // goto tap_init, skipping the LUT
LDI #x60 // load tap pattern 1
JMP r5 // jump back to tap loop
LDI #x48 // load tap pattern 2
JMP r5 // jump back to tap loop
LDI #x78 // load tap pattern 3
JMP r5 // jump back to tap loop
LDI #x72 // load tap pattern 4
JMP r5 // jump back to tap loop
LDI #x6A // load tap pattern 5
JMP r5 // jump back to tap loop
LDI #x69 // load tap pattern 6
JMP r5 // jump back to tap loop
LDI #x5C // load tap pattern 7
JMP r5 // jump back to tap loop
LDI #x7E // load tap pattern 8
JMP r5 // jump back to tap loop
LDI #x7B // load tap pattern 9
JMP r5 // jump back to tap loop
tap_init: LDI #d64
PUT r11 // set read pointer to 64
LDI #d0
PUT r12 // set write pointer to 0
LDI #d10
PUT r8 // load 10 into preamble counter
LDI #d64
PUT r9 // load 64 (total encryption length) to r9
LDI done
NXT r10 // decrement tap selection by 1, starts at 9 for the first iteration
JEZ r0 // if no more taps left that didn't work, raise the done flag
LDI tap_init
PUT r5 // put the tap_loop address in r5
LDI tap_lut
ADD r10
ADD r10 // add 2*tap select to tap_lut location, results in location of selected tap pattern
JMP r0 // jump to LUT, which loads the tap pattern into r0
PUT r6 // tap pattern now in r6
LDW r11 // get the first preamble character
PUT r1 // put cipher text into r1
LDI #d32 // load expected space character
STW r12 // write initial space into memory
XOR r1 // get the initial state
PUT r7 // put initial state guess into r7
NXT r11 // increment read pointer
NXT r12 // increment write pointer
NXT r9 // decrement total encryption chars remaining
tap_loop: LDI lfsr_routine
JAL r0 // jump to lfsr routine which calculates next state in r7
LDI #d32 // load space char expected plaintext
XOR r7
CLB r0 // clear leading bit in the expected ciphertext
PUT r1 // store expected cipher text in r1
LDI tap_init
PUT r2 // load the outer loop top into r2
LDW r11 // load actual ciphertext
SUB r1 // subtract actual from expected, result of 0 means matching
JNZ r2 // jump to outer loop (picks new tap pattern) if the actual cipher was not equal to the expected
LDI #d32 // load preamble char
STW r12 // store preamble char in memory
NXT r11 // increment read pointer
NXT r12 // increment write pointer
NXT r9 // decrement total encryption chars remaining
LDI main_loop // load main_loop location into r0
NXT r8 // decrement preamble counter
JEZ r0 // if r8 (preamble counter) is zero, then all preamble have matched and current tap pattern is correct, jump to main loop
LDI tap_loop
JMP r0 // jump to tap_loop if characters matched but preamble is not over
main_loop: LDI correct
PUT r1 // put correct handle address in r1
LDW r11 // load the next ciphertext byte
CHK r0 // check ciphertext for error
JEZ r1 // if no error, jump to correct, otherwise continue to error handling
error: LDI #x80 // load error flag character into r0
STW r12 // store error flag to write pointer
LDI common
JMP r0 // jump out of error handling, to common operations after writing
correct: XOR r7 // bitwise XOR the current state with ciphertext space to generate plaintext
CLB r0 // clear the leading bit of the plaintext as in requirements
STW r12 // store plaintext to write pointer
common: LDI lfsr_routine // load address for the lfsr_routine label
JAL r0 // jump to the lfsr_routine label
NXT r11 // increment read pointer
NXT r12 // increment write pointer
LDI done // load address of label done
NXT r9 // decrement number of remaining plaintext chars
JEZ r0 // jump to end of program if all plaintext chars have been processed
LDI main_loop // load address of main_loop
JMP r0 // jump to main_loop if there is still space for message characters
lfsr_routine: GET r7 // get previous state
AND r6 // and state with taps to get feedback pattern
PTY r0 // get feedback parity bit
PUT r1 // store feedback bit to r1 temporarily
GET r7 // get previous state again
LSH #d1 // left shift previous state by 1
ORR r1 // or with parity bit to get next state
PUT r7 // put next state to r7
GET r14 // load link register
JMP r0 // return to function call address
done: LDI #b10000000 // load the processor flag state needed to halt the program
PUT r15 // put and set the done flag to 1 to halt the PC and indicate the program has finished
LDI #d255
JMP r0