CircuitProject-CPU

目录

寄存器

  • PC 程序计数器
  • ALU
  • PSW/FLAG 程序状态字
  • A 寄存器
  • B 寄存器
  • C 寄存器
  • D 寄存器
  • IR 指令寄存器
  • DST 目的操作数寄存器
  • SRC 源操作数寄存器

  • MSR 存储器段寄存器
  • MAR 存储器地址寄存器
  • MC 内存控制器

  • SP 堆栈指针寄存器
  • BP 基址寄存器
  • SI 源变址寄存器
  • DI 目的变址寄存器
  • CS 代码段寄存器
  • DS 数据段寄存器
  • SS 堆栈段寄存器
  • ES 附加段寄存器

  • TMP 临时寄存器若干

指令

  • 二操作数:3bit 最高位为:1
    • mov dst, src
    • add dst, src
    • sub dst, src
    • cmp op1, op2
    • and dst, src
    • or dst, src
    • xor dst, src
  • 一操作数:次最高位为 1
    • inc src
    • dec src
    • not src
    • call dst
    • jmp dst
    • jo dst
    • jno dst
    • jz dst
    • jnz dst
    • push dst
    • pop dst
    • int dst
  • 临操作数:
    • nop
    • hlt
    • ret
    • iret

寻址方式

  • 立即数寻址 MOV A 5
  • 寄存器寻址 MOV A B
  • 直接寻址 MOV A [5]
  • 寄存器间接寻址 MOV A [B]

寄存器控制器

读写控制器

读写控制方式

  1. 指令寄存器的数据
  2. 目的操作数寄存器的数据
  3. 源操作数寄存器的是数据

控制单元

取指令微程序

# coding=utf-8

MSR = 1
MAR = 2
MDR = 3
RAM = 4
IR = 5
DST = 6
SRC = 7
A = 8
B = 9
C = 10
D = 11
DI = 12
SI = 13
SP = 14
BP = 15
CS = 16
DS = 17
SS = 18
ES = 19
VEC = 20
T1 = 21
T2 = 22

MSR_OUT = MSR
MAR_OUT = MAR
MDR_OUT = MDR
RAM_OUT = RAM
IR_OUT = IR
DST_OUT = DST
SRC_OUT = SRC
A_OUT = A
B_OUT = B
C_OUT = C
D_OUT = D
DI_OUT = DI
SI_OUT = SI
SP_OUT = SP
BP_OUT = BP
CS_OUT = CS
DS_OUT = DS
SS_OUT = SS
ES_OUT = ES
VEC_OUT = VEC
T1_OUT = T1
T2_OUT = T2

_DST_SHIFT = 5

MSR_IN = MSR << _DST_SHIFT
MAR_IN = MAR << _DST_SHIFT
MDR_IN = MDR << _DST_SHIFT
RAM_IN = RAM << _DST_SHIFT
IR_IN = IR << _DST_SHIFT
DST_IN = DST << _DST_SHIFT
SRC_IN = SRC << _DST_SHIFT
A_IN = A << _DST_SHIFT
B_IN = B << _DST_SHIFT
C_IN = C << _DST_SHIFT
D_IN = D << _DST_SHIFT
DI_IN = DI << _DST_SHIFT
SI_IN = SI << _DST_SHIFT
SP_IN = SP << _DST_SHIFT
BP_IN = BP << _DST_SHIFT
CS_IN = CS << _DST_SHIFT
DS_IN = DS << _DST_SHIFT
SS_IN = SS << _DST_SHIFT
ES_IN = ES << _DST_SHIFT
VEC_IN = VEC << _DST_SHIFT
T1_IN = T1 << _DST_SHIFT
T2_IN = T2 << _DST_SHIFT

SRC_R = 2 ** 10
SRC_W = 2 ** 11
DST_R = 2 ** 12
DST_W = 2 ** 13

PC_WE = 2 ** 14
PC_CS = 2 ** 15
PC_EN = 2 ** 16

PC_OUT = PC_CS
PC_IN = PC_CS | PC_WE
PC_INC = PC_CS | PC_WE | PC_EN

_OP_SHIFT = 17

OP_ADD = 0
OP_SUB = 1 << _OP_SHIFT
OP_INC = 2 << _OP_SHIFT
OP_DEC = 3 << _OP_SHIFT
OP_AND = 4 << _OP_SHIFT
OP_OR = 5 << _OP_SHIFT
OP_XOR = 6 << _OP_SHIFT
OP_NOT = 7 << _OP_SHIFT

ALU_OUT = 1 << 20
ALU_PSW = 1 << 21

CYC = 2 ** 30
HLT = 2 ** 31

ADDR2 = 1 << 7
ADDR1 = 1 << 6

ADDR2_SHIFT = 4
ADDR1_SHIFT = 2

AM_INS = 0
AM_REG = 1
AM_DIR = 2
AM_RAM = 3
# coding=utf-8

import pin

FETCH = [
    pin.PC_OUT | pin.MAR_IN,
    pin.RAM_OUT | pin.IR_IN | pin.PC_INC,
    pin.PC_OUT | pin.MAR_IN,
    pin.RAM_OUT | pin.DST_IN | pin.PC_INC,
    pin.PC_OUT | pin.MAR_IN,
    pin.RAM_OUT | pin.SRC_IN | pin.PC_INC,
]
# coding=utf-8

import os
import pin
import assembly as ASM

dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'micro.bin')

micro = [pin.HLT for _ in range(0x10000)]

for addr in range(0x10000):
    ir = addr >> 8
    psw = (addr >> 4) & 0xf
    cyc = addr & 0xf

    if cyc < len(ASM.FETCH):
        micro[addr] = ASM.FETCH[cyc]

with open(filename, 'wb') as file:
    for var in micro:
        value = var.to_bytes(4, byteorder='little')
        file.write(value)

print('Compile micro instruction finish!!!')

指令系统

  • 二地址指令
    • 1xxx[aa][bb]
  • 一地址指令
    • 01xxxx[aa]
  • 零地址指令
    • 00xxxxxx
      INSTRUCTIONS = {
       2: {
       MOV: {
           (pin.AM_REG, pin.AM_INS): [
               pin.DST_W | pin.SRC_OUT,
           ],
           (pin.AM_REG, pin.AM_REG): [
               pin.DST_W | pin.SRC_R,
           ],
           (pin.AM_REG, pin.AM_DIR): [
               pin.SRC_OUT | pin.MAR_IN,
               pin.DST_W | pin.RAM_OUT
           ],
           (pin.AM_REG, pin.AM_RAM): [
               pin.SRC_R | pin.MAR_IN,
               pin.DST_W | pin.RAM_OUT
           ],
           (pin.AM_DIR, pin.AM_INS): [
               pin.DST_OUT | pin.MAR_IN,
               pin.RAM_IN | pin.SRC_OUT
           ],
           (pin.AM_DIR, pin.AM_REG): [
               pin.DST_OUT | pin.MAR_IN,
               pin.RAM_IN | pin.SRC_R,
           ],
           (pin.AM_DIR, pin.AM_DIR): [
               pin.SRC_OUT | pin.MAR_IN,
               pin.RAM_OUT | pin.T1_IN,
               pin.DST_OUT | pin.MAR_IN,
               pin.RAM_IN | pin.T1_OUT,
           ],
           (pin.AM_DIR, pin.AM_RAM): [
               pin.SRC_R | pin.MAR_IN,
               pin.RAM_OUT | pin.T1_IN,
               pin.DST_OUT | pin.MAR_IN,
               pin.RAM_IN | pin.T1_OUT,
           ],
      
           (pin.AM_RAM, pin.AM_INS): [
               pin.DST_R | pin.MAR_IN,
               pin.RAM_IN | pin.SRC_OUT
           ],
           (pin.AM_RAM, pin.AM_REG): [
               pin.DST_R | pin.MAR_IN,
               pin.RAM_IN | pin.SRC_R,
           ],
           (pin.AM_RAM, pin.AM_DIR): [
               pin.SRC_OUT | pin.MAR_IN,
               pin.RAM_OUT | pin.T1_IN,
               pin.DST_R | pin.MAR_IN,
               pin.RAM_IN | pin.T1_OUT,
           ],
           (pin.AM_RAM, pin.AM_RAM): [
               pin.SRC_R | pin.MAR_IN,
               pin.RAM_OUT | pin.T1_IN,
               pin.DST_R | pin.MAR_IN,
               pin.RAM_IN | pin.T1_OUT,
           ]
       },
       ADD: {
           (pin.AM_REG, pin.AM_INS): [
               pin.DST_R | pin.A_IN,
               pin.SRC_OUT | pin.B_IN,
               pin.OP_ADD | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW
           ],
           (pin.AM_REG, pin.AM_REG): [
               pin.DST_R | pin.A_IN,
               pin.SRC_R | pin.B_IN,
               pin.OP_ADD | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW
           ],
       },
       SUB: {
           (pin.AM_REG, pin.AM_INS): [
               pin.DST_R | pin.A_IN,
               pin.SRC_OUT | pin.B_IN,
               pin.OP_SUB | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW
           ],
           (pin.AM_REG, pin.AM_REG): [
               pin.DST_R | pin.A_IN,
               pin.SRC_R | pin.B_IN,
               pin.OP_SUB | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW
           ],
       },
       },
       1: {
       INC: {
           pin.AM_REG: [
               pin.DST_R | pin.A_IN,
               pin.OP_INC | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW
           ],
       },
       DEC: {
           pin.AM_REG: [
               pin.DST_R | pin.A_IN,
               pin.OP_DEC | pin.ALU_OUT | pin.DST_W | pin.ALU_PSW
           ],
       },
       },
       0: {
       NOP: [
           pin.CYC,
       ],
       HLT: [
           pin.HLT,
       ]
       }
      }
      
ADDR2 = 1 << 7
ADDR1 = 1 << 6

ADDR2_SHIFT = 4
ADDR1_SHIFT = 2

AM_INS = 0
AM_REG = 1
AM_DIR = 2
AM_RAM = 3

MOV 指令

MOV = 0 | ADDR2

ADD 指令

ADD = ADDR2 | (1 << ADDR2_SHIFT)

HLT 指令

HLT = 0x3f # 0x11 1111

NOP 指令

NOP = 0

二地址指令

def compile_addr2(addr, ir, psw, index):
    global micro

    op = ir & 0xf0
    amd = (ir >> 2) & 3
    ams = ir & 3

    INST = ASM.INSTRUCTIONS[2]
    if op not in INST:
        micro[addr] = pin.CYC
        return
    am = (amd, ams)
    if am not in INST[op]:
        micro[addr] = pin.CYC
        return

    EXEC = INST[op][am]
    if index < len(EXEC):
        micro[addr] = EXEC[index]
    else:
        micro[addr] = pin.CYC

一地址指令

def compile_addr1(addr, ir, psw, index):
    global micro

    op = ir & 0xfc
    amd = ir & 3

    INST = ASM.INSTRUCTIONS[1]
    if op not in INST:
        micro[addr] = pin.CYC
        return

    if amd not in INST[op]:
        micro[addr] = pin.CYC
        return

    EXEC = INST[op][amd]
    if index < len(EXEC):
        micro[addr] = EXEC[index]
    else:
        micro[addr] = pin.CYC

零地址指令

def compile_addr0(addr, ir, psw, index):
    global micro

    op = ir

    INST = ASM.INSTRUCTIONS[2]
    if op not in INST:
        micro[addr] = pin.CYC
        return

    EXEC = INST[op]
    if index < len(EXEC):
        micro[addr] = EXEC[index]
    else:
        micro[addr] = pin.CYC

汇编编译器

# coding=utf-8

import os
import re

import pin
import assembly as ASM

dirname = os.path.dirname(__file__)

inputfile = os.path.join(dirname, 'program.asm')
outputfile = os.path.join(dirname, 'program.bin')

annotation = re.compile(r"(.*?);.*")

codes = []
marks = {}

OP2 = {
    'MOV': ASM.MOV,
    'ADD': ASM.ADD,
    'SUB': ASM.SUB,
    'CMP': ASM.CMP,
    'AND': ASM.AND,
    'OR': ASM.OR,
    'XOR': ASM.XOR,
}

OP1 = {
    'INC': ASM.INC,
    'DEC': ASM.DEC,
    'NOT': ASM.NOT,
    'JMP': ASM.JMP,
}

OP0 = {
    'NOP': ASM.NOP,
    'HLT': ASM.HLT,
}

OP2SET = set(OP2.values())
OP1SET = set(OP1.values())
OP0SET = set(OP0.values())

REGISTERS = {
    "A": pin.A,
    "B": pin.B,
    "C": pin.C,
    "D": pin.D,
}


class Code(object):

    TYPE_CODE = 1
    TYPE_LABEL = 2

    def __init__(self, number, source: str):
        self.numer = number
        self.source = source.upper()
        self.op = None
        self.dst = None
        self.src = None
        self.type = self.TYPE_CODE
        self.index = 0
        self.prepare_source()

    def get_op(self):
        if self.op in OP2:
            return OP2[self.op]
        if self.op in OP1:
            return OP1[self.op]
        if self.op in OP0:
            return OP0[self.op]
        raise SyntaxError(self)

    def get_am(self, addr):
        global marks
        if not addr:
            return None, None
        if addr in marks:
            return pin.AM_INS, marks[addr].index * 3
        if addr in REGISTERS:
            return pin.AM_REG, REGISTERS[addr]
        if re.match(r'^[0-9]+$', addr):
            return pin.AM_INS, int(addr)
        if re.match(r'^0X[0-9A-F]+$', addr):
            return pin.AM_INS, int(addr, 16)
        match = re.match(r'^\[([0-9]+)\]$', addr)
        if match:
            return pin.AM_DIR, int(match.group(1))
        match = re.match(r'^\[(0X[0-9A-F]+)\]$', addr)
        if match:
            return pin.AM_DIR, int(match.group(1), 16)
        match = re.match(r'^\[(.+)\]$', addr)
        if match and match.group(1) in REGISTERS:
            return pin.AM_RAM, REGISTERS[match.group(1)]
        raise SyntaxError(self)

    def prepare_source(self):
        if self.source.endswith(':'):
            self.type = self.TYPE_LABEL
            self.name = self.source.strip(':')
            return

        tup = self.source.split(',')
        if len(tup) > 2:
            raise SyntaxError(self)
        if len(tup) == 2:
            self.src = tup[1].strip()

        tup = re.split(r" +", tup[0])
        if len(tup) > 2:
            raise SyntaxError(self)
        if len(tup) == 2:
            self.dst = tup[1].strip()

        self.op = tup[0].strip()

    def compile_code(self):
        op = self.get_op()

        amd, dst = self.get_am(self.dst)
        ams, src = self.get_am(self.src)

        if src is not None and (amd, ams) not in ASM.INSTRUCTIONS[2][op]:
            raise SyntaxError(self)
        if src is None and dst and amd not in ASM.INSTRUCTIONS[1][op]:
            raise SyntaxError(self)
        if src is None and dst is None and op not in ASM.INSTRUCTIONS[0]:
            raise SyntaxError(self)

        amd = amd or 0
        ams = ams or 0
        dst = dst or 0
        src = src or 0

        if op in OP2SET:
            ir = op | (amd << 2) | ams
        elif op in OP1SET:
            ir = op | amd
        else:
            ir = op

        return [ir, dst, src]

    def __repr__(self):
        return f'[{self.numer}] - {self.source}'


class SyntaxError(Exception):

    def __init__(self, code: Code, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.code = code


def compile_program():
    global codes
    global marks

    with open(inputfile, encoding='utf8') as file:
        lines = file.readlines()

    for index, line in enumerate(lines):
        source = line.strip()
        if ';' in source:
            match = annotation.match(source)
            source = match.group(1)
        if not source:
            continue
        code = Code(index + 1, source)
        codes.append(code)

    code = Code(index + 2, 'HLT')
    codes.append(code)

    result = []

    current = None
    for var in range(len(codes) - 1, -1, -1):
        code = codes[var]
        if code.type == Code.TYPE_CODE:
            current = code
            result.insert(0, code)
            continue
        if code.type == Code.TYPE_LABEL:
            marks[code.name] = current
            continue
        raise SyntaxError(code)

    for index, var in enumerate(result):
        var.index = index

    with open(outputfile, 'wb') as file:
        for code in result:
            values = code.compile_code()
            for value in values:
                result = value.to_bytes(1, byteorder='little')
                file.write(result)


def main():
    try:
        compile_program()
    except SyntaxError as e:
        print(f'Syntax error at {e.code}')
        return

    print('compile program.asm finished!!!')


if __name__ == '__main__':
    main()

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦