move firmware files into dedicated folder
This commit is contained in:
138
firmware/assembler.py
Normal file
138
firmware/assembler.py
Normal 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
2
firmware/example.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
python assembler.py cse141L.bin program1.asm program2.asm program3.asm
|
66
firmware/program1.asm
Normal file
66
firmware/program1.asm
Normal 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
107
firmware/program2.asm
Normal 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
115
firmware/program3.asm
Normal 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
|
Reference in New Issue
Block a user