parent
4051d867a3
commit
4dcc3b8893
@ -0,0 +1 @@
|
|||||||
|
*/*.pdf
|
@ -0,0 +1,136 @@
|
|||||||
|
# Memory
|
||||||
|
# 32-bit address
|
||||||
|
# 8-bit cell
|
||||||
|
# Register File
|
||||||
|
# ·32 32-bit registers, with 2 read ports and 1 write portTest bench
|
||||||
|
# / Add the number in memory address 0 and 1 to address 3
|
||||||
|
# Load r1, #0
|
||||||
|
# Load r2,#1
|
||||||
|
# Add r3, r1, r2
|
||||||
|
# Store r3, #3
|
||||||
|
import numpy as np
|
||||||
|
import re
|
||||||
|
import random
|
||||||
|
class register_file:
|
||||||
|
|
||||||
|
def __init__(self , size) -> None:
|
||||||
|
self.regs = np.array([0] * size , dtype=np.int32)
|
||||||
|
self.size = size
|
||||||
|
|
||||||
|
def read(self , idx1 : int , idx2 : int) -> tuple:# 2 read port
|
||||||
|
if idx1 < 0 or idx1 >= self.size or idx2 < 0 or idx2 >= self.size:
|
||||||
|
raise IndexError(f"The index is out of range")
|
||||||
|
|
||||||
|
return (self.regs[idx1] , self.regs[idx2])
|
||||||
|
|
||||||
|
def write(self , idx : int , value : np.int32) -> None:# 1 write port
|
||||||
|
if idx < 0 or idx >= self.size:
|
||||||
|
raise IndexError("The index is out of range")
|
||||||
|
|
||||||
|
if value < -2**31 or value > 2**31 - 1:
|
||||||
|
raise ValueError("The value is out of range")
|
||||||
|
|
||||||
|
self.regs[idx] = value
|
||||||
|
|
||||||
|
def info(self) -> None:
|
||||||
|
print(f"register file : {self.regs}")
|
||||||
|
|
||||||
|
class memory:
|
||||||
|
def __init__(self , size):
|
||||||
|
self.size = size
|
||||||
|
self.mem = {key : np.int8(0) for key in range(10)}#8-bit cell
|
||||||
|
# use dictionary to simulate 2**32 byte-memory
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.mem = {key : np.int8(0) for key in self.mem}
|
||||||
|
|
||||||
|
def info(self) -> None:
|
||||||
|
print(f"memory : {self.mem}")
|
||||||
|
|
||||||
|
def read(self , idx : int) -> np.int8:
|
||||||
|
if idx < 0 or idx >= self.size:
|
||||||
|
raise IndexError("The index is out of range")
|
||||||
|
|
||||||
|
if idx not in self.mem:
|
||||||
|
self.mem[idx] = np.int8(0)
|
||||||
|
return self.mem[idx]
|
||||||
|
|
||||||
|
def write(self , idx , value : np.int8) -> None:
|
||||||
|
if idx < 0 or idx >= self.size:
|
||||||
|
raise IndexError("The index is out of range")
|
||||||
|
|
||||||
|
if(value < -128 or value > 127):
|
||||||
|
raise ValueError("The value is out of range")
|
||||||
|
|
||||||
|
self.mem[idx] = value
|
||||||
|
|
||||||
|
|
||||||
|
class instruction:
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def Load(ins : list , immediate: bool = False) -> None:
|
||||||
|
regfile.write(ins[1] , mem.read(ins[2]))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def Loadi(ins : list):#load immediate to register , just for test , style of instruction : Loadi r1 , i100
|
||||||
|
regfile.write(ins[1] , ins[2]) #to fix : merge into Load instruction by adding flag immediate , maybe
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def Store(ins : list) -> None:
|
||||||
|
mem.write(ins[2] , regfile.read(ins[1] , 0)[0])#just use one read port of regfile
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def Add(ins : list) -> None:
|
||||||
|
r1 , r2 = regfile.read(ins[2] , ins[3])
|
||||||
|
regfile.write(ins[1] , r1 + r2)
|
||||||
|
|
||||||
|
def exec_ins(self , ins : list) -> None:
|
||||||
|
target_ins = getattr(type(self) , ins[0])
|
||||||
|
if target_ins is None:
|
||||||
|
raise RuntimeError("the error instruction {}".format(ins[0]))
|
||||||
|
target_ins(ins)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse_instruction(instruc : str) -> list:
|
||||||
|
#parse the instruction
|
||||||
|
_ins = re.split(r'[ ,]+' , instruc)# split the string by space and comma
|
||||||
|
ins = [_ins[0]]
|
||||||
|
for elem in _ins:
|
||||||
|
if elem[0] == 'r' or elem[0] == '#' or elem[0] == 'i':#get the bias of address
|
||||||
|
ins.append(int(elem[1:]))
|
||||||
|
|
||||||
|
return ins
|
||||||
|
|
||||||
|
class testbench:
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def memory_random_flip():
|
||||||
|
mem.mem = {key : random.randint(-10,10) for key in mem.mem}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def test():
|
||||||
|
testbench.memory_random_flip()
|
||||||
|
mem.info()
|
||||||
|
test_instr = ['Load r1, #0' , 'Load r2,#1' , 'Add r3, r1, r2' , 'Store r3, #3']
|
||||||
|
for ins in test_instr:
|
||||||
|
_ins = instruction.parse_instruction(ins)
|
||||||
|
instruc.exec_ins(_ins)
|
||||||
|
|
||||||
|
mem.info()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
global regfile , mem , instruc
|
||||||
|
regfile = register_file(32)#32 32-bit registers
|
||||||
|
mem = memory(2 ** 32)# 32-bit address memory
|
||||||
|
instruc = instruction()
|
||||||
|
|
||||||
|
testbench.test()
|
||||||
|
while True:
|
||||||
|
_inst = input('>')
|
||||||
|
inst = instruc.parse_instruction(_inst)
|
||||||
|
instruc.exec_ins(inst)
|
||||||
|
mem.info()
|
||||||
|
regfile.info()
|
Binary file not shown.
Loading…
Reference in new issue