From 7ca56c1a730fcecd0fe3af5e6b652fa09514a18b Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Fri, 26 Apr 2024 15:40:14 +0300 Subject: Refactor project structure, add README and LICENSE --- atk16_utils/charmem.py | 63 -------------------- atk16_utils/charmem/charmem.bin | Bin 0 -> 2048 bytes atk16_utils/charmem/charmem.py | 63 ++++++++++++++++++++ atk16_utils/charmem/charset.txt | Bin 0 -> 23058 bytes atk16_utils/charmem/ibm_cga_8x8.ttf | Bin 0 -> 35952 bytes atk16_utils/ucode.py | 112 ------------------------------------ atk16_utils/ucode/ucode.bin | Bin 0 -> 768 bytes atk16_utils/ucode/ucode.py | 112 ++++++++++++++++++++++++++++++++++++ 8 files changed, 175 insertions(+), 175 deletions(-) delete mode 100644 atk16_utils/charmem.py create mode 100644 atk16_utils/charmem/charmem.bin create mode 100644 atk16_utils/charmem/charmem.py create mode 100644 atk16_utils/charmem/charset.txt create mode 100644 atk16_utils/charmem/ibm_cga_8x8.ttf delete mode 100755 atk16_utils/ucode.py create mode 100644 atk16_utils/ucode/ucode.bin create mode 100755 atk16_utils/ucode/ucode.py (limited to 'atk16_utils') diff --git a/atk16_utils/charmem.py b/atk16_utils/charmem.py deleted file mode 100644 index aaac122..0000000 --- a/atk16_utils/charmem.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python3 -# Generate .bin file with ATK16 CPU TPU charmem data - -# Addressed by _CCC CCCC CYYY -# Data width 8bit: ___X XXXX -# where _ = unused, C = 8bit character code, Y = character y coordinate, X = pixel value - -import sys - -if len(sys.argv) != 2: - print("usage: charmem.py ") - sys.exit(1) - -outfile_path = sys.argv[1] - -with open("charset.txt", "r") as f: - lines = [s.strip("\n") for s in f.readlines()] - -header_chars = lines[0] - -charset: list[list[str]] = [] - -CHAR_HEIGHT = 8 -CHAR_WIDTH = 8 - -i = 0 -while i < len(lines): - i += 1 # skip comment line - char = lines[i:i+CHAR_HEIGHT] - for row in char: - if len(row) != CHAR_WIDTH: - raise Exception(f"char row number {i} has width != {CHAR_WIDTH}: {len(row)}\n" + row + "\n" + "\n".join(char)) - charset.append(char) - i += CHAR_HEIGHT + 1 - -CHAR_N = len(charset) - -TOTAL_BYTEARRAY_SIZE = CHAR_N * CHAR_HEIGHT - -def string_to_byte(input_string: str): - # Replace spaces with '0' and '#' with '1' - binary_string = input_string.replace(' ', '0').replace('█', '1') - - assert(len(input_string) == CHAR_WIDTH) - - # Check if the string contains only '0' or '1' - if not all(c in '01' for c in binary_string): - raise ValueError("Input string must contain only spaces and '█' characters.") - - # Convert the binary string to an unsigned integer byte - return int(binary_string[::-1], 2) - - -res_b = bytearray(TOTAL_BYTEARRAY_SIZE) -for cn, char in enumerate(charset): - for cy in range(0, CHAR_HEIGHT): - addr = (cn << 3) + cy - byte = string_to_byte(char[cy]) - print(f"{byte:>08b}") - res_b[addr] = byte - -with open(outfile_path, "wb") as f: - f.write(res_b) diff --git a/atk16_utils/charmem/charmem.bin b/atk16_utils/charmem/charmem.bin new file mode 100644 index 0000000..1276d28 Binary files /dev/null and b/atk16_utils/charmem/charmem.bin differ diff --git a/atk16_utils/charmem/charmem.py b/atk16_utils/charmem/charmem.py new file mode 100644 index 0000000..aaac122 --- /dev/null +++ b/atk16_utils/charmem/charmem.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# Generate .bin file with ATK16 CPU TPU charmem data + +# Addressed by _CCC CCCC CYYY +# Data width 8bit: ___X XXXX +# where _ = unused, C = 8bit character code, Y = character y coordinate, X = pixel value + +import sys + +if len(sys.argv) != 2: + print("usage: charmem.py ") + sys.exit(1) + +outfile_path = sys.argv[1] + +with open("charset.txt", "r") as f: + lines = [s.strip("\n") for s in f.readlines()] + +header_chars = lines[0] + +charset: list[list[str]] = [] + +CHAR_HEIGHT = 8 +CHAR_WIDTH = 8 + +i = 0 +while i < len(lines): + i += 1 # skip comment line + char = lines[i:i+CHAR_HEIGHT] + for row in char: + if len(row) != CHAR_WIDTH: + raise Exception(f"char row number {i} has width != {CHAR_WIDTH}: {len(row)}\n" + row + "\n" + "\n".join(char)) + charset.append(char) + i += CHAR_HEIGHT + 1 + +CHAR_N = len(charset) + +TOTAL_BYTEARRAY_SIZE = CHAR_N * CHAR_HEIGHT + +def string_to_byte(input_string: str): + # Replace spaces with '0' and '#' with '1' + binary_string = input_string.replace(' ', '0').replace('█', '1') + + assert(len(input_string) == CHAR_WIDTH) + + # Check if the string contains only '0' or '1' + if not all(c in '01' for c in binary_string): + raise ValueError("Input string must contain only spaces and '█' characters.") + + # Convert the binary string to an unsigned integer byte + return int(binary_string[::-1], 2) + + +res_b = bytearray(TOTAL_BYTEARRAY_SIZE) +for cn, char in enumerate(charset): + for cy in range(0, CHAR_HEIGHT): + addr = (cn << 3) + cy + byte = string_to_byte(char[cy]) + print(f"{byte:>08b}") + res_b[addr] = byte + +with open(outfile_path, "wb") as f: + f.write(res_b) diff --git a/atk16_utils/charmem/charset.txt b/atk16_utils/charmem/charset.txt new file mode 100644 index 0000000..bee1e3d Binary files /dev/null and b/atk16_utils/charmem/charset.txt differ diff --git a/atk16_utils/charmem/ibm_cga_8x8.ttf b/atk16_utils/charmem/ibm_cga_8x8.ttf new file mode 100644 index 0000000..9f29ec5 Binary files /dev/null and b/atk16_utils/charmem/ibm_cga_8x8.ttf differ diff --git a/atk16_utils/ucode.py b/atk16_utils/ucode.py deleted file mode 100755 index 22a2ce2..0000000 --- a/atk16_utils/ucode.py +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env python3 -# Generate .bin file with ATK16 CPU microcode - -# Addressed by OOOO BUUU -# where O = opcode, B = branch flag, U = microsequencer value - -import sys - -if len(sys.argv) != 2: - print("usage: ucode.py ") - sys.exit(1) - -outfile_path = sys.argv[1] - -PC_CO = 1 << 0 -PC_IE = 1 << 1 -PC_OE = 1 << 2 -MAR_IE = 1 << 3 -MEM_IE = 1 << 4 -MEM_OE = 1 << 5 -RW_IE = 1 << 6 -R1_OE = 1 << 7 -R2_OE = 1 << 8 -IR_IE = 1 << 9 -IM_M = 1 << 10 -LI_OE = 1 << 11 -ALU_OE = 1 << 12 -FR_IE = 1 << 13 -HALT = 1 << 14 -US_RS = 1 << 15 -ISRA_OE = 1 << 16 -IM_DS = 1 << 17 -IM_EN = 1 << 18 -IPC_IE = 1 << 19 -IPC_OE = 1 << 20 -NOP5 = 1 << 21 -NOP6 = 1 << 22 -NOP7 = 1 << 23 - -BRANCH_FLAG_STATES_N = 2 -UCODE_N: int = 2**3 -CONTROL_WORD_SIZE = 3 - -def not_branch(bs: list[int]) -> list[list[int]]: - return BRANCH_FLAG_STATES_N * [bs] - -def branch(false_branch: list[int], true_branch: list[int]) -> list[list[int]]: - return [false_branch, true_branch] - -fetch = [PC_OE|MAR_IE, MEM_OE|IR_IE|PC_CO] - -def nop(): - return not_branch([*fetch, US_RS, 0, 0, 0, 0, 0]) - -ucode = [ - # ALR 0000 TTTL LLRR RSSS - not_branch([*fetch, ALU_OE|FR_IE|RW_IE, US_RS, 0, 0, 0, 0]), - # ALI 0001 TTTL LLII ISSS - not_branch([*fetch, IM_M|ALU_OE|FR_IE|RW_IE, US_RS, 0, 0, 0, 0]), - # LDR 0010 TTTR RRXX XXXX - not_branch([*fetch, R1_OE|MAR_IE, MEM_OE|RW_IE, US_RS, 0, 0, 0]), - # STR 0011 XXXL LLRR RXXX - not_branch([*fetch, R1_OE|MAR_IE, R2_OE|MEM_IE, US_RS, 0, 0, 0]), - # LDI 0100 TTTI IIII IIII - not_branch([*fetch, LI_OE|RW_IE, US_RS, 0, 0, 0, 0]), - # JPR 0101 XXXR RRXX XXXX - not_branch([*fetch, R1_OE|PC_IE, US_RS, 0, 0, 0, 0]), - # JPI 0110 XXXI IIII IIII - not_branch([*fetch, IM_M|LI_OE|PC_IE, US_RS, 0, 0, 0, 0]), - # BRR 0111 XFFR RRXX XXXX - branch([*fetch, US_RS, 0, 0, 0, 0, 0], - [*fetch, R1_OE|PC_IE, US_RS, 0, 0, 0, 0]), - # BRI 1000 XFFI IIII IIII - branch([*fetch, US_RS, 0, 0, 0, 0, 0], - [*fetch, IM_M|LI_OE|PC_IE, US_RS, 0, 0, 0, 0]), - # LPC 1001 TTTX XXXX XXXX - not_branch([*fetch, PC_OE|RW_IE, US_RS, 0, 0, 0, 0]), - # NOP 1010 XXXX XXXX XXXX - nop(), - # NOP 1011 XXXX XXXX XXXX - nop(), - # ISRP0 1100 XXXX XXXX XXXX - not_branch([IM_EN|PC_OE|IPC_IE, ISRA_OE|MAR_IE, MEM_OE|PC_IE, US_RS, 0, 0, 0, 0]), - # ISRP1 1101 XXXX XXXX XXXX - not_branch([IM_EN|PC_OE|IPC_IE, ISRA_OE|MAR_IE, MEM_OE|PC_IE, US_RS, 0, 0, 0, 0]), - # RTI 1110 XXXX XXXX XXXX - not_branch([*fetch, IM_DS|IPC_OE|PC_IE, US_RS, 0, 0, 0, 0]), - # HLT 1111 XXXX XXXX XXXX - not_branch([*fetch, HALT, 0, 0, 0, 0, 0]), -] - -INST_N = len(ucode) -TOTAL_BYTEARRAY_SIZE = INST_N * BRANCH_FLAG_STATES_N * UCODE_N * CONTROL_WORD_SIZE - -res_b = bytearray(TOTAL_BYTEARRAY_SIZE) - -for i in range(INST_N): - for j in range(BRANCH_FLAG_STATES_N): - for k in range(UCODE_N): - for l in range(CONTROL_WORD_SIZE): - idx = l + \ - k * CONTROL_WORD_SIZE + \ - j * CONTROL_WORD_SIZE * UCODE_N + \ - i * CONTROL_WORD_SIZE * UCODE_N * BRANCH_FLAG_STATES_N - cword = ucode[i][j][k] - assert len(ucode[i][j]) == 8 - cbyte = (cword >> (8 * (CONTROL_WORD_SIZE - l - 1))) & 0xff - print(f"inst: {i:>04b}, idx: {idx:>04x}, cbyte: {cbyte:>08b}") - res_b[idx] = cbyte - -with open(outfile_path, "wb") as f: - f.write(res_b) diff --git a/atk16_utils/ucode/ucode.bin b/atk16_utils/ucode/ucode.bin new file mode 100644 index 0000000..70c046f Binary files /dev/null and b/atk16_utils/ucode/ucode.bin differ diff --git a/atk16_utils/ucode/ucode.py b/atk16_utils/ucode/ucode.py new file mode 100755 index 0000000..22a2ce2 --- /dev/null +++ b/atk16_utils/ucode/ucode.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +# Generate .bin file with ATK16 CPU microcode + +# Addressed by OOOO BUUU +# where O = opcode, B = branch flag, U = microsequencer value + +import sys + +if len(sys.argv) != 2: + print("usage: ucode.py ") + sys.exit(1) + +outfile_path = sys.argv[1] + +PC_CO = 1 << 0 +PC_IE = 1 << 1 +PC_OE = 1 << 2 +MAR_IE = 1 << 3 +MEM_IE = 1 << 4 +MEM_OE = 1 << 5 +RW_IE = 1 << 6 +R1_OE = 1 << 7 +R2_OE = 1 << 8 +IR_IE = 1 << 9 +IM_M = 1 << 10 +LI_OE = 1 << 11 +ALU_OE = 1 << 12 +FR_IE = 1 << 13 +HALT = 1 << 14 +US_RS = 1 << 15 +ISRA_OE = 1 << 16 +IM_DS = 1 << 17 +IM_EN = 1 << 18 +IPC_IE = 1 << 19 +IPC_OE = 1 << 20 +NOP5 = 1 << 21 +NOP6 = 1 << 22 +NOP7 = 1 << 23 + +BRANCH_FLAG_STATES_N = 2 +UCODE_N: int = 2**3 +CONTROL_WORD_SIZE = 3 + +def not_branch(bs: list[int]) -> list[list[int]]: + return BRANCH_FLAG_STATES_N * [bs] + +def branch(false_branch: list[int], true_branch: list[int]) -> list[list[int]]: + return [false_branch, true_branch] + +fetch = [PC_OE|MAR_IE, MEM_OE|IR_IE|PC_CO] + +def nop(): + return not_branch([*fetch, US_RS, 0, 0, 0, 0, 0]) + +ucode = [ + # ALR 0000 TTTL LLRR RSSS + not_branch([*fetch, ALU_OE|FR_IE|RW_IE, US_RS, 0, 0, 0, 0]), + # ALI 0001 TTTL LLII ISSS + not_branch([*fetch, IM_M|ALU_OE|FR_IE|RW_IE, US_RS, 0, 0, 0, 0]), + # LDR 0010 TTTR RRXX XXXX + not_branch([*fetch, R1_OE|MAR_IE, MEM_OE|RW_IE, US_RS, 0, 0, 0]), + # STR 0011 XXXL LLRR RXXX + not_branch([*fetch, R1_OE|MAR_IE, R2_OE|MEM_IE, US_RS, 0, 0, 0]), + # LDI 0100 TTTI IIII IIII + not_branch([*fetch, LI_OE|RW_IE, US_RS, 0, 0, 0, 0]), + # JPR 0101 XXXR RRXX XXXX + not_branch([*fetch, R1_OE|PC_IE, US_RS, 0, 0, 0, 0]), + # JPI 0110 XXXI IIII IIII + not_branch([*fetch, IM_M|LI_OE|PC_IE, US_RS, 0, 0, 0, 0]), + # BRR 0111 XFFR RRXX XXXX + branch([*fetch, US_RS, 0, 0, 0, 0, 0], + [*fetch, R1_OE|PC_IE, US_RS, 0, 0, 0, 0]), + # BRI 1000 XFFI IIII IIII + branch([*fetch, US_RS, 0, 0, 0, 0, 0], + [*fetch, IM_M|LI_OE|PC_IE, US_RS, 0, 0, 0, 0]), + # LPC 1001 TTTX XXXX XXXX + not_branch([*fetch, PC_OE|RW_IE, US_RS, 0, 0, 0, 0]), + # NOP 1010 XXXX XXXX XXXX + nop(), + # NOP 1011 XXXX XXXX XXXX + nop(), + # ISRP0 1100 XXXX XXXX XXXX + not_branch([IM_EN|PC_OE|IPC_IE, ISRA_OE|MAR_IE, MEM_OE|PC_IE, US_RS, 0, 0, 0, 0]), + # ISRP1 1101 XXXX XXXX XXXX + not_branch([IM_EN|PC_OE|IPC_IE, ISRA_OE|MAR_IE, MEM_OE|PC_IE, US_RS, 0, 0, 0, 0]), + # RTI 1110 XXXX XXXX XXXX + not_branch([*fetch, IM_DS|IPC_OE|PC_IE, US_RS, 0, 0, 0, 0]), + # HLT 1111 XXXX XXXX XXXX + not_branch([*fetch, HALT, 0, 0, 0, 0, 0]), +] + +INST_N = len(ucode) +TOTAL_BYTEARRAY_SIZE = INST_N * BRANCH_FLAG_STATES_N * UCODE_N * CONTROL_WORD_SIZE + +res_b = bytearray(TOTAL_BYTEARRAY_SIZE) + +for i in range(INST_N): + for j in range(BRANCH_FLAG_STATES_N): + for k in range(UCODE_N): + for l in range(CONTROL_WORD_SIZE): + idx = l + \ + k * CONTROL_WORD_SIZE + \ + j * CONTROL_WORD_SIZE * UCODE_N + \ + i * CONTROL_WORD_SIZE * UCODE_N * BRANCH_FLAG_STATES_N + cword = ucode[i][j][k] + assert len(ucode[i][j]) == 8 + cbyte = (cword >> (8 * (CONTROL_WORD_SIZE - l - 1))) & 0xff + print(f"inst: {i:>04b}, idx: {idx:>04x}, cbyte: {cbyte:>08b}") + res_b[idx] = cbyte + +with open(outfile_path, "wb") as f: + f.write(res_b) -- cgit v1.3