Created
March 28, 2018 04:03
-
-
Save badocelot/c3b157d6ffdd352693f5d6ce766be709 to your computer and use it in GitHub Desktop.
Little-Man Computer Simulator + 4-bit Rule110 program for it
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class LMComputer: | |
class Memory: | |
def __init__(self): | |
self.__cells = [0] * 100 | |
def __getitem__(self, key): | |
return self.__cells[key] | |
def __setitem__(self, key, value): | |
if isinstance(key, int) and 0 <= key <= 99: | |
if isinstance(value, int): | |
if 0 <= value <= 999: | |
self.__cells[key] = value | |
else: | |
raise ValueError(value) | |
else: | |
raise TypeError('value must be int') | |
else: | |
raise IndexError(key) | |
def __init__(self): | |
self.__memory = LMComputer.Memory() | |
self.__accumulator = 0 | |
self.__program_counter = 0 | |
self.__negative_flag = False | |
@property | |
def accumulator(self): | |
return self.__accumulator | |
@accumulator.setter | |
def accumulator(self, value): | |
if not isinstance(value, int): | |
raise TypeError(value) | |
self.negative_flag = False | |
self.overflow_flag = False | |
if value < 0: | |
self.__accumulator = 0 | |
self.negative_flag = True | |
elif value > 999: | |
self.__accumulator = 999 | |
self.overflow_flag = True | |
else: | |
self.__accumulator = value | |
@property | |
def memory(self): | |
return self.__memory | |
@property | |
def program_counter(self): | |
return self.__program_counter | |
@program_counter.setter | |
def program_counter(self, value): | |
if not isinstance(value, int): | |
raise TypeError(value) | |
elif not (0 <= value <= 99): | |
raise ValueError(value) | |
else: | |
self.__program_counter = value | |
def load(self, program): | |
for i in range(len(program)): | |
self.memory[i] = program[i] | |
@property | |
def negative_flag(self): | |
return self.__negative_flag | |
@negative_flag.setter | |
def negative_flag(self, value): | |
self.__negative_flag = bool(value) | |
def step(self): | |
instruction = self.memory[self.program_counter] | |
opcode = instruction // 100 | |
address = instruction % 100 | |
if instruction == 0: | |
return | |
elif instruction == 901: | |
self.accumulator = int(input()) | |
elif instruction == 902: | |
print(self.accumulator) | |
elif opcode == 1: | |
self.accumulator += self.memory[address] | |
elif opcode == 2: | |
self.accumulator -= self.memory[address] | |
elif opcode == 3: | |
self.memory[address] = self.accumulator | |
elif opcode == 5: | |
self.accumulator = self.memory[address] | |
elif opcode == 6: | |
self.program_counter = address | |
return | |
elif opcode == 7: | |
if self.accumulator == 0 and not self.negative_flag: | |
self.program_counter = address | |
return | |
elif opcode == 8: | |
if self.accumulator != 0 or self.negative_flag: | |
self.program_counter = address | |
return | |
else: | |
raise ValueError("bad instruction at " + str(self.program_counter)) | |
self.program_counter += 1 | |
def reset(self): | |
self.accumulator = 0 | |
self.program_counter = 0 | |
self.negative_flag = False | |
self.__memory = LMComputer.Memory() | |
def run(self, address=99): | |
while self.program_counter != address and self.memory[self.program_counter] != 0: | |
self.step() | |
# dsl functions | |
add = lambda address: address + 100 | |
sub = lambda address: address + 200 | |
sta = lambda address: address + 300 | |
lda = lambda address: address + 500 | |
bra = lambda address: address + 600 | |
brz = lambda address: address + 700 | |
brp = lambda address: address + 800 | |
inp = 901 | |
out = 902 | |
hlt = 0 | |
rule110 = ( | |
[bra(11)] + # 0 # jump past the data | |
[0] * 10 + # 1 - 10 # last row [1 - 5], next row [6 - 10] | |
[inp, sta(1)] + # 11 - 12 # get a number from input and store it @ 1 | |
[inp, sta(2)] + # 13 - 14 # get a number from input and store it @ 2 | |
[inp, sta(3)] + # 15 - 16 # get a number from input and store it @ 3 | |
[inp, sta(4)] + # 17 - 18 # get a number from input and store it @ 4 | |
[bra(22), 0] + # 19 - 20 # | |
[1] + # 21 # a one for use as data | |
# start: rule for first bit | |
[lda(4), brz(32)] + # 22 - 23 # test whether the left neighbor is 0 | |
[lda(1), brz(29)] + # 24 - 25 # leading 1; check if leading 10 or 11 | |
[sub(2), sta(6), bra(39)] + # 26 - 28 # leading 11 | |
[lda(2), sta(6), bra(39)] + # 29 - 31 # leading 10 | |
[add(1), add(2), brz(38)] + # 32 - 34 # leading 0; check if 000 | |
[lda(21), sta(6), bra(39)] + # 35 - 37 # not 000 put a 1 | |
[sta(6)] + # 38 # 000 - put a 0 | |
# rule for second bit | |
[lda(1), brz(49)] + # 39 - 40 # test whether the left neighbor is 0 | |
[lda(2), brz(46)] + # 41 - 42 # leading 1; check if leading 10 or 11 | |
[sub(3), sta(7), bra(56)] + # 43 - 45 # leading 11 | |
[lda(3), sta(7), bra(56)] + # 46 - 48 # leading 10 | |
[add(2), add(3), brz(55)] + # 49 - 51 # leading 0; check if 000 | |
[lda(21), sta(7), bra(56)] + # 52 - 54 # not 000 put a 1 | |
[sta(7)] + # 55 # 000 - put a 0 | |
# rule for third bit | |
[lda(2), brz(66)] + # 56 - 57 # test whether the left neighbor is 0 | |
[lda(3), brz(63)] + # 58 - 59 # leading 1; check if leading 10 or 11 | |
[sub(4), sta(8), bra(73)] + # 60 - 62 # leading 11 | |
[lda(4), sta(8), bra(73)] + # 63 - 65 # leading 10 | |
[add(3), add(4), brz(72)] + # 66 - 68 # leading 0; check if 000 | |
[lda(21), sta(8), bra(73)] + # 69 - 71 # not 000 put a 1 | |
[sta(8)] + # 72 # 000 - put a 0 | |
# rule for fourth bit | |
[lda(3), brz(83)] + # 73 - 74 # test whether the left neighbor is 0 | |
[lda(4), brz(80)] + # 75 - 76 # leading 1; check if leading 10 or 11 | |
[sub(1), sta(9), bra(90)] + # 77 - 79 # leading 11 | |
[lda(1), sta(9), bra(90)] + # 80 - 82 # leading 10 | |
[add(4), add(1), brz(89)] + # 83 - 85 # leading 0; check if 000 | |
[lda(21), sta(9), bra(90)] + # 86 - 88 # not 000 put a 1 | |
[sta(9)] + # 89 # 000 - put a 0 | |
# copy the new row over the last | |
[lda(6), sta(1)] + # 90 - 91 # copy value at 6 to 1 | |
[lda(7), sta(2)] + # 92 - 93 # copy value at 7 to 2 | |
[lda(8), sta(3)] + # 94 - 95 # copy value at 8 to 3 | |
[lda(9), sta(4)] + # 96 - 97 # copy value at 9 to 4 | |
[bra(22)] # 98 # go back to start | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment