Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions .idea/Computer-Architecture.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/profiles_settings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions ls8/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ but you'll have to implement those three above instructions first!
## Step 0: IMPORTANT: inventory what is here!

* Make a list of files here.
1. cpu.py emulates a cpu of LS-8 Microcomputer
2. ls8.py - uses cpu to run a program
* Write a short 3-10-word description of what each file does.
* Note what has been implemented, and what hasn't.
* Read this whole file.
Expand Down
154 changes: 136 additions & 18 deletions ls8/cpu.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,98 @@
"""CPU functionality."""

import sys
import os.path
HLT = 0b00000001
LDI = 0b10000010
PRN = 0b01000111
MUL = 0b10100010

PUSH = 0b01000101
POP = 0b01000110

CALL = 0b01010000
RET = 0b00010001
ADD = 0b10100000


class CPU:
"""Main CPU class."""

def __init__(self):
"""Construct a new CPU."""
pass
#pass
self.ram = [0] * 256 # 256 ram can only be as 0-355
self. pc = 0 #program counter
self.reg = [0] * 8 # 8 bit regester
self.mar = 0 #memory address register memory address to read or write
self.mdr = 0 #memory data register holds the value to write or read
self.flag = 0 #flag register hold flag status
self.halted = False
self.running = True

# SPpoints at the value at the top of the stack (most recently pushed), or at address F4 ifempty.
self.reg[7] = 0xF4 # 244 # int('F4', 16)
self.ir = 0
# Setup Branch Table
self.branchtable = {}
self.branchtable[HLT] = self.execute_HLT
self.branchtable[LDI] = self.execute_LDI
self.branchtable[PRN] = self.execute_PRN
self.branchtable[MUL] = self.execute_MUL
self.branchtable[PUSH] = self.execute_PUSH
self.branchtable[POP] = self.execute_POP
self.branchtable[CALL] = self.execute_CALL
self.branchtable[ADD] = self.execute_ADD
self.branchtable[RET] = self.excute_RET

# Property wrapper

@property
def sp(self):
return self.reg[7]

@sp.setter
def sp(self, a):
self.reg[7] = a & 0xFF

def instruction_size(self):
return ((self.ir >> 6) & 0b11) + 1

def instruction_sets_pc(self):
return ((self.ir >> 4) & 0b0001) == 1

def ram_read(self, mar):
if mar >= 0 and mar < len(self.ram):
return self.ram[mar]
else:
print(f"Error:{mar}")
return -1

def load(self):
def ram_write(self, mar, mdr):
if mar >= 0 and mar < len(self.ram):
self.ram[mar] = mdr & 0xFF
else:
print(f"Error:{mdr}")

def load(self, file_name):
"""Load a program into memory."""

address = 0

# For now, we've just hardcoded a program:

program = [
# From print8.ls8
0b10000010, # LDI R0,8
0b00000000,
0b00001000,
0b01000111, # PRN R0
0b00000000,
0b00000001, # HLT
]

for instruction in program:
self.ram[address] = instruction
address += 1
file_path = os.path.join(os.path.dirname(__file__), file_name)
try:
with open(file_path) as f:
for line in f:
num = line.split("#")[0].strip() # "10000010"
try:
instruction = int(num, 2)
self.ram[address] = instruction
address += 1
except:
continue
except:
print(f'Could not find file named: {file_name}')
sys.exit(1)


def alu(self, op, reg_a, reg_b):
Expand Down Expand Up @@ -62,4 +126,58 @@ def trace(self):

def run(self):
"""Run the CPU."""
pass


while not self.halted:
self.ir = self.ram_read(self.pc) # these are info reg and program counter
operand_a = self.ram_read(self.pc + 1)
operand_b = self.ram_read(self.pc + 2)

if not self.instruction_sets_pc():
self.pc += self.instruction_size()
self.exexute_instruction(operand_a,operand_b)
def exexute_instruction(self, operand_a, operand_b):
if self.ir in self.branchtable:
self.branchtable[self.ir](operand_a, operand_b)
else:
print('Error')
sys.exit(1)




def execute_HLT(self, a=None, b=None):
self.halted = True

def execute_LDI(self, reg_num, val):
self.reg[reg_num] = val

def execute_PRN(self, reg_num, b=None):
print(self.reg[reg_num])

def execute_MUL(self, reg_num, reg_num2):
self.reg[reg_num] *= self.reg[reg_num2]

def execute_PUSH(self, reg_num, b=None):
self.sp -= 1
self.mdr = self.reg[reg_num]
self.ram_write(self.sp, self.mdr)

def execute_POP(self, dest_reg_num, b=None):
self.mdr = self.ram_read(self.sp)
self.reg[dest_reg_num] = self.mdr
self.sp += 1

def execute_CALL(self, dest_reg_num, b=None):
self.sp -=1
self.ram_write(self.sp, self.pc + self.instruction_size())
self.pc = self.reg[dest_reg_num]

def excute_RET(self, a=None, b=None):
self.mdr = self.ram_read(self.sp)
self.pc = self.mdr
self.sp += 1

def execute_ADD(self, reg_num, reg_num1):
self.reg[reg_num] += self.reg[reg_num1]

12 changes: 10 additions & 2 deletions ls8/ls8.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
#!/usr/bin/env python3

"""Main."""

argv_message = ''
import sys
from cpu import *
import sys
if len(sys.argv) != 2:
print(argv_message)
sys.exit(1)
else:

file_name = sys.argv[1]


cpu = CPU()

cpu.load()
cpu.load(file_name)
cpu.run()