Commit e2b13351 authored by Yu Christina Juan's avatar Yu Christina Juan
Browse files

lab04 working

parent 701d1688
......@@ -22,9 +22,9 @@ def alu(op1,op2,alu_fun): # operation determined by the input alu_fun
if alu_fun == 8: #Sub
return op1-op2
if alu_fun == 9: #Srl (shift right logical)
return (op1 % 0x100000000)>>op2
return (op1)>>op2
if alu_fun == 10: #Sll (shift left logical)
return (op1 % 0x100000000)<<op2
return (op1)<<op2
if alu_fun == 11: #Or
return op1|op2
return
......
# filename: onestage_pt1.py
import itertools
import sys
from pydigital.memory import readmemh
from pydigital.register import Register
from pydigital.utils import sextend, twos_comp
from riscv_isa import Instruction
from riscv_isa import decoder
from riscv_isa.isa import regNumToName
from riscv_isa.decoder import control, enums
from regfile import RegFile
from alu import alu
from mux import make_mux
# the PC register
PC = Register()
RF = RegFile()
control = decoder.control
filename = sys.argv[1]
# construct a memory segment for instruction memory
# load the contents from the 32-bit fetch_test hex file (big endian)
imem = readmemh(filename, word_size = 4, byteorder = 'big')
def display():
if pc_val == None:
return "PC: xxxxxxxx, IR: xxxxxxxx\n"
else:
if instr.imm != "":
instr.rs2 = f"rs2: xxxxxxxx [xx] i_imm: {int(instr.immb, 2):04x}"
else:
instr.rs2 = f"rs2: {rs2Val} [{int(instr.rs2b, 2)}] i_imm: xxxx"
if rs1Val != None and instr.rs1 != "":
rs1 = f"rs1: {rs1Val} [{int(instr.rs1b, 2)}] "
else:
rs1 = f"rs1: xxxxxxxx [xx] "
return f"PC: {pc_val:08x}, IR: {instr.val:08x}, {instr}\n" + \
f"rd: {RF.read(int(instr.rdb, 2))} [{int(instr.rdb, 2)}] " + rs1 + instr.rs2 + \
f" op: {int(instr.opcode, 2):x} func3: {int(instr.funct3)} func7: {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}:", display())
continue
# access instruction memory
instr = Instruction(imem[pc_val], pc_val)
rs1Val = None
rs2Val = None
if instr.rs1 != "":
rs1Val = RF.read(int(instr.rs1b, 2))
if instr.rs2 != "":
rs2Val = RF.read(int(instr.rs2b, 2))
if instr.name == "li":
instr.name = "addi"
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
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), \
lambda: sextend(int(instr.binVal[0:12], 2), 12), pc_val)
op1 = op1Mux(op1_sel)
op2 = op2Mux(op2_sel)
aluVal = alu(op1, op2, alu_fun)
if rf_wen:
RF.regs[int(instr.rdb, 2)] = aluVal
# print one line at the end of the clock cycle
print(f"{t}:", 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 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])
# clock logic blocks, PC is the only clocked module!
# here the next pc value is always +4
PC.clock(4 + pc_val)
# 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,6 +76,11 @@ def as_twos_comp(val):
else:
return val & 0xffffffff
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:
return (val - (1 << b))
if __name__=="__main__":
print (f'{sextend(0x80000000):08x}')
......
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
......@@ -40,9 +40,9 @@ csr_cmd:CSR.N
# this is the raw compressed control table using the edited enums
_c = """Inst val_inst,br_type,op1_sel,op2_sel,ALU_fun,wb_sel,rf_wen,mem_em,mem_wr,mask_type,csr_cmd
ADD 10005110043
ADDI 10015110043
ADDI 10025110043
AND 10004110043
ANDI 10014110043
ANDI 10024110043
AUIPC 10235110043
BEQ 18000000043
BGE 15000000043
......@@ -63,32 +63,32 @@ FENCE 10000000043
FENCE_I 10000000043
JAL 16000010043
JALR 11010010043
LB 10015211013
LBU 10015211013
LH 10015211023
LHU 10015211023
LUI 10202110043
LW 10015211043
LB 10025211013
LBU 10025211013
LH 10025211023
LHU 10025211023
LUI 10102110043
LW 10025211043
MRET 10000000042
OR 1000b110043
ORI 1001b110043
SB 10025001113
SH 10025001123
ORI 1002b110043
SB 10015001113
SH 10015001123
SLL 1000a110043
SLLI 1001a110043
SLLI 1002a110043
SLT 10006110043
SLTI 10016110043
SLTIU 10013110043
SLTI 10026110043
SLTIU 10023110043
SLTU 10003110043
SRA 10007110043
SRAI 10017110043
SRAI 10027110043
SRL 10009110043
SRLI 10019110043
SRLI 10029110043
SUB 10008110043
SW 10025001143
SW 10015001143
WFI 10000000043
XOR 10001110043
XORI 10011110043"""
XORI 10021110043"""
class IControl:
"instruction control helper class, decodes one compressed line of control signals"
......@@ -169,13 +169,13 @@ enums = {
"OP1_X": 0,
"OP1_RS1": 0,
"OP1_IMZ": 1,
"OP1_IMU": 2
"OP1_IMU": 1
},
"op2_sel": {
"OP2_X": 0,
"OP2_RS2": 0,
"OP2_IMI": 1,
"OP2_IMS": 2,
"OP2_IMI": 2,
"OP2_IMS": 1,
"OP2_PC": 3,
},
"ALU_fun": {
......
from .csr_list import csrs
from pydigital.utils import twos_comp
class BadInstruction(Exception):
pass
......@@ -16,6 +17,24 @@ def regNumToName(num):
's4', 's5', 's6', 's7', # 20..23
's8', 's9', 's10', 's11', # 24..27]
't3', 't4', 't5', 't6'][num] # 28..31
opcodeDict = { #opcode, (type, funct3), funct7/imm, inst
"0010011": {"000": "addi", "010": "slti", "110": "ori", "111": "andi", "001": "slli"},
"0110111": "lui",
"0110011": {"000": {
"0100000": "sub",
"0000000": "add"}, "001": "sll"},
"1110011": {"000": {
"000000000001": "ebreak",
"000000000000": "ecall"}}}
"""typeDict = {
"I": ["addi", "slti", "ori", "andi", "slli", "ecall"],
"R": ["add", "sub", "sll"],
"U": ["lui"]
}"""
class Instruction():
"represents/decodes RISCV instructions"
def __init__ (self, val, pc, symbols = {}):
......@@ -28,41 +47,108 @@ class Instruction():
self.val = val
self.pc = pc # pc relative instrs need pc to compute targets for display
self.symbols = symbols
self.binVal = bin(self.val)[2:].zfill(32)
self.opcode = self.binVal[25:]
#self.name = self.getName(self.binVal)
self.name = ""; self.type = ""
#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.type = self.getType()
self.name = self.getName()
def getType(self):
# return the instruction type given opcode
if self.opcode in opcodeDict:
if self.opcode == "0110011":
return "R"
if (self.opcode == "0010011") or (self.opcode == "1110011"):
return "I"
if self.opcode == "0110111":
return "U"
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.immb = self.binVal[:12] #immediate in binary
self.imm = twos_comp(int(self.immb,2), len(self.immb))
#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":
return "ori"
elif self.funct3 == "111":
return "andi"
elif (self.opcode == "1110011") and (self.funct3 == "000"):
return "ecall"
if self.funct3 == "000":
if self.rs1 == "zero":
return "li"
else:
return "addi"
elif self.funct3 == "001":
return "slli"
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
if self.funct7 == "0000000":
if self.funct3 == "000":
return "add"
elif self.funct3 == "001":
return "sll"
elif self.type == "U":
self.funct7 = "0"
self.funct3 = "0"
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"
def __str__(self):
binVal = bin(self.val)[2:].zfill(32)
opcode = binVal[25:]
insType = ""
functsb = ""
rs2 = ""
rs1 = ""
functtb = ""
rd = ""
if (opcode == "0010011") or (opcode == "1110011"): #type 1 = I
insType = "i type"
immb = binVal[:12] #immediate in binary
imm = str(int(immb, 2)) #convert integer binary to string
rs1b = binVal[12:17] #rs1 in binary
rs1 = regNumToName(int(rs1b, 2)) #rs1 reg
functtb = binVal[17:20] #funct3 in binary
rdb = binVal[20:25] #rd in binary
rd = regNumToName(int(rdb, 2)) #rd register
if (opcode == "1110011") and (functtb == "000"):
return "ecall"
if (rs1 == "zero") and (functtb == "000"):
return f"li,\t\t{rd}, {imm}"
#opcode = self.binVal[25:]
#insType = getType(opcode)
#functsb = ""
#rs2 = ""
#rs1 = ""
#functtb = ""
#rd = ""
if self.type == "I":
self.immb = self.binVal[:12] #immediate in binary
#self.imm = str(int(self.immb, 2)) #convert integer binary to string
if self.name == "ecall" or self.name == "ebreak":
return self.name
elif self.name == "li" or (self.name == "addi" and self.rs1 == "zero"):
return f"li,\t{self.rd}, {self.imm}"
return f"{self.name},\t{self.rd}, {self.rs1}, {self.imm}"
elif self.type == "R":
self.funct7 = self.binVal[:7] #funct7 in binary
self.rs2b = self.binVal[7:12] #reg rs2 in binary
self.rs2 = regNumToName(int(self.rs2b, 2)) #reg rs2
#if self.name == "add":
return f"{self.name},\t{self.rd}, {self.rs1}, {self.rs2}"
elif self.type == "U":
return f"{self.name},\t{self.rd}, {self.imm}"
elif opcode == "0110011": #type 2 == R
insType = "r type"
functsb = binVal[:7] #funct7 in binary
rs2b = binVal[7:12] #reg rs2 in binary
rs2 = regNumToName(int(rs2b, 2)) #reg rs2
rs1b = binVal[12:17] #reg rs1 in binary
rs1 = regNumToName(int(rs1b, 2)) #reg rs1
functtb = binVal[17:20] #funct3 in binary
rdb = binVal[20:25] #rd reg in binary
rd = regNumToName(int(rdb, 2)) #rd reg
if (functsb == "0000000") and (functtb == "000"):
return f"add,\t{rd}, {rs1}, {rs2}"
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