Example #1
0
class CU(IC):
    #attributes for CU
    ram = [None] * 16
    alu = None
    running = None
    #registers
    a = None
    b = None
    c = None
    d = None

    #special register for output
    pc = None
    ir = None
    irb = None
    oR = None
    clock = None
    visualizations = None

    def __init__(self, manufacturer, build_date, purpose, ram, clock,
                 visualizations):
        super().__init__(manufacturer, build_date, purpose)
        self.ram = RAM(manufacturer, build_date, "Random access memory", 16,
                       ram)  #RAM
        self.alu = ALU(manufacturer, build_date,
                       "Arithmetic and Logic unit")  #ALU
        #clock
        self.clock = Clock(manufacturer, build_date,
                           "This component manages the time", clock)
        #Registers
        self.a = Register(manufacturer, build_date, "Register A", 4, "")
        self.b = Register(manufacturer, build_date, "Register B", 4, "")
        self.c = Register(manufacturer, build_date, "Register C", 4, "")
        self.d = Register(manufacturer, build_date, "Register D", 4, "")
        self.pc = Register(manufacturer, build_date, "Program Counter", 4, 0)
        self.ir = Register(manufacturer, build_date, "Instruction Register", 4,
                           "")
        self.irb = Register(manufacturer, build_date, "Instruction Register",
                            4, "")
        self.oR = ORegister(manufacturer, build_date, "Output Register", 4, "")
        self.visualizations = visualizations

    # Intruction Set Table
    def OUTPUT(self, arg):
        pos = int(arg, 2)  #convert binary to decimal
        data = self.ram.getData(pos)  #retrieve data from RAM at position pos
        self.oR.setData(data)  #set data into ORegister

        return "message loaded into ORegister"

    def LD_A(self, RAMLoc):
        pos = int(RAMLoc)
        data = self.ram.getData(pos)
        print(f"Succesfully loaded 'RAM[{pos}]={data}' into Register: A")
        self.a.setData(data)

    def LD_B(self, RAMLoc):
        pos = int(RAMLoc)
        data = self.ram.getData(pos)
        print(f"Succesfully loaded 'RAM[{pos}]={data}' into Register: B")
        self.b.setData(data)

    def AND(self, arg):
        letra1 = self.twoBitToRegLetter(arg[0])
        letra2 = self.twoBitToRegLetter(arg[1])
        value1 = letra1.getData()
        value2 = letra2.getData()
        comparison = self.alu.AND(value1,
                                  value2)  # calls the alu logic operation 'or'
        print(
            f"Register {letra1}: {value1}\nRegister {letra2}: {value2}\And: {bool(comparison)}"
        )
        return comparison

    def ILD_A(self, constant):
        constant = int(constant)
        self.a.setData(constant)
        print(f"Succesfuly loaded {self.a.getData()} into Register A")

    def STR_A(self, addr):
        data = self.a.getData()
        addr = int(addr)
        data = int(data)
        self.ram.setData(addr, data)
        print(f"Succesfuly wrote {self.a.getData()} into RAM address: {addr}")

    def STR_B(self, addr):
        data = self.b.getData()
        addr = int(addr)
        data = int(data)
        self.ram.setData(addr, data)
        print(f"Succesfuly wrote {self.b.getData()} into RAM address: {addr}")

    def OR(self, arg):
        reg1 = self.twoBitToRegLetter(
            arg[0])  # extracts the first 2-bit from the 8bit value
        reg2 = self.twoBitToRegLetter(
            arg[1])  # extracts the first 2-bit from the 8bit value
        value1 = reg1.getData()
        value2 = reg2.getData()
        comparison = self.alu.OR(reg1,
                                 reg2)  # calls the alu logic operation 'or'
        print(
            f"Register {reg1}: {value1}\nRegister {reg2}: {value2}\Or: {bool(comparison)}"
        )
        return comparison

    def ILD_B(self, constant):
        constant = int(constant)
        self.b.setData(constant)
        print(f"Succesfuly read {self.b.getData()} into Register B")

    def ADD(self, arg):
        reg1 = self.twoBitToRegLetter(
            arg[0])  # extracts the first 2-bit from the 8bit value
        reg2 = self.twoBitToRegLetter(
            arg[1])  # extracts the first 2-bit from the 8bit value
        value1 = reg1.getData()
        value2 = reg2.getData()
        addition = self.alu.ADD(value1, value2)
        reg2.setData(addition)
        print(
            f"Register {reg1}: {value1}\nRegister {reg2}: {value2}\Addition: {addition}"
        )

    def SUB(self, arg):
        reg1 = self.twoBitToRegLetter(
            arg[0])  # extracts the first 2-bit from the 8bit value
        reg2 = self.twoBitToRegLetter(
            arg[1])  # extracts the first 2-bit from the 8bit value
        value1 = reg1.getData()
        value2 = reg2.getData()
        substraction = self.alu.SUB(value1, value2)
        reg2.setData(substraction)
        print(
            f"Register {reg1}: {value1}\nRegister {reg2}: {value2}\Substraction: {substraction}"
        )

    def JMP(self, arg):
        self.pc.data = int(arg)

    def JMP_N(self, arg):
        if (self.alu.getNegative() == 1):
            self.JMP(arg)
        else:
            pass

    def ILD_C(self, constant):
        constant = int(constant)
        self.a.setData(constant)
        print(f"Succesfuly loaded {self.c.getData()} into Register C")

    def ILD_D(self, constant):
        constant = int(constant)
        self.a.setData(constant)
        print(f"Succesfuly loaded {self.d.getData()} into Register D")

    def reset(self):
        self.pc.data = 0
        self.ir = self.irb
        self.running = False

    def HALT(self, data):
        print("HALTING...")
        self.reset()

    # Dictionary with commands and functions
    intructionSetTable = {
        "0000": OUTPUT,
        "OUTPUT": OUTPUT,
        "0001": LD_A,
        "LD_A": LD_A,
        "0010": LD_B,
        "LD_B": LD_B,
        "0011": AND,
        "AND": AND,
        "0100": ILD_A,
        "ILD_A": ILD_A,
        "0101": STR_A,
        "STR_A": STR_A,
        "0110": STR_B,
        "STR_B": STR_B,
        "0111": OR,
        "OR": OR,
        "1000": ILD_B,
        "ILD_B": ILD_B,
        "1001": ADD,
        "ADD": ADD,
        "1010": SUB,
        "SUB": SUB,
        "1011": JMP,
        "JMP": JMP,
        "1100": JMP_N,
        "JMP_N": JMP_N,
        "1101": ILD_C,
        "ILD_C": ILD_C,
        "ILD_D": ILD_D,
        "1110": ILD_D,
        "HALT": HALT,
        "1111": HALT
    }

    # Dictionary that returns for each 2bit code a letter corresponding to a reg
    def twoBitToRegLetter(self, param):
        if (param == "00" or param == "A"):
            return self.a
        if (param == "01" or param == "B"):
            return self.b
        if (param == "10" or param == "C"):
            return self.c
        if (param == "11" or param == "D"):
            return self.d

    # twoBitToRegLetter = {
    #     "00": "a",
    #      "A": "a",
    #     "01": "b",
    #      "B": "b",
    #     "10": "c",
    #      "C": "c",
    #     "11": "d",
    #      "D": "d"
    # }

    def getFunction(self, opcode):
        return self.intructionSetTable.get(opcode)

    """ def getRegLetter(self, twoBit):
        return self.twoBitToRegLetter.get(twoBit) """

    def initBios(self, string):
        pass

    def startInstructions(self, codelines):
        for line in codelines:
            if (line[0] != "#"):
                self.fetch(line)
                self.clock.next()

    def run(self, codelines, pc=None):
        if pc:
            self.pc.data = pc
        self.running = True
        while self.running:
            self.startInstructions(codelines)

    def fetch(self, codeline):
        self.decode(codeline)

    def decode(self, lineOfCode):
        opcode = lineOfCode.split()[0]
        print(f"opcode: {opcode}")
        function = self.getFunction(opcode)
        print(f"function: {function}")
        print(f"PC: {self.pc.data}")
        self.pc.data += 1
        self.ir = function
        if (len(lineOfCode.split()) == 3):
            arguments = lineOfCode.split()[1:]
            arguments = list(map(str, arguments))
            print(f"Arguments: {arguments}")
        elif (len(lineOfCode.split()) == 2):
            arguments = lineOfCode.split()[1]
        else:
            arguments = None
        self.execute(function, arguments)

    def execute(self, function, param):
        function(self, param)

    def printStatus(self):
        return f"Running?: {bool(self.running)}"