Commit 13d3a2e7 authored by Yu Christina Juan's avatar Yu Christina Juan
Browse files

lab5

parent e2b13351
# 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
print(str(DM.mem) + '\n')
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():
if pc_val == None:
return "PC: xxxxxxxx, IR: xxxxxxxx\n"
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.u_imm != None:
# rs2imm_str = f"rs2: xxxxxxxx [xx] i_imm: {instr.u_imm:04x}"
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}\n"
#f"rd: {RF.read(int(instr.rdb, 2))} [{int(instr.rdb, 2)}] " + rs1_str + rs2imm_str + \
#f" op: {int(instr.opcode, 2):x} f3: {int(instr.funct3)} f7: {int(instr.funct7)}" + \
#f" alu_fun: {alu_str}\n"
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
rs1Val = lambda: RF.read(int(instr.rs1b, 2)) if RF.read(int(instr.rs1b, 2)) else 0
rs2Val = lambda: RF.read(int(instr.rs2b, 2)) if RF.read(int(instr.rs2b, 2)) else 0
if instr.name == "li":
instr.name = "addi"
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
print(instr.name)
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(rs1Val, uType)
op2Mux = make_mux(rs2Val, sType, iType, 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)
print(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}:", display())
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
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
#PC.clock(4 + pc_val)
takeBranch = False
if instr.name == "beq":
takeBbranch = (rs1Val == rs2Val)
elif instr.name == "bne":
takeBbranch = (rs1Val != rs2Val)
elif instr.name == "blt":
takeBbranch = (rs1Val < rs2Val)
elif instr.name == "bge":
takeBbranch = (rs1Val >= rs2Val)
elif instr.name == "bltu":
takeBbranch = (rs1Val >= rs2Val)
elif instr.name == "bgeu":
takeBbranch = (rs1Val >= rs2Val)
print()
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.")
RF.display()
break
\ No newline at end of file
......@@ -76,7 +76,7 @@ for t in itertools.count():
wb_sel = control[instr.name].wb_sel
op1Mux = make_mux(lambda: rs1Val, lambda: sextend(int(instr.binVal[0:20], 2), 20) << 12)
op2Mux = make_mux(lambda: rs2Val, lambda: sextend(int(instr.binVal[0:7] + instr.binVal[20:25], 2), 12), \
op2Mux = make_mux(lambda: rs2Val, lambda: sextenssd(int(instr.binVal[0:7] + instr.binVal[20:25], 2), 12), \
lambda: sextend(int(instr.binVal[0:12], 2), 12), pc_val)
op1 = op1Mux(op1_sel)
......@@ -101,11 +101,11 @@ for t in itertools.count():
RF.display()
break
if instr.name == "ecall":
'''if instr.name == "ecall":
if (RF.regs[10] == 0x0) or (RF.regs[10] == 0xa):
print("ECALL(10): EXIT")
if RF.regs[10] == 0x1:
print("ECALL(1):", RF.regs[11])
print("ECALL(1):", RF.regs[11])'''
# clock logic blocks, PC is the only clocked module!
# here the next pc value is always +4
......
......@@ -78,8 +78,10 @@ def as_twos_comp(val):
def twos_comp(val, b):
"take a python signed integer value and represent as a 2-s complement integer"
if (val & (1 << (b - 1))) != 0:
if (val & (1 << (b - 1))) != 0: # if sign bit is set e.g., 8bit: 128-255
return (val - (1 << b))
return val
if __name__=="__main__":
......
......@@ -3,7 +3,7 @@ from riscv_isa.isa import regNumToName
class RegFile:
def __init__(self):
self.regs = [0]*32 #set all registers as 0
self.regs = [None]*32 #set all registers as none
def read(self, rs):
return self.regs[rs] #read contents of register
......
from decoder import control, enums
if __name__ == '__main__':
inst = ["sw", "beq", "bne", "lui", "jal"]
for i in inst:
j = control[i]
print(i)
print("\t".join(["{}:{}".format(i.rjust(8), enums[i][j.renums[i][getattr(j,i)]]) for i in j.fields]))
\ No newline at end of file
from .csr_list import csrs
from pydigital.utils import twos_comp
from pydigital.utils import twos_comp, as_twos_comp, sextend
class BadInstruction(Exception):
pass
......@@ -18,10 +18,25 @@ def regNumToName(num):
's8', 's9', 's10', 's11', # 24..27]
't3', 't4', 't5', 't6'][num] # 28..31
instrDict = {
"I": ["lw", "addi", "slti", "ori", "andi", "slli", "sltiu", "xori", "srli",
"srai","ecall"],
"R": ["sub", "add", "sll", "slt", "sltu", "xor", "srl",
"sra", "or", "and"],
"U": ["lui"],
"S": ["sw"],
"SB": ["beq", "bne", "blt", "bge", "bltu", "bgeu"],
"UJ": ["jal"],
}
opcodeDict = { #opcode, (type, funct3), funct7/imm, inst
opcodeDict = { #opcode, funct3, funct7/imm, inst
"0000011": {"010": "lw"},
"0100011": {"010": "sw"},
"1100011": {"000": "beq", "001": "bne", "100": "blt", "101": "bge", "110": "bltu", "111": "bgeu"},
"0010011": {"000": "addi", "010": "slti", "110": "ori", "111": "andi", "001": "slli"},
"0110111": "lui",
"1101111": "jal",
"0110011": {"000": {
"0100000": "sub",
"0000000": "add"}, "001": "sll"},
......@@ -29,11 +44,14 @@ opcodeDict = { #opcode, (type, funct3), funct7/imm, inst
"000000000001": "ebreak",
"000000000000": "ecall"}}}
"""typeDict = {
"I": ["addi", "slti", "ori", "andi", "slli", "ecall"],
"R": ["add", "sub", "sll"],
"U": ["lui"]
}"""
INST_TYPE_MASK = 0b00000000000000000000000001111111
INST_FUNC3_MASK = 0b00000000000000000111000000000000
INST_RD_MASK = 0b00000000000000000000111110000000
INST_RS1_MASK = 0b00000000000011111000000000000000
INST_RS2_MASK = 0b00000001111100000000000000000000
INST_IMM_ITYPE_MASK = 0b11111111111100000000000000000000
INST_IMM_UTYPE_MASK = 0b11111111111111111111000000000000
INST_FUNC7_MASK = 0b11111110000000000000000000000000
class Instruction():
"represents/decodes RISCV instructions"
......@@ -50,11 +68,13 @@ class Instruction():
self.binVal = bin(self.val)[2:].zfill(32)
self.opcode = self.binVal[25:]
#self.name = self.getName(self.binVal)
self.name = ""; self.type = ""
self.name = None; self.type = None
#self.type = self.getType(self.binVal[25:])
self.immb = None; self.rs1b = None; self.rs2b = None; self.rdb = None
self.funct3 = ""; self.funct7 = ""
self.rd = ""; self.rs1 = ""; self.rs2 = ""; self.imm = ""
self.funct3 = None; self.funct7 = None
self.rd = None; self.rs1 = None; self.rs2 = None; self.imm = None
self.i_imm = self.val & INST_IMM_ITYPE_MASK
self.u_imm = self.val & INST_IMM_UTYPE_MASK
self.type = self.getType()
self.name = self.getName()
......@@ -63,28 +83,29 @@ class Instruction():
if self.opcode in opcodeDict:
if self.opcode == "0110011":
return "R"
if (self.opcode == "0010011") or (self.opcode == "1110011"):
if (self.opcode == "0010011") or (self.opcode == "1110011") or (self.opcode == "0000011"):
return "I"
if self.opcode == "0110111":
return "U"
if self.opcode == "0100011":
return "S"
if self.opcode == "1100011":
return "SB"
if self.opcode == "1101111 ":
return "UJ"
return "error getting type"
def getName(self):
# return instruction name given binary representation
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
self.rdb = self.binVal[20:25] #rd reg in binary
self.rd = regNumToName(int(self.rdb, 2)) #rd reg
if self.type == "I":
self.funct7 = "0"
#self.funct7 = "0"
self.immb = self.binVal[:12] #immediate in binary
self.imm = twos_comp(int(self.immb,2), len(self.immb))
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
#self.imm = str(int(self.immb, 2)) #convert integer binary to string
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
if self.funct3 == "010":
return "slti"
elif self.funct3 == "110":
......@@ -103,9 +124,13 @@ class Instruction():
elif self.type == "R":
self.funct7 = self.binVal[:7] #funct7 in binary
self.funct3 = self.binVal[17:20] #funct3 in binary
self.rs2b = self.binVal[7:12] #reg rs2 in binary
self.rs2 = regNumToName(int(self.rs2b, 2)) #reg rs2
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
self.rdb = self.binVal[20:25] #rd reg in binary
self.rd = regNumToName(int(self.rdb, 2)) #rd reg
if self.funct7 == "0000000":
if self.funct3 == "000":
return "add"
......@@ -113,15 +138,71 @@ class Instruction():
return "sll"
elif self.type == "U":
self.funct7 = "0"
self.funct3 = "0"
self.rdb = self.binVal[20:25] #rd reg in binary
self.rd = regNumToName(int(self.rdb, 2)) #rd reg
self.immb = self.binVal[:20]
self.imm = twos_comp(int(self.immb,2), len(self.immb))
#self.imm = str(int(self.immb, 2))
if self.opcode == "0110111":
return "lui"
#else:
# return "auipc"
elif self.opcode == "0010111":
return "auipc"
elif self.type == "UJ":
self.rdb = self.binVal[20:25] #rd reg in binary
self.rd = regNumToName(int(self.rdb, 2)) #rd reg
self.immb = self.binVal[0] + self.binVal[12:20] + self.binVal[11] + self.binVal[1:11]
self.imm = twos_comp(int(self.immb,2), len(self.immb)) << 1
#self.imm = str(int(self.immb, 2))
if self.opcode == "0110111":
return "lui"
elif self.opcode == "0010111":
return "auipc"
elif self.type == "S":
self.rs2b = self.binVal[7:12] #reg rs2 in binary
self.rs2 = regNumToName(int(self.rs2b, 2)) #reg rs2
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]
imm2b = self.binVal[0:7]
self.immb = imm1b + imm2b
self.imm = twos_comp(int(self.immb,2), len(self.immb))
if self.funct3 == "000":
return "sb"
elif self.funct3 == "001":
return "sh"
elif self.funct3 == "010":
return "sw"
elif self.funct3 == "011":
return "sd"
elif self.type == "SB":
self.funct3 = self.binVal[17:20] #funct3 in binary
self.rs2b = self.binVal[7:12] #reg rs2 in binary
self.rs2 = regNumToName(int(self.rs2b, 2)) #reg rs2
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))
if self.funct3 == "000":
return "beq"
elif self.funct3 == "001":
return "bne"
elif self.funct3 == "100":
return "blt"
elif self.funct3 == "101":
return "bge"
elif self.funct3 == "110":
return "bltu"
elif self.funct3 == "111":
return "bgeu"
def __str__(self):
#opcode = self.binVal[25:]
......@@ -151,4 +232,10 @@ class Instruction():
elif self.type == "U":
return f"{self.name},\t{self.rd}, {self.imm}"
elif self.type == "S" or self.type == "SB":
return f"{self.name}\t{self.rs1}, {self.rs2}, {self.imm}"
elif self.type == "UJ":
return f"{self.name}\t{self.rd}, pc + {self.imm}"
return ""
\ 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