#!/usr/bin/env python3
#
# CPU simulator for COMP2120
#
opcode = [ADD, SUB, NOT, AND, OR, MOV, LD, ST, B, HLT];
DO_NOT_SET_FLAG = 0
SET_FLAG = 1
RAM_SIZE=1024
RF_SIZE=32
import sys
import array as arr
class Register:
def __init__(self, name, val):
self.name=name
self.val=val
def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
def puthex(val):
return {0:0{1}x}.format(val,8)
def init_memory():
global mem
mem = arr.array(I, [])
for x in range(0, RAM_SIZE):
mem.append(0)
def init_RF():
global RF
RF = arr.array(I, [])
for x in range(0, RF_SIZE):
RF.append(0)
def init():
global Register
global Signal
Register = {
PC : 0,
A: 0,
B: 0,
C: 0,
MAR: 0,
MBR: 0,
RFOUT1 : 0,
RFOUT2 : 0,
RFIN : 0,
IR : 0,
ZERO_FLAG : 0
}
Signal = {
calc_addr: 0,
branch : 0,
read_RF_port_1 : 0,
read_RF_port_2 : 0,
write_RF : 0,
src_of_S1: ,
dst_of_S1: ,
src_of_S2: ,
dst_of_S2: ,
src_of_D : ,
dst_of_D : ,
doalu: 0,
ALU_func : ,
move_via_S1: 0,
move_via_S2: 0,
move_via_D : 0,
read_memory: 0,
write_memory : 0,
dohalt : 0
}
init_memory()
init_RF()
def reset():
Register[PC] = 0
def incPC():
Register[PC] += 4
if (debug):
eprint(PC is increased by 4 (, puthex(Register[PC]), ))
def do_move_via_S1 (src, dst):
Register[dst] = Register[src]
if (debug):
eprint(Move via S1: , dst, <-“, src, ” (“, puthex(Register[src]), “)”)def do_move_via_S2 (src, dst):Register[dst] = Register[src] if (debug):eprint(“Move via S2: “, dst, “<-“, src, ” (“, puthex(Register[src]), “)”)def do_move_via_D (src, dst):Register[dst] = Register[src] if (debug):eprint(“Move via D: “, dst, “<-“, src, ” (“, puthex(Register[src]), “)”)def do_read_RF_port1():reg = (Register[“IR”]//65536)%256Register[“RFOUT1”] = RF[reg]if (debug):eprint(“Read RF Port 1 — R”, reg, ” (“, puthex(Register[“RFOUT1”]), “)”)def do_read_RF_port2():reg = (Register[“IR”]%65536)//256Register[“RFOUT2”] = RF[reg]if (debug):eprint(“Read RF Port 2 — R”, reg, ” (“, puthex(Register[“RFOUT2”]), “)”)def do_write_RF():reg = Register[“IR”]%256RF[reg] = Register[“RFIN”]if (debug):eprint(“Write RF — R”, reg, ” (“, puthex(Register[“RFIN”]), “)”)def ALU_COPY():Register[“C”] = Register[“A”]if (debug):eprint(“ALU (COPY)”)def ALU_ADD():Register[“C”] = Register[“A”] + Register[“B”]if (debug):eprint(“ALU (ADD)”)def ALU_SUB():Register[“C”] = Register[“A”] – Register[“B”]if (debug):eprint(“ALU (SUB)”)def ALU_AND():Register[“C”] = Register[“A”] & Register[“B”]if (debug):eprint(“ALU (AND)”)def ALU_OR():Register[“C”] = Register[“A”] | Register[“B”]if (debug):eprint(“ALU (OR)”)def ALU_NOT():Register[“C”] = ~Register[“A”]if (debug):eprint(“ALU (NOT)”)def ALU_operation (opcode, setflag):switcher = {“OP_COPY”: ALU_COPY,”OP_ADD” : ALU_ADD,”OP_SUB” : ALU_SUB,”OP_AND” : ALU_AND,”OP_OR”: ALU_OR,”OP_NOT” : ALU_NOT}func = switcher.get(opcode)func()if (setflag==1):if (Register[“C”]==0):Register[“ZERO_FLAG”] = 1else:Register[“ZERO_FLAG”] = 0if (debug):eprint(“Zero Flag Set to “, Register[“ZERO_FLAG”])def do_read_memory():addr = Register[“MAR”]//4Register[“MBR”] = mem[addr]if (debug):eprint(“Read Memory at “, puthex(Register[“MAR”]), ” (“, puthex(Register[“MBR”]), “)”)def do_write_memory():addr = Register[“MAR”]//4mem[addr] = Register[“MBR”] if (debug):eprint(“Write Memory at “, puthex(Register[“MAR”]), ” (“, puthex(Register[“MBR”]), “)”)def fetch():if (debug):eprint(“——————————————-“)eprint(“Instruction Fetch”)eprint(“——————————————-“)do_move_via_S1(“PC”, “A”)ALU_operation(“OP_COPY”, DO_NOT_SET_FLAG)do_move_via_D(“C”, “MAR”)addr = Register[“MAR”]//4Register[“IR”] = mem[addr]if (debug):eprint(“Read Instruction at “, puthex(Register[“MAR”]), ” (“, puthex(Register[“IR”]), “)”)incPC()def set_HALT():Signal[“dohalt”] = 1def set_ADD():Signal[“calc_addr”] = 0Signal[“branch”] = 0Signal[“read_RF_port_1”] = 1Signal[“read_RF_port_2”] = 1Signal[“write_RF”] = 1Signal[“src_of_S1”] = “RFOUT1″Signal[“dst_of_S1”] = “A”Signal[“src_of_S2”] = “RFOUT2″Signal[“dst_of_S2”] = “B”Signal[“src_of_D”] = “C”Signal[“dst_of_D”] = “RFIN”Signal[“doalu”] = 1Signal[“ALU_func”] = “OP_ADD”Signal[“move_via_S1”] = 1Signal[“move_via_S2”] = 1Signal[“move_via_D”] = 1Signal[“read_memory”] = 0Signal[“write_memory”] = 0Signal[“dohalt”] = 0def set_SUB():# Fill in the code for SUB instruction heredef set_AND():Signal[“calc_addr”] = 0Signal[“branch”] = 0Signal[“read_RF_port_1”] = 1Signal[“read_RF_port_2”] = 1Signal[“write_RF”] = 1Signal[“src_of_S1”] = “RFOUT1″Signal[“dst_of_S1”] = “A”Signal[“src_of_S2”] = “RFOUT2″Signal[“dst_of_S2”] = “B”Signal[“src_of_D”] = “C”Signal[“dst_of_D”] = “RFIN”Signal[“doalu”] = 1Signal[“ALU_func”] = “OP_AND”Signal[“move_via_S1”] = 1Signal[“move_via_S2”] = 1Signal[“move_via_D”] = 1Signal[“read_memory”] = 0Signal[“write_memory”] = 0Signal[“dohalt”] = 0def set_OR():Signal[“calc_addr”] = 0Signal[“branch”] = 0Signal[“read_RF_port_1”] = 1Signal[“read_RF_port_2”] = 1Signal[“write_RF”] = 1Signal[“src_of_S1”] = “RFOUT1″Signal[“dst_of_S1”] = “A”Signal[“src_of_S2”] = “RFOUT2″Signal[“dst_of_S2”] = “B”Signal[“src_of_D”] = “C”Signal[“dst_of_D”] = “RFIN”Signal[“doalu”] = 1Signal[“ALU_func”] = “OP_OR”Signal[“move_via_S1”] = 1Signal[“move_via_S2”] = 1Signal[“move_via_D”] = 1Signal[“read_memory”] = 0Signal[“write_memory”] = 0Signal[“dohalt”] = 0def set_NOT():Signal[“calc_addr”] = 0Signal[“branch”] = 0Signal[“read_RF_port_1”] = 1Signal[“read_RF_port_2”] = 0Signal[“write_RF”] = 1Signal[“src_of_S1”] = “RFOUT1″Signal[“dst_of_S1”] = “A”Signal[“src_of_S2”] = “”Signal[“dst_of_S2”] = “”Signal[“src_of_D”] = “C”Signal[“dst_of_D”] = “RFIN”Signal[“doalu”] = 1Signal[“ALU_func”] = “OP_NOT”Signal[“move_via_S1”] = 1Signal[“move_via_S2”] = 0Signal[“move_via_D”] = 1Signal[“read_memory”] = 0Signal[“write_memory”] = 0Signal[“dohalt”] = 0def set_MOVE():Signal[“calc_addr”] = 0Signal[“branch”] = 0Signal[“read_RF_port_1”] = 1Signal[“read_RF_port_2”] = 0Signal[“write_RF”] = 1Signal[“src_of_S1”] = “RFOUT1″Signal[“dst_of_S1”] = “A”Signal[“src_of_S2”] = “”Signal[“dst_of_S2”] = “”Signal[“src_of_D”] = “C”Signal[“dst_of_D”] = “RFIN”Signal[“doalu”] = 1Signal[“ALU_func”] = “OP_COPY”Signal[“move_via_S1”] = 1Signal[“move_via_S2”] = 0Signal[“move_via_D”] = 1Signal[“read_memory”] = 0Signal[“write_memory”] = 0Signal[“dohalt”] = 0def set_LD():Signal[“calc_addr”] = 1Signal[“branch”] = 0Signal[“read_RF_port_1”] = 0Signal[“read_RF_port_2”] = 0Signal[“write_RF”] = 1Signal[“src_of_S1”] = “MBR”Signal[“dst_of_S1”] = “A”Signal[“src_of_S2”] = “”Signal[“dst_of_S2”] = “”Signal[“src_of_D”] = “C”Signal[“dst_of_D”] = “RFIN”Signal[“doalu”] = 1Signal[“ALU_func”] = “OP_COPY”Signal[“move_via_S1”] = 1Signal[“move_via_S2”] = 0Signal[“move_via_D”] = 1Signal[“read_memory”] = 1Signal[“write_memory”] = 0Signal[“dohalt”] = 0def set_ST():# Fill in the code for ST instruction here.def set_BR():Signal[“calc_addr”] = 1Signal[“branch”] = 1Signal[“read_RF_port_1”] = 0Signal[“read_RF_port_2”] = 0Signal[“write_RF”] = 0Signal[“src_of_S1”] = “”Signal[“dst_of_S1”] = “”Signal[“src_of_S2”] = “”Signal[“dst_of_S2”] = “”Signal[“src_of_D”] = “”Signal[“dst_of_D”] = “”Signal[“doalu”] = 0Signal[“ALU_func”] = “”Signal[“move_via_S1”] = 0Signal[“move_via_S2”] = 0Signal[“move_via_D”] = 0Signal[“read_memory”] = 0Signal[“write_memory”] = 0Signal[“dohalt”] = 0def decode():opcode = Register[“IR”]//16777216;# get the leftmost byteswitcher = {0 : set_ADD,1 : set_SUB,2 : set_NOT,3 : set_AND,4 : set_OR,5 : set_MOVE,6 : set_LD,7 : set_ST,8 : set_BR,9 : set_HALT,}func=switcher.get(opcode)func()if (debug):eprint(“——————————————-“)eprint(“Instruction Decode”)eprint(“——————————————-“)def execute():if (debug):eprint(“——————————————-“)eprint(“Instruction Execute”)eprint(“——————————————-“)if (Signal[“dohalt”]):returnif (Signal[“calc_addr”]):do_move_via_S1(“PC”, “A”)ALU_operation(“OP_COPY”, DO_NOT_SET_FLAG)do_move_via_D(“C”,”MAR”)do_read_memory()do_move_via_S1(“MBR”,”A”)ALU_operation(“OP_COPY”, DO_NOT_SET_FLAG)do_move_via_D(“C”,”MAR”)incPC()if (Signal[“read_memory”]):do_read_memory()if (Signal[“read_RF_port_1”]):do_read_RF_port1()if (Signal[“read_RF_port_2”]):do_read_RF_port2()if (Signal[“move_via_S1”]):do_move_via_S1(Signal[“src_of_S1”],Signal[“dst_of_S1”])if (Signal[“move_via_S2”]):do_move_via_S1(Signal[“src_of_S2”],Signal[“dst_of_S2”])if (Signal[“doalu”]):ALU_operation(Signal[“ALU_func”],SET_FLAG)if (Signal[“move_via_D”]):do_move_via_D(Signal[“src_of_D”], Signal[“dst_of_D”])if (Signal[“write_RF”]):do_write_RF()if (Signal[“write_memory”]):do_write_memory()if (Signal[“branch”]): condition_code = Register[“IR”]//65536%256if (condition_code == 0):#unconditional branchbranch_taken = 1elif (condition_code == 1): #branch if zerobranch_taken = Register[“ZERO_FLAG”]elif (condition_code == 2): #branch if not zerobranch_taken = not Register[“ZERO_FLAG”]if (branch_taken):do_move_via_S1(“MAR”, “A”)ALU_operation(“OP_COPY”, DO_NOT_SET_FLAG)do_move_via_D(“C”,”PC”)def read_program(fn):global nwordi = 0#f = open(fn, “r”)try:with open(fn, “r”) as f:for x in f:mem[i] = int(x,16)i = i + 1nword=iexcept IOError:eprint(“Cannot read file “, fn)exit()def dump_memory():eprint(“Content of Memory:”)for x in range(0,nword):eprint(puthex(mem[x]))def dump_register(n):eprint(“Content of the first “, n, ” registers:”)for x in range(0,n):eprint(puthex(RF[x]))def disassemble():addr = mem[Register[“PC”]//4]IR = Register[“IR”]op = IR//16777216s1 = (IR//65536)%256s2 = (IR%65536)//256d = IR%256if (op < 6): #ALU operationsif ((op!=2) and (op!=5)):eprint(opcode[op], ” R”, s1, “, R”, s2, “, R”, d)else:eprint(opcode[op], ” R”, s1, “, R”, d)elif (op == 6) : # ldeprint(opcode[op], puthex(addr), “, R”, d)elif (op == 7): #steprint(opcode[op], ” R”, s1, “, “, puthex(addr))elif (op == 8): #brcondition_code = (IR//65536)%256if (condition_code==0):opcodebr=”BR”elif (condition_code==1):opcodebr=”BZ”else:opcodebr=”BNZ”eprint(opcodebr, puthex(addr))else:eprint(opcode[op])def usage():eprint(“Usage: [python3] ./sim.py [-d] progname”)def main():global debugdebug = 0argc = len(sys.argv)if (argc == 1):usage()exit()if (sys.argv[1][0]==’-‘):if (argc == 2):usage()exit()filename=sys.argv[2]if (sys.argv[1][1]==’d’):debug = 1else:usage()exit()else:debug = 0filename=sys.argv[1] init()read_program(filename)dump_memory()reset()while(not Signal[“dohalt”]):if (debug):eprint (“Executing PC at “, puthex(Register[“PC”]))fetch()decode()if (debug):eprint(“IR = “, puthex(Register[“IR”]))disassemble()execute()if (debug):dump_register(14)input(“Press Enter to Continue”)eprint(“Final Result:”)dump_register(14)dump_memory()main()
Reviews
There are no reviews yet.