Commit db7f40b2 authored by Christina Yu's avatar Christina Yu
Browse files

lab6

parent 74e5c850
#alu.py
from pydigital.utils import sextend
alu_ops = ['X','^','cp','sltu', 'and', 'add', 'slt', 'sra', 'sub', 'srl', 'sll', 'or']
def alu(op1,op2,alu_fun): # operation determined by the input alu_fun
def add(op1, op2):
if op1 == -0x7fffff60:
print('dfsa')
return op1 + op2
def alu(op1, op2, alu_fun): # operation determined by the input alu_fun
if alu_fun == 0: # 0 (no operation)
return 0
if alu_fun == 1: #Xor
......@@ -14,7 +20,7 @@ def alu(op1,op2,alu_fun): # operation determined by the input alu_fun
if alu_fun == 4: #And
return op1&op2
if alu_fun == 5: #Add
return op1+op2
return add(op1, op2)
if alu_fun == 6: #Slt (set less than)
return int(op1<op2)
if alu_fun == 7: #Sra (shift right arithmetic)
......@@ -24,7 +30,7 @@ def alu(op1,op2,alu_fun): # operation determined by the input alu_fun
if alu_fun == 9: #Srl (shift right logical)
return (op1)>>op2
if alu_fun == 10: #Sll (shift left logical)
return (op1)<<op2
return sextend((op1) << op2)
if alu_fun == 11: #Or
return op1|op2
return
......
# filename: onestage_pt1.py
# filename: onestage_elf.py
import itertools
import sys
from pydigital.memory import readmemh, Memory, MemorySegment
from pydigital.utils import sextend, twos_comp
#from pydigital.memory import readmemh, MemorySegment
from pydigital.utils import sextend, as_twos_comp, twos_comp
from pydigital.elfloader import load_elf
from pydigital.register import Register
from riscv_isa.isa import regNumToName
from pydigital.memory import Memory
#from riscv_isa.isa import regNumToName
from riscv_isa.decoder import control, enums
from riscv_isa import Instruction, decoder
from regfile import RegFile
from mux import make_mux
from alu import alu
control = decoder.control
ALU = lambda op1, op2, alu_fun: alu(op1, op2, alu_fun)
#DM = Memory(MemorySegment(0xE0000, 0x4000)) #0xe0000, 0x10000
binFile = sys.argv[1]
elfMem, symbolTable = load_elf(binFile)
imem = elfMem
# the PC register
PC = Register()
RF = RegFile()
DM = Memory(MemorySegment(0xE0000, 0x4000)) #0xe0000, 0x10000
RF.clock(2, 0xEFFFF, True)
control = decoder.control
RF.regs[2] = 0xeffff
RF.regs[0] = 0x00000
DM = Memory(elfMem)
ALU = lambda op1, op2, alu_fun: alu(op1, op2, alu_fun)
RF.regs[2] = 0xeffff #pointer
RF.regs[0] = 0x00000
#RF.clock(2, 0xEFFFF, True)
#RF.regs[2] = 0xeffff #pointer
#RF.regs[0] = 0x00000
# construct a memory segment for instruction memory
# load the contents from the 32-bit fetch_test hex file (big endian)
imem = readmemh(sys.argv[1], word_size = 4, byteorder = 'big')
# imem = readmemh(sys.argv[1], word_size = 4, byteorder = 'big')
def display():
print("--------------------------------------------------------------------------------")
......@@ -57,6 +58,7 @@ def display():
f" alu_fun: {alu_str}"
startup = True
# generate system clocks until we reach a stopping condition
# this is basically the run function from the last lab
for t in itertools.count():
......@@ -65,18 +67,17 @@ for t in itertools.count():
# RESET the PC register
if startup:
PC.reset(imem.begin_addr)
#PC.reset(imem.begin_addr)
PC.reset(symbolTable["_start"])
startup = False
print(f"{t:20d}:", display())
continue
if t == 0:
continue
# access instruction memory
# access instruction memory
instr = Instruction(imem[pc_val], pc_val)
###################################################################################
rs1Val = None
rs2Val = None
if instr.rs1 != None:
rs1Val = RF.read(int(instr.rs1b, 2))
if instr.rs2 != None:
......@@ -84,59 +85,42 @@ for t in itertools.count():
iType = lambda: twos_comp(int(instr.binVal[0:12], 2), 12)
sType = lambda: twos_comp(int(instr.binVal[0:7] + instr.binVal[20:25], 2), 12)
uType = lambda: twos_comp(int(instr.binVal[0:20], 2), 20) << 12
uType = lambda: int(instr.binVal[0:20], 2) << 12
ujType = lambda: twos_comp(int(instr.binVal[0] + instr.binVal[12:20] + \
instr.binVal[11] + instr.binVal[1:11], 2), 20) << 1
sbType = lambda: twos_comp(int(instr.binVal[0] + instr.binVal[24] + instr.binVal[1:7] + instr.binVal[20:24], 2), 12) << 1
###################################################################################
# decode
if instr.name in ["CSRRS", "CSRRW"]:
print(f"{t:20d}:", display())
PC.clock(pc_val + 4)
continue
#decoding
alu_fun = control[instr.name].ALU_fun
alu_str = control[instr.name].renums["ALU_fun"][getattr(control[instr.name], "ALU_fun")]
op1_sel = control[instr.name].op1_sel
op2_sel = control[instr.name].op2_sel
mem_wr = control[instr.name].mem_wr
mem_val = control[instr.name].mask_type
rf_wen = control[instr.name].rf_wen
wb_sel = control[instr.name].wb_sel
mem_em = control[instr.name].mem_em
#execute
# execute
op1Mux = make_mux(lambda: rs1Val, uType)
op2Mux = make_mux(lambda: rs2Val, sType, iType, lambda: pc_val)
op2Mux = make_mux(lambda: rs2Val, sType, iType, lambda: (pc_val))
op1 = op1Mux(op1_sel)
op2 = op2Mux(op2_sel)
aluVal = ALU(op1, op2, alu_fun)
aluValUnsigned = as_twos_comp(aluVal)
rData = DM.out(aluVal)
DM.clock(aluVal, rs2Val, mem_wr)
if instr.name == "sw":
print(DM.mem[aluVal])
wdMux = lambda x: [pc_val + 4, aluVal, rData][x]
wd = wdMux(wb_sel)
# writeback
rd = int(instr.binVal[20:25], 2)
RF.clock(rd, wd, rf_wen)
# print one line at the end of the clock cycle
print(f"{t:20d}:", display())
RF.display()
if instr.name == 'ecall':
if RF.read(10) == 1:
print(f"ECALL({RF.read(10)}): {RF.read(11)}\n")
elif (RF.read(10) == 0) or (RF.read(10) == 10):
strr = f"ECALL({RF.read(10)}): "
if RF.read(10) == 10:
print(strr + 'EXIT\n')
else:
print(strr + 'HALT\n')
RF.display()
break
if rs1Val == None: rs1Val = 0
jalr = lambda i_imm, rs1Val: rs1Val + i_imm
# if rs1Val == None: rs1Val = 0
jalr = lambda i_imm, rs1Val: as_twos_comp(rs1Val) + i_imm
branch = lambda pc, imm: pc + imm
jump = lambda pc, imm: pc + imm
jalrVal = jalr(i_imm = iType(), rs1Val = rs1Val)
branchVal = branch(pc_val, twos_comp(int(instr.binVal[0:7] + instr.binVal[20:25], 2), 12))
branchVal = branch(pc_val, sbType())
jumpVal = jump(pc_val, ujType())
pc_change = [pc_val + 4, jalrVal, branchVal, jumpVal]
pc_des = 0
......@@ -153,9 +137,9 @@ for t in itertools.count():
elif instr.name == "bge":
takeBranch = (rs1Val >= rs2Val)
elif instr.name == "bltu":
takeBranch = (rs1Val >= rs2Val)
takeBranch = (as_twos_comp(rs1Val) < as_twos_comp(rs2Val))
elif instr.name == "bgeu":
takeBranch = (rs1Val >= rs2Val)
takeBranch = (as_twos_comp(rs1Val) >= as_twos_comp(rs2Val))
if instr.name == "jalr":
pc_des = 1
......@@ -165,10 +149,60 @@ for t in itertools.count():
pc_des = 3
PC.clock(pc_change[pc_des])
# memory
rData = None
if (mem_em):
rData = DM.out(aluValUnsigned)
DM.clock(aluValUnsigned, rs2Val, mem_wr)
if mem_em == 1 and mem_wr == 1 and 'tohost' in symbolTable:
if (mem_val == 4 and aluVal == symbolTable['tohost']+4) or \
(mem_val == 8 and aluVal == symbolTable['tohost']):
# syscall detected, tohost is a 64 bit reg, so wait for addr of second word on 32 bit
val = DM.mem[symbolTable['tohost']]
if val & 0b1 == 0b1:
# exit
print(f"{t:20d}:", display())
RF.display()
print (f"SYSCALL: exit ({val>>1})")
sys.exit(val>>1)
else:
which = DM.mem[DM.mem[symbolTable['tohost']]]
arg0 = DM.mem[DM.mem[symbolTable['tohost']] + 8]
arg1 = DM.mem[DM.mem[symbolTable['tohost']] + 16]
arg2 = DM.mem[DM.mem[symbolTable['tohost']] + 24]
if which == 64:
print(DM.mem[arg1:arg1+arg2].decode("ASCII"), end = "")
DM.mem[symbolTable['fromhost']] = 1
wdMux = lambda x: [pc_val + 4, aluVal, rData][x]
wd = wdMux(wb_sel)
# writeback
rd = int(instr.binVal[20:25], 2)
RF.clock(rd, wd, rf_wen)
# print one line at the end of the clock cycle
print(f"{t:20d}:", display())
###################################################################################
RF.display()
if instr.name == 'ecall':
if RF.read(10) == 1:
print(f"ECALL({RF.read(10)}): {RF.read(11)}\n")
elif (RF.read(10) == 0) or (RF.read(10) == 10):
strr = f"ECALL({RF.read(10)}): "
if RF.read(10) == 10:
print(strr + 'EXIT\n')
else:
print(strr + 'HALT\n')
RF.display()
break
###################################################################################
# check stopping conditions on NEXT instruction
if PC.out() > 0x1100:
print("STOP -- PC is large! Is something wrong?")
break
# if PC.out() > 0x1100:
# print("STOP -- PC is large! Is something wrong?")
# break
if imem[PC.out()] == 0:
#print("Done -- end of program.")
print("------------------------------< Final reg values >------------------------------")
......
......@@ -4,7 +4,7 @@ from riscv_isa.isa import regNumToName
class RegFile:
def __init__(self):
self.regs = [None]*32 #set all registers as none
self.regs[0] = 0
self.regs[0] = 0x0
def read(self, rs):
return self.regs[rs] #read contents of register
......@@ -17,8 +17,8 @@ class RegFile:
def display(self):
for i in range(0, 32, 4): # loop to display registers and their content
fmt_reg = lambda i: f"{self.regs[i]:09x}" if self.regs[i] != None else "xxxxxxxx"
print(" ".join([f"{regNumToName(i+j).rjust(4)}: {fmt_reg(i+j)}" for j in range(4)]))
fmt_reg = lambda i: f"{self.regs[i]:08x}" if self.regs[i] != None else "xxxxxxxx"
print("\t\t".join([f"{regNumToName(i+j).rjust(6)}: {fmt_reg(i+j)}" for j in range(4)]))
"""testbench"""
......
......@@ -43,7 +43,7 @@ ADD 10005110043
ADDI 10025110043
AND 10004110043
ANDI 10024110043
AUIPC 10235110043
AUIPC 10135110043
BEQ 18000000043
BGE 15000000043
BGEU 12000000043
......
......@@ -189,7 +189,7 @@ class Instruction():
self.funct3 = self.binVal[17:20] #funct3 in binary
imm1b = self.binVal[20:25]
imm2b = self.binVal[0:7]
self.immb = imm1b + imm2b
self.immb = imm2b + imm1b
self.imm = twos_comp(int(self.immb,2), len(self.immb))
if self.funct3 == "000":
return "sb"
......@@ -207,11 +207,13 @@ class Instruction():
self.rs1b = self.binVal[12:17] #reg rs1 in binary
self.rs1 = regNumToName(int(self.rs1b, 2)) #reg rs1
self.funct3 = self.binVal[17:20] #funct3 in binary
imm1b = self.binVal[20:25]
imm1b = self.binVal[20:25]
imm2b = self.binVal[0:7]
self.immb = imm1b + imm2b
self.imm = twos_comp(int(self.immb,2), len(self.immb))
#imm1b = self.binVal[20:25]
#imm2b = self.binVal[0:7]
#self.immb = imm1b + imm2b
#self.imm = twos_comp(int(self.immb,2), len(self.immb))
self.immb = self.binVal[0] + self.binVal[24] + self.binVal[1:7] + self.binVal[20:24]
self.imm = twos_comp(int(self.immb,2), len(self.immb)) << 1
if self.funct3 == "000":
return "beq"
elif self.funct3 == "001":
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment