Commit 74e5c850 authored by Christina Yu's avatar Christina Yu
Browse files

lab6

parent c7be8418
# filename: onestage_pt1.py
import itertools
import sys
from pydigital.memory import readmemh, Memory, MemorySegment
from pydigital.utils import sextend, twos_comp
from pydigital.register import Register
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
# 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
ALU = lambda op1, op2, alu_fun: alu(op1, op2, alu_fun)
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')
def display():
print("--------------------------------------------------------------------------------")
if pc_val == None:
print("------------------------------< reset >------------------------------")
return "PC: xxxxxxxx, IR: xxxxxxxx"
else:
if instr.imm != None:
rs2imm_str = f"rs2: xxxxxxxx [xx] imm: {int(instr.immb, 2):04x}"
else:
rs2imm_str = f"rs2: {rs2Val} [{int(instr.rs2b, 2)}] imm: xxxx"
if instr.rd != None:
rd_str = f"rd: {RF.read(int(instr.rdb, 2))} [{instr.rd}] "
else:
rd_str = f"rd: xxxxxxxx [xx] "
if rs1Val != None:
rs1_str = f"rs1: {rs1Val} [{instr.rs1}] "
else:
rs1_str = f"rs1: xxxxxxxx [xx] "
return f"PC: {pc_val:08x}, IR: {instr.val:08x}, {instr}\n" + \
rd_str + rs1_str + rs2imm_str + \
f" op: {instr.opcode} f3: {instr.funct3} f7: {instr.funct7}" + \
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():
# sample inputs
pc_val = PC.out()
# RESET the PC register
if startup:
PC.reset(imem.begin_addr)
startup = False
print(f"{t:20d}:", display())
continue
if t == 0:
continue
# 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:
rs2Val = RF.read(int(instr.rs2b, 2))
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
ujType = lambda: twos_comp(int(instr.binVal[0] + instr.binVal[12:20] + \
instr.binVal[11] + instr.binVal[1:11], 2), 20) << 1
#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
rf_wen = control[instr.name].rf_wen
wb_sel = control[instr.name].wb_sel
#execute
op1Mux = make_mux(lambda: rs1Val, uType)
op2Mux = make_mux(lambda: rs2Val, sType, iType, lambda: pc_val)
op1 = op1Mux(op1_sel)
op2 = op2Mux(op2_sel)
aluVal = ALU(op1, op2, alu_fun)
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
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))
jumpVal = jump(pc_val, ujType())
pc_change = [pc_val + 4, jalrVal, branchVal, jumpVal]
pc_des = 0
# clock logic blocks, PC is the only clocked module!
# here the next pc value is always +4
takeBranch = False
if instr.name == "beq":
takeBranch = (rs1Val == rs2Val)
elif instr.name == "bne":
takeBranch = (rs1Val != rs2Val)
elif instr.name == "blt":
takeBranch = (rs1Val < rs2Val)
elif instr.name == "bge":
takeBranch = (rs1Val >= rs2Val)
elif instr.name == "bltu":
takeBranch = (rs1Val >= rs2Val)
elif instr.name == "bgeu":
takeBranch = (rs1Val >= rs2Val)
if instr.name == "jalr":
pc_des = 1
elif instr.type == "SB" and takeBranch:
pc_des = 2
elif instr.type == "UJ":
pc_des = 3
PC.clock(pc_change[pc_des])
# check stopping conditions on NEXT instruction
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 >------------------------------")
RF.display()
break
\ No newline at end of file
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