def dlx(clk_period=1, Reset=Signal(intbv(0)[1:]), Zero=Signal(intbv(0)[1:])): """ 5级流水线DLX处理器 ======================================= Stages ------ +------------------+ | +------- Hazard | | +-> Detect <-----+ | | | | | | | | | | v v | v | [IF] -> IF/ID -> [ID] -> ID/EX -> [EX] -> EX/MEM -> [MEM] -> MEM/WB __ ^ | ^ | | | | | | <_____________| | | | +> FORW <___________________________| | | | |_______________________________________________________| 约定: ------------ * 信号用驼峰命名法 * 实例用匈牙利命名法 * 为区分在两个及以上阶段使用的信号,增加了后缀。 例如:'PcAdderO_if' 在 IF阶段,PcAdderO_id 在ID阶段 """ ############################## # clock settings ############################## # 时钟信号 Clk = Signal(intbv(0)[1:]) ClkPc = Signal(intbv(0)[1:]) clk_driver = clock_driver(Clk, clk_period) clk_driver_pc = clock_driver(ClkPc, clk_period * 4) #################### #feedback Signals ###################### # signals from and advanced stage which feeds a previous component BranchAdderO_mem = Signal(intbv(0, min=MIN, max=MAX)[32:]) # IF级中控制PC的多路选择器的信号(branch or immediate) PCSrc_mem = Signal(intbv(0)[1:]) # 当分支指令时为1 FlushOnBranch = PCSrc_mem # MuxMemO_wb 数据的寄存器写入指针 WrRegDest_wb = Signal(intbv(0)[32:]) # WB输出的数据 MuxMemO_wb = Signal(intbv(0, min=MIN, max=MAX)) RegWrite_wb = Signal(intbv(0)[1:]) # Forwarding 单元中生成的信号,控制输入至ALU的多路选择器 ForwardA, ForwardB = [Signal(intbv(0)[2:]) for i in range(2)] AluResult_mem = Signal(intbv(0, min=MIN, max=MAX)) # 判断流水线是否阻塞,该信号会使PC冻结,并把所有控制信号置零 Stall = Signal(intbv(0)[1:]) ############################## # IF ############################## #instruction memory # 连接PC 和 Instruction Memory Ip = Signal(intbv(0)[32:]) Instruction_if = Signal(intbv(0)[32:]) im = instruction_memory(Ip, Instruction_if) #PC # 输出至branch多路选择器,pc的输入 NextIp = Signal(intbv(0)[32:]) pc = program_counter(Clk, NextIp, Ip, Stall) #pc_adder # 这里的1代表1条指令,即4字节 INCREMENT = 1 # pc_addr 的输出,branch_adder and mux_branch的输入 PcAdderOut_if = Signal(intbv(0)[32:]) #复用ALU实现PC + 4 pc_adder = ALU(Signal(0b0010), Ip, Signal(INCREMENT), PcAdderOut_if, Signal(0)) #控制下条指令还是分支指令 mux_pc_source = mux2(PCSrc_mem, NextIp, PcAdderOut_if, BranchAdderO_mem) ############################## # IF/ID ############################## PcAdderOut_id = Signal(intbv(0)[32:]) Instruction_id = Signal(intbv(0)[32:]) latch_if_id_ = latch_if_id(Clk, FlushOnBranch, Instruction_if, PcAdderOut_if, Instruction_id, PcAdderOut_id, Stall) ############################## # ID ############################## #DECODER Opcode_id = Signal(intbv(0)[6:]) #instruction 31:26 Rs_id = Signal(intbv(0)[5:]) #instruction 25:21 Rt_id = Signal(intbv(0)[5:]) #instruction 20:16 Rd_id = Signal(intbv(0)[5:]) #instruction 15:11 Shamt_id = Signal(intbv(0)[5:]) #instruction 10:6 Func_id = Signal(intbv(0)[6:]) #instruction 5:0 Address16_id = Signal(intbv(0, min=-(2**15), max=2**15 - 1)) #instruction 15:0 NopSignal = Signal(intbv(0)[1:]) instruction_decoder_ = instruction_dec(Instruction_id, Opcode_id, Rs_id, Rt_id, Rd_id, Shamt_id, Func_id, Address16_id, NopSignal) #sign extend Address32_id = Signal(intbv(0, min=MIN, max=MAX)) sign_extend_ = sign_extend(Address16_id, Address32_id) #CONTROL signals_1bit = [Signal(intbv(0)[1:]) for i in range(7)] RegDst_id, ALUSrc_id, MemtoReg_id, RegWrite_id, MemRead_id, MemWrite_id, Branch_id = signals_1bit ALUop_id = Signal(intbv(0)[2:]) control_ = control(Opcode_id, RegDst_id, Branch_id, MemRead_id, MemtoReg_id, ALUop_id, MemWrite_id, ALUSrc_id, RegWrite_id, NopSignal, Stall) #REGISTER FILE Data1_id = Signal(intbv(0, min=MIN, max=MAX)) Data2_id = Signal(intbv(0, min=MIN, max=MAX)) register_file_i = register_file(Clk, Rs_id, Rt_id, WrRegDest_wb, MuxMemO_wb, RegWrite_wb, Data1_id, Data2_id, depth=32) ############################## # ID/EX ############################## PcAdderOut_ex = Signal(intbv(0)[32:]) signals_1bit = [Signal(intbv(0)[1:]) for i in range(7)] RegDst_ex, ALUSrc_ex, MemtoReg_ex, RegWrite_ex, MemRead_ex, MemWrite_ex, Branch_ex = signals_1bit ALUop_ex = Signal(intbv(0)[2:]) Data1_ex = Signal(intbv(0, min=MIN, max=MAX)) Data2_ex = Signal(intbv(0, min=MIN, max=MAX)) Rs_ex = Signal(intbv(0)[5:]) #instruction 25:21 Rt_ex = Signal(intbv(0)[5:]) #instruction 20:16 Rd_ex = Signal(intbv(0)[5:]) #instruction 15:11 #Shamt_ex = Signal(intbv(0)[5:]) #instruction 10:6 Func_ex = Signal(intbv(0)[6:]) #instruction 5:0 Address32_ex = Signal(intbv(0, min=MIN, max=MAX)) latch_id_ex_ = latch_id_ex( Clk, FlushOnBranch, PcAdderOut_id, Data1_id, Data2_id, Address32_id, Rs_id, Rt_id, Rd_id, Func_id, RegDst_id, ALUop_id, ALUSrc_id, #去到 EX 的信号 Branch_id, MemRead_id, MemWrite_id, #去到 MEM 的信号 RegWrite_id, MemtoReg_id, #去到 WB 的信号 PcAdderOut_ex, Data1_ex, Data2_ex, Address32_ex, Rs_ex, Rt_ex, Rd_ex, Func_ex, RegDst_ex, ALUop_ex, ALUSrc_ex, #去到 EX 的信号 Branch_ex, MemRead_ex, MemWrite_ex, #去到 MEM 的信号 RegWrite_ex, MemtoReg_ex #去到 WB 的信号 ) ############################## # EX ############################## BranchAdderO_ex = Signal(intbv(0, min=MIN, max=MAX)[32:]) Zero_ex = Signal(intbv(0)[1:]) AluResult_ex = Signal(intbv(0, min=MIN, max=MAX)) ForwMux1Out, ForwMux2Out = [ Signal(intbv(0, min=MIN, max=MAX)) for i in range(2) ] MuxAluDataSrc_ex = Signal(intbv(0, min=MIN, max=MAX)) WrRegDest_ex = Signal(intbv(0)[32:]) forw_mux1_ = mux4(ForwardA, ForwMux1Out, Data1_ex, MuxMemO_wb, AluResult_mem) forw_mux2_ = mux4(ForwardB, ForwMux2Out, Data2_ex, MuxMemO_wb, AluResult_mem) mux_alu_src = mux2(ALUSrc_ex, MuxAluDataSrc_ex, ForwMux2Out, Address32_ex) #Branch adder branch_adder_ = ALU(Signal(0b0010), PcAdderOut_ex, Address32_ex, BranchAdderO_ex, Signal(0)) #ALU Control AluControl = Signal(intbv('1111')[4:]) #control signal to alu alu_control_ = alu_control(ALUop_ex, Func_ex, AluControl) #ALU alu_ = ALU(AluControl, ForwMux1Out, MuxAluDataSrc_ex, AluResult_ex, Zero_ex) #控制写入寄存器是rt或rd mux_wreg = mux2(RegDst_ex, WrRegDest_ex, Rt_ex, Rd_ex) ############################## # EX/MEM ############################## BranchAdderO_mem = Signal(intbv(0, min=MIN, max=MAX)) Zero_mem = Signal(intbv(0)[1:]) Data2_mem = Signal(intbv(0, min=MIN, max=MAX)) WrRegDest_mem = Signal(intbv(0)[32:]) #control signals signals_1bit = [Signal(intbv(0)[1:]) for i in range(5)] MemtoReg_mem, RegWrite_mem, MemRead_mem, MemWrite_mem, Branch_mem = signals_1bit latch_ex_mem_ = latch_ex_mem( Clk, Reset, BranchAdderO_ex, AluResult_ex, Zero_ex, Data2_ex, WrRegDest_ex, Branch_ex, MemRead_ex, MemWrite_ex, #去到 MEM 的信号 RegWrite_ex, MemtoReg_ex, #去到 WB 的信号 BranchAdderO_mem, AluResult_mem, Zero_mem, Data2_mem, WrRegDest_mem, Branch_mem, MemRead_mem, MemWrite_mem, #去到 MEM 的信号 RegWrite_mem, MemtoReg_mem, #去到 WB 的信号 ) ############################## # MEM ############################## DataMemOut_mem = Signal(intbv(0, min=MIN, max=MAX)) #branch AND gate branch_and_gate = and_gate(Branch_mem, Zero_mem, PCSrc_mem) #data memory data_memory_ = data_memory(Clk, AluResult_mem, Data2_mem, DataMemOut_mem, MemRead_mem, MemWrite_mem) ############################## # EX/WB ############################## #RegWrite_wb, on feedback signals section MemtoReg_wb = Signal(intbv(0)[1:]) DataMemOut_wb = Signal(intbv(0, min=MIN, max=MAX)) AluResult_wb = Signal(intbv(0, min=MIN, max=MAX)) #WrRegDest_wb on feedback signals sections. latch_mem_wb_ = latch_mem_wb( Clk, Reset, DataMemOut_mem, AluResult_mem, WrRegDest_mem, RegWrite_mem, MemtoReg_mem, #去到 WB 的信号 DataMemOut_wb, AluResult_wb, WrRegDest_wb, RegWrite_wb, MemtoReg_wb, #去到 WB 的信号 ) ############################## # WB ############################## #mux2(sel, mux_out, chan1, chan2): mux_mem2reg_ = mux2(MemtoReg_wb, MuxMemO_wb, AluResult_wb, DataMemOut_wb) ############################## # Forwarding unit ############################## forwarding_ = forwarding( RegWrite_mem, WrRegDest_mem, Rs_ex, Rt_ex, #inputs of EX hazards RegWrite_wb, WrRegDest_wb, #left inputs of MEM hazards ForwardA, ForwardB) ############################## # hazard detection unit ############################## hazard_detector_ = hazard_detector(MemRead_ex, Rt_ex, Rs_id, Rt_id, Stall) if DEBUG: @always(Clk.posedge) def debug_internals(): sep = "\n" + "=" * 31 + " cycle %i (%ins)" + "=" * 31 print(sep % (int(now() / 2.0 + 0.5), now())) #IF print("\n" + "." * 35 + " IF " + "." * 35 + "\n") print( "PcAdderOut_if %i | BranchAdderO_mem %i | PCSrc_mem %i | NextIp %i | Ip %i" % (PcAdderOut_if, BranchAdderO_mem, PCSrc_mem, NextIp, Ip)) print('Instruction_if %s (%i)' % (bin(Instruction_if, 32), Instruction_if)) if True: # now () > 2: #ID print("\n" + "." * 35 + " ID " + "." * 35 + "\n") print("PcAdderO_id %i | Instruction_id %s (%i) | Nop %i" % (PcAdderOut_id, bin(Instruction_id, 32), Instruction_id, NopSignal)) print( 'Op %s | Rs %i | Rt %i | Rd %i | Func %i | Addr16 %i | Addr32 %i' % \ (bin(Opcode_id, 6), Rs_id, Rt_id, Rd_id, Func_id, Address16_id, Address32_id )) print('Data1 %i | Data2 %i' % (Data1_id, Data2_id)) print('-->CONTROL') print( 'RegDst %i ALUop %s ALUSrc %i | Branch %i MemR %i MemW %i | RegW %i Mem2Reg %i ' % \ ( RegDst_id , bin(ALUop_id, 2), ALUSrc_id, Branch_id, MemRead_id, MemWrite_id, RegWrite_id, MemtoReg_id)) print('Stall --> %i' % Stall) if True: #if now () > 4: #EX print("\n" + "." * 35 + " EX " + "." * 35 + "\n") print("PcAdderO_ex %i | BranchAdderO_ex %i " % (PcAdderOut_ex, BranchAdderO_ex)) print("Rs %i | Rt %i | Rd %i | Func %i | Addr32 %i" % (Rs_ex, Rt_ex, Rd_ex, Func_ex, Address32_ex)) print('Data1_ex %i | Data2_ex %i' % (Data1_ex, Data2_ex)) print('ForwardA %i | ForwardB %i' % (ForwardA, ForwardB)) print('ForwMux1Out %i | ForwMux2Out %i' % (ForwMux1Out, ForwMux2Out)) print('-->CONTROL') print( 'RegDst %i ALUop %s ALUSrc %i | Branch %i MemR %i MemW %i | RegW %i Mem2Reg %i ' % \ ( RegDst_ex , bin(ALUop_ex, 2), ALUSrc_ex, Branch_ex, MemRead_ex, MemWrite_ex, RegWrite_ex, MemtoReg_ex)) print('--> ALU') print( 'MuxAluDataSrc %i | AluCtrl %s | AluResult_ex %i | Zero_ex %i' % (MuxAluDataSrc_ex, bin(AluControl, 4), AluResult_ex, Zero_ex)) print('WrRegDest_ex %i' % WrRegDest_ex) if True: #if now () > 6: #MEM print("\n" + "." * 35 + "MEM " + "." * 35 + "\n") print("BranchAdderO_mem %i " % (BranchAdderO_mem)) print('-->CONTROL') print( 'Branch %i MemR %i MemW %i | RegW %i Mem2Reg %i ' % \ ( Branch_mem, MemRead_mem, MemWrite_mem, RegWrite_mem, MemtoReg_mem)) print('--> Branch') print('Branch_mem %i Zero %i | PCSrc_mem %i' % (Branch_mem, Zero_mem, PCSrc_mem)) print('--> Data mem') print( 'AluResult_mem %i | Data2_mem %i | DataMemOut_mem %i | MemW %i MemR %i' \ % (AluResult_mem, Data2_mem, DataMemOut_mem, MemWrite_mem, MemRead_mem)) print('WrRegDest_mem %i' % WrRegDest_mem) if True: #if now() > 8: #WB print("\n" + "." * 35 + "WB" + "." * 35 + "\n") print('CONTROL --> RegW %i Mem2Reg %i ' % (RegWrite_mem, MemtoReg_mem)) print('DataMemOut_wb %i | AluResult_wb %i | MuxMemO_wb %i ' % (DataMemOut_wb, AluResult_wb, MuxMemO_wb)) print('WrRegDest_wb %i | MuxMemO_wb %i' % (WrRegDest_wb, MuxMemO_wb)) return instances()
def pipeline(clk_period=1, Reset=Signal(intbv(0)[1:]), Zero=Signal(intbv(0)[1:])): """ A DLX processor with 5 pipeline stages. ======================================= Stages ------ [IF] -> IF/ID -> [ID] -> ID/EX -> [EX] -> EX/MEM -> [MEM] -> MEM/WB __ ^ | |_______________________________________________________| Conventions: ------------ * Signals are in ``CamelCase`` * Instances are with ``under_score`` * The signals shared two or more stage are suffixed with the pipeline stage to which it belongs. For example: ``PcAdderO_if`` before IF/ID latch is the same signal than ``PcAdderO_id`` after it. """ ############################## # clock settings ############################## Clk = Signal(intbv(0)[1:]) # internal clock ClkPc = Signal(intbv(0)[1:]) # frec should be almost 1/4 clk internal clk_driver = clock_driver(Clk, clk_period) clk_driver_pc = clock_driver(ClkPc, clk_period * 4) #################### # feedback Signals ###################### # signals from and advanced stage which feeds a previous component BranchAdderO_mem = Signal(intbv(0, min=MIN, max=MAX)[32:]) PCSrc_mem = Signal(intbv(0)[1:]) # control of mux for program_counter on IF stage - (branch or inmediante_next) WrRegDest_wb = Signal(intbv(0)[32:]) # register pointer where MuxMemO_wb data will be stored. MuxMemO_wb = Signal( intbv(0, min=MIN, max=MAX) ) # data output from WB mux connected as Write Data input on Register File (ID stage) RegWrite_wb = Signal(intbv(0)[1:]) ############################## # IF ############################## # instruction memory Ip = Signal(intbv(0)[32:]) # connect PC with intruction_memory Instruction_if = Signal(intbv(0)[32:]) # 32 bits instruction line. im = instruction_memory(Ip, Instruction_if) # PC NextIp = Signal(intbv(0)[32:]) # output of mux_branch - input of pc pc = program_counter(Clk, NextIp, Ip) # pc_adder INCREMENT = 1 # it's 4 in the book, but my memory it's organized in 32bits words, not bytes PcAdderOut_if = Signal(intbv(0)[32:]) # output of pc_adder - input0 branch_adder and mux_branch pc_adder = ALU( Signal(0b0010), Ip, Signal(INCREMENT), PcAdderOut_if, Signal(0) ) # hardwire an ALU to works as an adder # mux controlling next ip branches. mux_pc_source = mux2(PCSrc_mem, NextIp, PcAdderOut_if, BranchAdderO_mem) ############################## # IF/ID ############################## PcAdderOut_id = Signal(intbv(0)[32:]) Instruction_id = Signal(intbv(0)[32:]) latch_if_id_ = latch_if_id(Clk, Reset, Instruction_if, PcAdderOut_if, Instruction_id, PcAdderOut_id) ############################## # ID ############################## # DECODER Opcode_id = Signal(intbv(0)[6:]) # instruction 31:26 - to Control Rs_id = Signal(intbv(0)[5:]) # instruction 25:21 - to read_reg_1 Rt_id = Signal(intbv(0)[5:]) # instruction 20:16 - to read_reg_2 and mux controlled by RegDst Rd_id = Signal(intbv(0)[5:]) # instruction 15:11 - to the mux controlled by RegDst Shamt_id = Signal(intbv(0)[5:]) # instruction 10:6 - Func_id = Signal(intbv(0)[6:]) # instruction 5:0 - to ALUCtrl Address16_id = Signal(intbv(0, min=-(2 ** 15), max=2 ** 15 - 1)) # instruction 15:0 - to Sign Extend NopSignal = Signal(intbv(0)[1:]) instruction_decoder_ = instruction_dec( Instruction_id, Opcode_id, Rs_id, Rt_id, Rd_id, Shamt_id, Func_id, Address16_id, NopSignal ) # sign extend Address32_id = Signal(intbv(0, min=MIN, max=MAX)) sign_extend_ = sign_extend(Address16_id, Address32_id) # CONTROL signals_1bit = [Signal(intbv(0)[1:]) for i in range(7)] RegDst_id, ALUSrc_id, MemtoReg_id, RegWrite_id, MemRead_id, MemWrite_id, Branch_id = signals_1bit ALUop_id = Signal(intbv(0)[2:]) control_ = control( Opcode_id, RegDst_id, Branch_id, MemRead_id, MemtoReg_id, ALUop_id, MemWrite_id, ALUSrc_id, RegWrite_id, NopSignal, ) # REGISTER FILE Data1_id = Signal(intbv(0, min=MIN, max=MAX)) Data2_id = Signal(intbv(0, min=MIN, max=MAX)) register_file_i = register_file( Clk, Rs_id, Rt_id, WrRegDest_wb, MuxMemO_wb, RegWrite_wb, Data1_id, Data2_id, depth=32 ) ############################## # ID/EX ############################## PcAdderOut_ex = Signal(intbv(0)[32:]) signals_1bit = [Signal(intbv(0)[1:]) for i in range(7)] RegDst_ex, ALUSrc_ex, MemtoReg_ex, RegWrite_ex, MemRead_ex, MemWrite_ex, Branch_ex = signals_1bit ALUop_ex = Signal(intbv(0)[2:]) Data1_ex = Signal(intbv(0, min=MIN, max=MAX)) Data2_ex = Signal(intbv(0, min=MIN, max=MAX)) Rs_ex = Signal(intbv(0)[5:]) # instruction 25:21 - to read_reg_1 Rt_ex = Signal(intbv(0)[5:]) # instruction 20:16 - to read_reg_2 and mux controlled by RegDst Rd_ex = Signal(intbv(0)[5:]) # instruction 15:11 - to the mux controlled by RegDst # Shamt_ex = Signal(intbv(0)[5:]) #instruction 10:6 - Func_ex = Signal(intbv(0)[6:]) # instruction 5:0 - to ALUCtrl Address32_ex = Signal(intbv(0, min=MIN, max=MAX)) latch_id_ex_ = latch_id_ex( Clk, Reset, PcAdderOut_id, Data1_id, Data2_id, Address32_id, Rd_id, Rt_id, Func_id, RegDst_id, ALUop_id, ALUSrc_id, # signals to EX pipeline stage Branch_id, MemRead_id, MemWrite_id, # signals to MEM pipeline stage RegWrite_id, MemtoReg_id, # signals to WB pipeline stage PcAdderOut_ex, Data1_ex, Data2_ex, Address32_ex, Rd_ex, Rt_ex, Func_ex, RegDst_ex, ALUop_ex, ALUSrc_ex, # signals to EX pipeline stage Branch_ex, MemRead_ex, MemWrite_ex, # signals to MEM pipeline stage RegWrite_ex, MemtoReg_ex, # signals to WB pipeline stage ) ############################## # EX ############################## BranchAdderO_ex = Signal(intbv(0, min=MIN, max=MAX)[32:]) Zero_ex = Signal(intbv(0)[1:]) AluResult_ex = Signal(intbv(0, min=MIN, max=MAX)) MuxAluDataSrc_ex = Signal(intbv(0, min=MIN, max=MAX)) WrRegDest_ex = Signal(intbv(0)[32:]) # muxer 2nd operand in ALU mux_alu_src = mux2(ALUSrc_ex, MuxAluDataSrc_ex, Data2_ex, Address32_ex) # Branch adder branch_adder_ = ALU(Signal(0b0010), PcAdderOut_ex, Address32_ex, BranchAdderO_ex, Signal(0)) # ALU Control AluControl = Signal(intbv("1111")[4:]) # control signal to alu alu_control_ = alu_control(ALUop_ex, Func_ex, AluControl) # ALU alu_ = ALU(AluControl, Data1_ex, MuxAluDataSrc_ex, AluResult_ex, Zero_ex) # Mux RegDestiny Control Write register between rt and rd. mux_wreg = mux2(RegDst_ex, WrRegDest_ex, Rt_ex, Rd_ex) ############################## # EX/MEM ############################## BranchAdderO_mem = Signal(intbv(0, min=MIN, max=MAX)) Zero_mem = Signal(intbv(0)[1:]) AluResult_mem = Signal(intbv(0, min=MIN, max=MAX)) Data2_mem = Signal(intbv(0, min=MIN, max=MAX)) WrRegDest_mem = Signal(intbv(0)[32:]) # control signals signals_1bit = [Signal(intbv(0)[1:]) for i in range(5)] MemtoReg_mem, RegWrite_mem, MemRead_mem, MemWrite_mem, Branch_mem = signals_1bit latch_ex_mem_ = latch_ex_mem( Clk, Reset, BranchAdderO_ex, AluResult_ex, Zero_ex, Data2_ex, WrRegDest_ex, Branch_ex, MemRead_ex, MemWrite_ex, # signals to MEM pipeline stage RegWrite_ex, MemtoReg_ex, # signals to WB pipeline stage BranchAdderO_mem, AluResult_mem, Zero_mem, Data2_mem, WrRegDest_mem, Branch_mem, MemRead_mem, MemWrite_mem, # signals to MEM pipeline stage RegWrite_mem, MemtoReg_mem, # signals to WB pipeline stage ) ############################## # MEM ############################## DataMemOut_mem = Signal(intbv(0, min=MIN, max=MAX)) # branch AND gate branch_and_gate = and_gate(Branch_mem, Zero_mem, PCSrc_mem) # data memory data_memory_ = data_memory(Clk, AluResult_mem, Data2_mem, DataMemOut_mem, MemRead_mem, MemWrite_mem) ############################## # EX/WB ############################## # RegWrite_wb, on feedback signals section MemtoReg_wb = Signal(intbv(0)[1:]) DataMemOut_wb = Signal(intbv(0, min=MIN, max=MAX)) AluResult_wb = Signal(intbv(0, min=MIN, max=MAX)) # WrRegDest_wb on feedback signals sections. latch_mem_wb_ = latch_mem_wb( Clk, Reset, DataMemOut_mem, AluResult_mem, WrRegDest_mem, RegWrite_mem, MemtoReg_mem, # signals to WB pipeline stage DataMemOut_wb, AluResult_wb, WrRegDest_wb, RegWrite_wb, MemtoReg_wb, # signals to WB pipeline stage ) ############################## # WB ############################## # mux2(sel, mux_out, chan1, chan2): mux_mem2reg_ = mux2(MemtoReg_wb, MuxMemO_wb, AluResult_wb, DataMemOut_wb) ############################## # Forwarding unit ############################## ############################## # hazard detection unit ############################## if DEBUG: @always(Clk.posedge) def debug_internals(): sep = "\n" + "=" * 34 + " time %s " + "=" * 34 print sep % now() # IF print "\n" + "." * 35 + " IF " + "." * 35 + "\n" print "PcAdderOut_if %i | BranchAdderO_mem %i | PCSrc_mem %i | NextIp %i | Ip %i" % ( PcAdderOut_if, BranchAdderO_mem, PCSrc_mem, NextIp, Ip, ) print "Instruction_if %s (%i)" % (bin(Instruction_if, 32), Instruction_if) if True: # now () > 2: # ID print "\n" + "." * 35 + " ID " + "." * 35 + "\n" print "PcAdderO_id %i | Instruction_id %s (%i) | Nop %i" % ( PcAdderOut_id, bin(Instruction_id, 32), Instruction_id, NopSignal, ) print "Op %s | Rs %i | Rt %i | Rd %i | Func %i | Addr16 %i | Addr32 %i" % ( bin(Opcode_id, 6), Rs_id, Rt_id, Rd_id, Func_id, Address16_id, Address32_id, ) print "Data1 %i | Data2 %i" % (Data1_id, Data2_id) print "-->CONTROL" print "RegDst %i ALUop %s ALUSrc %i | Branch %i MemR %i MemW %i | RegW %i Mem2Reg %i " % ( RegDst_id, bin(ALUop_id, 2), ALUSrc_id, Branch_id, MemRead_id, MemWrite_id, RegWrite_id, MemtoReg_id, ) if True: # if now () > 4: # EX print "\n" + "." * 35 + " EX " + "." * 35 + "\n" print "PcAdderO_ex %i | BranchAdderO_ex %i " % (PcAdderOut_ex, BranchAdderO_ex) print "Rs %i | Rt %i | Rd %i | Func %i | Addr32 %i" % (Rs_ex, Rt_ex, Rd_ex, Func_ex, Address32_ex) print "Data1_ex %i | Data2_ex %i" % (Data1_ex, Data2_ex) print "-->CONTROL" print "RegDst %i ALUop %s ALUSrc %i | Branch %i MemR %i MemW %i | RegW %i Mem2Reg %i " % ( RegDst_ex, bin(ALUop_ex, 2), ALUSrc_ex, Branch_ex, MemRead_ex, MemWrite_ex, RegWrite_ex, MemtoReg_ex, ) print "--> ALU" print "MuxAluDataSrc %i | AluCtrl %s | AluResult_ex %i | Zero_ex %i" % ( MuxAluDataSrc_ex, bin(AluControl, 4), AluResult_ex, Zero_ex, ) print "WrRegDest_ex %i" % WrRegDest_ex if True: # if now () > 6: # MEM print "\n" + "." * 35 + "MEM " + "." * 35 + "\n" print "BranchAdderO_mem %i " % (BranchAdderO_mem) print "-->CONTROL" print "Branch %i MemR %i MemW %i | RegW %i Mem2Reg %i " % ( Branch_mem, MemRead_mem, MemWrite_mem, RegWrite_mem, MemtoReg_mem, ) print "--> Branch" print "Branch_mem %i Zero %i | PCSrc_mem %i" % (Branch_mem, Zero_mem, PCSrc_mem) print "--> Data mem" print "AluResult_mem %i | Data2_mem %i | DataMemOut_mem %i | MemW %i MemR %i" % ( AluResult_mem, Data2_mem, DataMemOut_mem, MemWrite_mem, MemRead_mem, ) print "WrRegDest_mem %i" % WrRegDest_mem if True: # if now() > 8: # WB print "\n" + "." * 35 + "WB" + "." * 35 + "\n" print "CONTROL --> RegW %i Mem2Reg %i " % (RegWrite_mem, MemtoReg_mem) print "DataMemOut_wb %i | AluResult_wb %i | MuxMemO_wb %i " % (DataMemOut_wb, AluResult_wb, MuxMemO_wb) print "WrRegDest_wb %i | MuxMemO_wb %i" % (WrRegDest_wb, MuxMemO_wb) return instances()
def pipeline(clk_period=1, Reset=Signal(intbv(0)[1:]), Zero=Signal(intbv(0)[1:])): """ A DLX processor with 5 pipeline stages. ======================================= Stages ------ [IF] -> IF/ID -> [ID] -> ID/EX -> [EX] -> EX/MEM -> [MEM] -> MEM/WB __ ^ | |_______________________________________________________| Conventions: ------------ * Signals are in ``CamelCase`` * Instances are with ``under_score`` * The signals shared two or more stage are suffixed with the pipeline stage to which it belongs. For example: ``PcAdderO_if`` before IF/ID latch is the same signal than ``PcAdderO_id`` after it. """ ############################## # clock settings ############################## Clk = Signal(intbv(0)[1:]) # internal clock ClkPc = Signal(intbv(0)[1:]) # frec should be almost 1/4 clk internal clk_driver = clock_driver(Clk, clk_period) clk_driver_pc = clock_driver(ClkPc, clk_period * 4) #################### #feedback Signals ###################### # signals from and advanced stage which feeds a previous component BranchAdderO_mem = Signal(intbv(0, min=MIN, max=MAX)[32:]) PCSrc_mem = Signal( intbv(0)[1:] ) # control of mux for program_counter on IF stage - (branch or inmediante_next) WrRegDest_wb = Signal(intbv( 0)[32:]) # register pointer where MuxMemO_wb data will be stored. MuxMemO_wb = Signal( intbv(0, min=MIN, max=MAX) ) # data output from WB mux connected as Write Data input on Register File (ID stage) RegWrite_wb = Signal(intbv(0)[1:]) ############################## # IF ############################## #instruction memory Ip = Signal(intbv(0)[32:]) # connect PC with intruction_memory Instruction_if = Signal(intbv(0)[32:]) # 32 bits instruction line. im = instruction_memory(Ip, Instruction_if) #PC NextIp = Signal(intbv(0)[32:]) # output of mux_branch - input of pc pc = program_counter(Clk, NextIp, Ip) #pc_adder INCREMENT = 1 # it's 4 in the book, but my memory it's organized in 32bits words, not bytes PcAdderOut_if = Signal(intbv( 0)[32:]) # output of pc_adder - input0 branch_adder and mux_branch pc_adder = ALU(Signal(0b0010), Ip, Signal(INCREMENT), PcAdderOut_if, Signal(0)) # hardwire an ALU to works as an adder #mux controlling next ip branches. mux_pc_source = mux2(PCSrc_mem, NextIp, PcAdderOut_if, BranchAdderO_mem) ############################## # IF/ID ############################## PcAdderOut_id = Signal(intbv(0)[32:]) Instruction_id = Signal(intbv(0)[32:]) latch_if_id_ = latch_if_id(Clk, Reset, Instruction_if, PcAdderOut_if, Instruction_id, PcAdderOut_id) ############################## # ID ############################## #DECODER Opcode_id = Signal(intbv(0)[6:]) # instruction 31:26 - to Control Rs_id = Signal(intbv(0)[5:]) # instruction 25:21 - to read_reg_1 Rt_id = Signal( intbv(0)[5:] ) # instruction 20:16 - to read_reg_2 and mux controlled by RegDst Rd_id = Signal( intbv(0)[5:]) # instruction 15:11 - to the mux controlled by RegDst Shamt_id = Signal(intbv(0)[5:]) # instruction 10:6 - Func_id = Signal(intbv(0)[6:]) # instruction 5:0 - to ALUCtrl Address16_id = Signal(intbv(0, min=-(2**15), max=2**15 - 1)) # instruction 15:0 - to Sign Extend NopSignal = Signal(intbv(0)[1:]) instruction_decoder_ = instruction_dec(Instruction_id, Opcode_id, Rs_id, Rt_id, Rd_id, Shamt_id, Func_id, Address16_id, NopSignal) #sign extend Address32_id = Signal(intbv(0, min=MIN, max=MAX)) sign_extend_ = sign_extend(Address16_id, Address32_id) #CONTROL signals_1bit = [Signal(intbv(0)[1:]) for i in range(7)] RegDst_id, ALUSrc_id, MemtoReg_id, RegWrite_id, MemRead_id, MemWrite_id, Branch_id = signals_1bit ALUop_id = Signal(intbv(0)[2:]) control_ = control(Opcode_id, RegDst_id, Branch_id, MemRead_id, MemtoReg_id, ALUop_id, MemWrite_id, ALUSrc_id, RegWrite_id, NopSignal) #REGISTER FILE Data1_id = Signal(intbv(0, min=MIN, max=MAX)) Data2_id = Signal(intbv(0, min=MIN, max=MAX)) register_file_i = register_file(Clk, Rs_id, Rt_id, WrRegDest_wb, MuxMemO_wb, RegWrite_wb, Data1_id, Data2_id, depth=32) ############################## # ID/EX ############################## PcAdderOut_ex = Signal(intbv(0)[32:]) signals_1bit = [Signal(intbv(0)[1:]) for i in range(7)] RegDst_ex, ALUSrc_ex, MemtoReg_ex, RegWrite_ex, MemRead_ex, MemWrite_ex, Branch_ex = signals_1bit ALUop_ex = Signal(intbv(0)[2:]) Data1_ex = Signal(intbv(0, min=MIN, max=MAX)) Data2_ex = Signal(intbv(0, min=MIN, max=MAX)) Rs_ex = Signal(intbv(0)[5:]) # instruction 25:21 - to read_reg_1 Rt_ex = Signal( intbv(0)[5:] ) # instruction 20:16 - to read_reg_2 and mux controlled by RegDst Rd_ex = Signal( intbv(0)[5:]) # instruction 15:11 - to the mux controlled by RegDst #Shamt_ex = Signal(intbv(0)[5:]) #instruction 10:6 - Func_ex = Signal(intbv(0)[6:]) # instruction 5:0 - to ALUCtrl Address32_ex = Signal(intbv(0, min=MIN, max=MAX)) latch_id_ex_ = latch_id_ex( Clk, Reset, PcAdderOut_id, Data1_id, Data2_id, Address32_id, Rd_id, Rt_id, Func_id, RegDst_id, ALUop_id, ALUSrc_id, # signals to EX pipeline stage Branch_id, MemRead_id, MemWrite_id, # signals to MEM pipeline stage RegWrite_id, MemtoReg_id, # signals to WB pipeline stage PcAdderOut_ex, Data1_ex, Data2_ex, Address32_ex, Rd_ex, Rt_ex, Func_ex, RegDst_ex, ALUop_ex, ALUSrc_ex, # signals to EX pipeline stage Branch_ex, MemRead_ex, MemWrite_ex, # signals to MEM pipeline stage RegWrite_ex, MemtoReg_ex # signals to WB pipeline stage ) ############################## # EX ############################## BranchAdderO_ex = Signal(intbv(0, min=MIN, max=MAX)[32:]) Zero_ex = Signal(intbv(0)[1:]) AluResult_ex = Signal(intbv(0, min=MIN, max=MAX)) MuxAluDataSrc_ex = Signal(intbv(0, min=MIN, max=MAX)) WrRegDest_ex = Signal(intbv(0)[32:]) #muxer 2nd operand in ALU mux_alu_src = mux2(ALUSrc_ex, MuxAluDataSrc_ex, Data2_ex, Address32_ex) #Branch adder branch_adder_ = ALU(Signal(0b0010), PcAdderOut_ex, Address32_ex, BranchAdderO_ex, Signal(0)) #ALU Control AluControl = Signal(intbv('1111')[4:]) # control signal to alu alu_control_ = alu_control(ALUop_ex, Func_ex, AluControl) #ALU alu_ = ALU(AluControl, Data1_ex, MuxAluDataSrc_ex, AluResult_ex, Zero_ex) #Mux RegDestiny Control Write register between rt and rd. mux_wreg = mux2(RegDst_ex, WrRegDest_ex, Rt_ex, Rd_ex) ############################## # EX/MEM ############################## BranchAdderO_mem = Signal(intbv(0, min=MIN, max=MAX)) Zero_mem = Signal(intbv(0)[1:]) AluResult_mem = Signal(intbv(0, min=MIN, max=MAX)) Data2_mem = Signal(intbv(0, min=MIN, max=MAX)) WrRegDest_mem = Signal(intbv(0)[32:]) #control signals signals_1bit = [Signal(intbv(0)[1:]) for i in range(5)] MemtoReg_mem, RegWrite_mem, MemRead_mem, MemWrite_mem, Branch_mem = signals_1bit latch_ex_mem_ = latch_ex_mem( Clk, Reset, BranchAdderO_ex, AluResult_ex, Zero_ex, Data2_ex, WrRegDest_ex, Branch_ex, MemRead_ex, MemWrite_ex, # signals to MEM pipeline stage RegWrite_ex, MemtoReg_ex, # signals to WB pipeline stage BranchAdderO_mem, AluResult_mem, Zero_mem, Data2_mem, WrRegDest_mem, Branch_mem, MemRead_mem, MemWrite_mem, # signals to MEM pipeline stage RegWrite_mem, MemtoReg_mem, # signals to WB pipeline stage ) ############################## # MEM ############################## DataMemOut_mem = Signal(intbv(0, min=MIN, max=MAX)) #branch AND gate branch_and_gate = and_gate(Branch_mem, Zero_mem, PCSrc_mem) #data memory data_memory_ = data_memory(Clk, AluResult_mem, Data2_mem, DataMemOut_mem, MemRead_mem, MemWrite_mem) ############################## # EX/WB ############################## #RegWrite_wb, on feedback signals section MemtoReg_wb = Signal(intbv(0)[1:]) DataMemOut_wb = Signal(intbv(0, min=MIN, max=MAX)) AluResult_wb = Signal(intbv(0, min=MIN, max=MAX)) #WrRegDest_wb on feedback signals sections. latch_mem_wb_ = latch_mem_wb( Clk, Reset, DataMemOut_mem, AluResult_mem, WrRegDest_mem, RegWrite_mem, MemtoReg_mem, # signals to WB pipeline stage DataMemOut_wb, AluResult_wb, WrRegDest_wb, RegWrite_wb, MemtoReg_wb, # signals to WB pipeline stage ) ############################## # WB ############################## #mux2(sel, mux_out, chan1, chan2): mux_mem2reg_ = mux2(MemtoReg_wb, MuxMemO_wb, AluResult_wb, DataMemOut_wb) ############################## # Forwarding unit ############################## ############################## # hazard detection unit ############################## if DEBUG: @always(Clk.posedge) def debug_internals(): sep = "\n" + "=" * 34 + " time %s " + "=" * 34 print sep % now() #IF print "\n" + "." * 35 + " IF " + "." * 35 + "\n" print "PcAdderOut_if %i | BranchAdderO_mem %i | PCSrc_mem %i | NextIp %i | Ip %i" % ( PcAdderOut_if, BranchAdderO_mem, PCSrc_mem, NextIp, Ip) print 'Instruction_if %s (%i)' % (bin(Instruction_if, 32), Instruction_if) if True: # now () > 2: #ID print "\n" + "." * 35 + " ID " + "." * 35 + "\n" print "PcAdderO_id %i | Instruction_id %s (%i) | Nop %i" % ( PcAdderOut_id, bin(Instruction_id, 32), Instruction_id, NopSignal) print 'Op %s | Rs %i | Rt %i | Rd %i | Func %i | Addr16 %i | Addr32 %i' % \ (bin(Opcode_id, 6), Rs_id, Rt_id, Rd_id, Func_id, Address16_id, Address32_id) print 'Data1 %i | Data2 %i' % (Data1_id, Data2_id) print '-->CONTROL' print 'RegDst %i ALUop %s ALUSrc %i | Branch %i MemR %i MemW %i | RegW %i Mem2Reg %i ' % \ (RegDst_id, bin(ALUop_id, 2), ALUSrc_id, Branch_id, MemRead_id, MemWrite_id, RegWrite_id, MemtoReg_id) if True: # if now () > 4: #EX print "\n" + "." * 35 + " EX " + "." * 35 + "\n" print "PcAdderO_ex %i | BranchAdderO_ex %i " % ( PcAdderOut_ex, BranchAdderO_ex) print "Rs %i | Rt %i | Rd %i | Func %i | Addr32 %i" % ( Rs_ex, Rt_ex, Rd_ex, Func_ex, Address32_ex) print 'Data1_ex %i | Data2_ex %i' % (Data1_ex, Data2_ex) print '-->CONTROL' print 'RegDst %i ALUop %s ALUSrc %i | Branch %i MemR %i MemW %i | RegW %i Mem2Reg %i ' % \ (RegDst_ex, bin(ALUop_ex, 2), ALUSrc_ex, Branch_ex, MemRead_ex, MemWrite_ex, RegWrite_ex, MemtoReg_ex) print '--> ALU' print 'MuxAluDataSrc %i | AluCtrl %s | AluResult_ex %i | Zero_ex %i' % ( MuxAluDataSrc_ex, bin(AluControl, 4), AluResult_ex, Zero_ex) print 'WrRegDest_ex %i' % WrRegDest_ex if True: # if now () > 6: #MEM print "\n" + "." * 35 + "MEM " + "." * 35 + "\n" print "BranchAdderO_mem %i " % (BranchAdderO_mem) print '-->CONTROL' print 'Branch %i MemR %i MemW %i | RegW %i Mem2Reg %i ' % \ (Branch_mem, MemRead_mem, MemWrite_mem, RegWrite_mem, MemtoReg_mem) print '--> Branch' print 'Branch_mem %i Zero %i | PCSrc_mem %i' % ( Branch_mem, Zero_mem, PCSrc_mem) print '--> Data mem' print 'AluResult_mem %i | Data2_mem %i | DataMemOut_mem %i | MemW %i MemR %i' \ % (AluResult_mem, Data2_mem, DataMemOut_mem, MemWrite_mem, MemRead_mem) print 'WrRegDest_mem %i' % WrRegDest_mem if True: # if now() > 8: #WB print "\n" + "." * 35 + "WB" + "." * 35 + "\n" print 'CONTROL --> RegW %i Mem2Reg %i ' % (RegWrite_mem, MemtoReg_mem) print 'DataMemOut_wb %i | AluResult_wb %i | MuxMemO_wb %i ' % ( DataMemOut_wb, AluResult_wb, MuxMemO_wb) print 'WrRegDest_wb %i | MuxMemO_wb %i' % (WrRegDest_wb, MuxMemO_wb) return instances()
def datapath(clk_period=1, reset=Signal(intbv(0)[1:]), zero=Signal(intbv(0)[1:])): ############################## # # clock settings # ############################## clk = Signal(intbv(0)[1:]) # internal clock clk_pc = Signal(intbv(0)[1:]) # frec should be almost 1/4 clk internal clk_driver = clock_driver(clk, clk_period) clk_driver_pc = clock_driver(clk_pc, clk_period * 4) ############################## # # internal signals # ############################## #program counter and branch signals ip = Signal(intbv(0)[32:]) # connect PC with intruction_memory pc_adder_out = Signal(intbv(0)[32:]) # output of pc_adder - input0 branch_adder and mux_branch next_ip = Signal(intbv(0)[32:]) # output of mux_branch - input of pc branch_adder_out = Signal(intbv(0)[32:]) branchZ = Signal(intbv(0)[1:]) # control of mux_branch instruction = Signal(intbv(0)[32:]) # 32 bits instruction line. #control signals signals_1bit = [Signal(intbv(0)[1:]) for i in range(7)] RegDst, ALUSrc, MemtoReg, RegWrite, MemRead, MemWrite, Branch = signals_1bit #ALUop connect Control with ALUcontrol ALUop = Signal(intbv(0)[2:]) #intruction memory output connectors opcode = Signal(intbv(0)[6:]) # instruction 31:26 - to Control rs = Signal(intbv(0)[5:]) # instruction 25:21 - to read_reg_1 rt = Signal(intbv(0)[5:]) # instruction 20:16 - to read_reg_2 and mux controlled by RegDst rd = Signal(intbv(0)[5:]) # instruction 15:11 - to the mux controlled by RegDst shamt = Signal(intbv(0)[5:]) # instruction 10:6 - func = Signal(intbv(0)[6:]) # instruction 5:0 - to ALUCtrl address = Signal(intbv(0, min=-(2 ** 15), max=2 ** 15 - 1)) # instruction 15:0 - to Sign Extend wr_reg_in = Signal(intbv(0)[5:]) # output of mux_wreg (it's rt or rd depends on RegDst) address32 = Signal(intbv(0, min=-(2 ** 31), max=2 ** 31 - 1)) # output of signextend #register file data vectors (input and outputs) data_in, data1, data2 = [Signal(intbv(0, min=-(2 ** 31), max=2 ** 31 - 1)) for i in range(3)] mux_alu_out = Signal(intbv(0, min=-(2 ** 31), max=2 ** 31 - 1)) # output of mux_alu_src #(data2 or address32 depends on ALUSrc) #ALU signals alu_control_out = Signal(intbv('1111')[4:]) alu_out = Signal(intbv(0, min=-(2 ** 31), max=2 ** 31 - 1)) zero = Signal(intbv(0)[1:]) #data memory signal ram_out = Signal(intbv(0, min=-(2 ** 31), max=2 ** 31 - 1)) mux_ram_out = Signal(intbv(0, min=-(2 ** 31), max=2 ** 31 - 1)) ############################## # # component instances # ############################## #program counter pc = program_counter(clk_pc, next_ip, ip) increment = 1 # it's 4 in the book, but my memory it's organized in 32bits words, not bytes pc_adder = ALU(Signal(0b0010), ip, Signal(increment), pc_adder_out, Signal(0)) # hardwire an ALU to works as an adder branch_adder = ALU(Signal(0b0010), pc_adder_out, address32, branch_adder_out, Signal(0)) branch_and_gate = and_gate(Branch, zero, branchZ) mux_branch = mux2(branchZ, next_ip, pc_adder_out, branch_adder_out) im = instruction_memory(ip, instruction) id = instruction_dec(instruction, opcode, rs, rt, rd, shamt, func, address) control_i = control(opcode, RegDst, Branch, MemRead, MemtoReg, ALUop, MemWrite, ALUSrc, RegWrite) mux_wreg = mux2(RegDst, wr_reg_in, rt, rd) register_file_i = register_file(clk, rs, rt, wr_reg_in, mux_ram_out, RegWrite, data1, data2, depth=32) sign_extend_i = sign_extend(address, address32) alu_control_i = alu_control(ALUop, func, alu_control_out) mux_alu_src = mux2(ALUSrc, mux_alu_out, data2, address32) alu_i = ALU(alu_control_out, data1, mux_alu_out, alu_out, zero) data_memory_i = data_memory(clk, alu_out, data2, ram_out, MemRead, MemWrite) mux_mem2reg = mux2(MemtoReg, mux_ram_out, alu_out, ram_out) if DEBUG: @always(clk.posedge) def debug_internals(): print "-" * 78 print "time %s | clk %i | clk_pc %i | ip %i " % (now(), clk, clk_pc, ip) print 'pc_add_o %i | branch_add_o %i | BranchZ %i | next_ip %i' % (pc_adder_out, branch_adder_out, branchZ, next_ip) print 'instruction', bin(instruction, 32) print 'opcode %s | rs %i | rt %i | rd %i | shamt %i | func %i | address %i' % \ (bin(opcode, 6), rs, rt, rd, shamt, func, address) print 'wr_reg_in %i | dat1 %i | dat2 %i | muxALUo %i ' % \ (wr_reg_in, data1, data2, mux_alu_out) print 'RegDst %i | ALUSrc %i | Mem2Reg %i | RegW %i | MemR %i | MemW %i | Branch %i | ALUop %s' % (RegDst, ALUSrc, MemtoReg, RegWrite, MemRead, MemWrite, Branch, bin(ALUop, 2)) print 'func: %s | aluop: %s | alu_c_out: %s' % (bin(func, 5), bin(ALUop, 2), bin(alu_control_out, 4)) print 'ALU_out: %i | Zero: %i' % (alu_out, zero) print 'ram_out %i | mux_ram_out %i ' % (ram_out, mux_ram_out) return instances()
def dlx(clk_period=1, Reset=Signal(intbv(0)[1:]), Zero=Signal(intbv(0)[1:])): """ A DLX processor with 5 pipeline stages. ======================================= Stages ------ +------------------+ | +------- Hazard | | +-> Detect <-----+ | | | | | | | | | | v v | v | [IF] -> IF/ID -> [ID] -> ID/EX -> [EX] -> EX/MEM -> [MEM] -> MEM/WB __ ^ | ^ | | | | | | <_____________| | | | +> FORW <___________________________| | | | |_______________________________________________________| Conventions: ------------ * Signals are in ``CamelCase`` * Instances are with ``under_score_`` (with a last ``_``) * The signals shared two or more stage are suffixed with the pipeline stage to which it belongs. For example: ``PcAdderO_if`` before IF/ID latch is the same signal than ``PcAdderO_id`` after it. """ ############################## # clock settings ############################## Clk = Signal(intbv(0)[1:]) #internal clock ClkPc = Signal(intbv(0)[1:]) #frec should be almost 1/4 clk internal clk_driver = clock_driver(Clk, clk_period) clk_driver_pc = clock_driver(ClkPc, clk_period * 4) #################### #feedback Signals ###################### # signals from and advanced stage which feeds a previous component BranchAdderO_mem = Signal(intbv(0, min=MIN, max=MAX)[32:]) PCSrc_mem = Signal(intbv(0)[1:]) #control of mux for program_counter on IF stage - (branch or inmediante_next) FlushOnBranch = PCSrc_mem # 1 when beq condition is asserted => flush IF / ID / EX to discard # instructions chargued wrongly WrRegDest_wb = Signal(intbv(0)[32:]) #register pointer where MuxMemO_wb data will be stored. MuxMemO_wb = Signal(intbv(0, min=MIN, max=MAX)) #data output from WB mux connected as Write Data input on Register File (ID stage) RegWrite_wb = Signal(intbv(0)[1:]) ForwardA, ForwardB = [ Signal(intbv(0)[2:]) for i in range(2) ] #Signals Generated in Forwarding units to control ALU's input muxers AluResult_mem = Signal(intbv(0, min=MIN, max=MAX)) Stall = Signal(intbv(0)[1:]) #when asserted the pipeline is stalled. It 'freezes' PC count #and put all Control Signals to 0's ############################## # IF ############################## #instruction memory Ip = Signal(intbv(0)[32:] ) #connect PC with intruction_memory Instruction_if = Signal(intbv(0)[32:]) #32 bits instruction line. im = instruction_memory (Ip, Instruction_if) #PC NextIp = Signal(intbv(0)[32:] ) #output of mux_branch - input of pc pc = program_counter(Clk, NextIp, Ip, Stall) #pc_adder INCREMENT = 1 #it's 4 in the book, but my instruction memory is organized in 32bits words, not in bytes PcAdderOut_if = Signal(intbv(0)[32:] ) #output of pc_adder - input0 branch_adder and mux_branch pc_adder = ALU(Signal(0b0010), Ip, Signal(INCREMENT), PcAdderOut_if, Signal(0)) #hardwiring an ALU to works as an adder #mux controlling next ip branches. mux_pc_source = mux2(PCSrc_mem, NextIp, PcAdderOut_if, BranchAdderO_mem) ############################## # IF/ID ############################## PcAdderOut_id = Signal(intbv(0)[32:]) Instruction_id = Signal(intbv(0)[32:]) latch_if_id_ = latch_if_id(Clk, FlushOnBranch, Instruction_if, PcAdderOut_if, Instruction_id, PcAdderOut_id, Stall) ############################## # ID ############################## #DECODER Opcode_id = Signal(intbv(0)[6:]) #instruction 31:26 - to Control Rs_id = Signal(intbv(0)[5:]) #instruction 25:21 - to read_reg_1 Rt_id = Signal(intbv(0)[5:]) #instruction 20:16 - to read_reg_2 and mux controlled by RegDst Rd_id = Signal(intbv(0)[5:]) #instruction 15:11 - to the mux controlled by RegDst Shamt_id = Signal(intbv(0)[5:]) #instruction 10:6 - Func_id = Signal(intbv(0)[6:]) #instruction 5:0 - to ALUCtrl Address16_id = Signal(intbv(0, min=-(2**15), max=2**15 - 1)) #instruction 15:0 - to Sign Extend NopSignal = Signal(intbv(0)[1:]) instruction_decoder_ = instruction_dec(Instruction_id, Opcode_id, Rs_id, Rt_id, Rd_id, Shamt_id, Func_id, Address16_id, NopSignal) #sign extend Address32_id = Signal(intbv(0, min=MIN, max=MAX)) sign_extend_ = sign_extend(Address16_id, Address32_id) #CONTROL signals_1bit = [Signal(intbv(0)[1:]) for i in range(7)] RegDst_id, ALUSrc_id, MemtoReg_id, RegWrite_id, MemRead_id, MemWrite_id, Branch_id = signals_1bit ALUop_id = Signal(intbv(0)[2:]) control_ = control(Opcode_id, RegDst_id, Branch_id, MemRead_id, MemtoReg_id, ALUop_id, MemWrite_id, ALUSrc_id, RegWrite_id, NopSignal, Stall) #REGISTER FILE Data1_id = Signal(intbv(0, min=MIN, max=MAX)) Data2_id = Signal(intbv(0, min=MIN, max=MAX)) register_file_i = register_file(Clk, Rs_id, Rt_id, WrRegDest_wb, MuxMemO_wb, RegWrite_wb, Data1_id, Data2_id, depth=32) ############################## # ID/EX ############################## PcAdderOut_ex = Signal(intbv(0)[32:]) signals_1bit = [Signal(intbv(0)[1:]) for i in range(7)] RegDst_ex, ALUSrc_ex, MemtoReg_ex, RegWrite_ex, MemRead_ex, MemWrite_ex, Branch_ex = signals_1bit ALUop_ex = Signal(intbv(0)[2:]) Data1_ex = Signal(intbv(0, min=MIN, max=MAX)) Data2_ex = Signal(intbv(0, min=MIN, max=MAX)) Rs_ex = Signal(intbv(0)[5:]) #instruction 25:21 - to read_reg_1 Rt_ex = Signal(intbv(0)[5:]) #instruction 20:16 - to read_reg_2 and mux controlled by RegDst Rd_ex = Signal(intbv(0)[5:]) #instruction 15:11 - to the mux controlled by RegDst #Shamt_ex = Signal(intbv(0)[5:]) #instruction 10:6 - Func_ex = Signal(intbv(0)[6:]) #instruction 5:0 - to ALUCtrl Address32_ex = Signal(intbv(0, min=MIN, max=MAX)) latch_id_ex_ = latch_id_ex(Clk, FlushOnBranch, PcAdderOut_id, Data1_id, Data2_id, Address32_id, Rs_id, Rt_id, Rd_id, Func_id, RegDst_id, ALUop_id, ALUSrc_id, #signals to EX pipeline stage Branch_id, MemRead_id, MemWrite_id, #signals to MEM pipeline stage RegWrite_id, MemtoReg_id, #signals to WB pipeline stage PcAdderOut_ex, Data1_ex, Data2_ex, Address32_ex, Rs_ex, Rt_ex, Rd_ex, Func_ex, RegDst_ex, ALUop_ex, ALUSrc_ex, #signals to EX pipeline stage Branch_ex, MemRead_ex, MemWrite_ex, #signals to MEM pipeline stage RegWrite_ex, MemtoReg_ex #signals to WB pipeline stage ) ############################## # EX ############################## BranchAdderO_ex = Signal(intbv(0, min=MIN, max=MAX)[32:]) Zero_ex = Signal(intbv(0)[1:]) AluResult_ex = Signal(intbv(0, min=MIN, max=MAX)) ForwMux1Out, ForwMux2Out = [ Signal(intbv(0, min=MIN, max=MAX)) for i in range(2) ] #Output of forw_mux1 and forw_mux2 MuxAluDataSrc_ex = Signal(intbv(0, min=MIN, max=MAX)) WrRegDest_ex = Signal(intbv(0)[32:]) forw_mux1_ = mux4(ForwardA, ForwMux1Out, Data1_ex, MuxMemO_wb, AluResult_mem) forw_mux2_ = mux4(ForwardB, ForwMux2Out, Data2_ex, MuxMemO_wb, AluResult_mem) #2nd muxer of 2nd operand in ALU mux_alu_src = mux2(ALUSrc_ex, MuxAluDataSrc_ex, ForwMux2Out, Address32_ex) #Branch adder branch_adder_ = ALU(Signal(0b0010), PcAdderOut_ex, Address32_ex, BranchAdderO_ex, Signal(0)) #ALU Control AluControl = Signal(intbv('1111')[4:]) #control signal to alu alu_control_ = alu_control(ALUop_ex, Func_ex, AluControl) #ALU alu_ = ALU(AluControl, ForwMux1Out, MuxAluDataSrc_ex, AluResult_ex, Zero_ex) #Mux RegDestiny Control Write register between rt and rd. mux_wreg = mux2(RegDst_ex, WrRegDest_ex, Rt_ex, Rd_ex) ############################## # EX/MEM ############################## BranchAdderO_mem = Signal(intbv(0, min=MIN, max=MAX)) Zero_mem = Signal(intbv(0)[1:]) Data2_mem = Signal(intbv(0, min=MIN, max=MAX)) WrRegDest_mem = Signal(intbv(0)[32:]) #control signals signals_1bit = [Signal(intbv(0)[1:]) for i in range(5)] MemtoReg_mem, RegWrite_mem, MemRead_mem, MemWrite_mem, Branch_mem = signals_1bit latch_ex_mem_ = latch_ex_mem(Clk, Reset, BranchAdderO_ex, AluResult_ex, Zero_ex, Data2_ex, WrRegDest_ex, Branch_ex, MemRead_ex, MemWrite_ex, #signals to MEM pipeline stage RegWrite_ex, MemtoReg_ex, #signals to WB pipeline stage BranchAdderO_mem, AluResult_mem, Zero_mem, Data2_mem, WrRegDest_mem, Branch_mem, MemRead_mem, MemWrite_mem, #signals to MEM pipeline stage RegWrite_mem, MemtoReg_mem, #signals to WB pipeline stage ) ############################## # MEM ############################## DataMemOut_mem = Signal(intbv(0, min=MIN, max=MAX)) #branch AND gate branch_and_gate = and_gate(Branch_mem, Zero_mem, PCSrc_mem) #data memory data_memory_ = data_memory(Clk, AluResult_mem, Data2_mem, DataMemOut_mem, MemRead_mem, MemWrite_mem) ############################## # EX/WB ############################## #RegWrite_wb, on feedback signals section MemtoReg_wb = Signal(intbv(0)[1:]) DataMemOut_wb = Signal(intbv(0, min=MIN, max=MAX)) AluResult_wb = Signal(intbv(0, min=MIN, max=MAX)) #WrRegDest_wb on feedback signals sections. latch_mem_wb_ = latch_mem_wb(Clk, Reset, DataMemOut_mem, AluResult_mem, WrRegDest_mem, RegWrite_mem, MemtoReg_mem, #signals to WB pipeline stage DataMemOut_wb, AluResult_wb, WrRegDest_wb, RegWrite_wb, MemtoReg_wb, #signals to WB pipeline stage ) ############################## # WB ############################## #mux2(sel, mux_out, chan1, chan2): mux_mem2reg_ = mux2(MemtoReg_wb, MuxMemO_wb, AluResult_wb, DataMemOut_wb) ############################## # Forwarding unit ############################## forwarding_ = forwarding(RegWrite_mem, WrRegDest_mem, Rs_ex, Rt_ex, #inputs of EX hazards RegWrite_wb, WrRegDest_wb, #left inputs of MEM hazards ForwardA, ForwardB ) ############################## # hazard detection unit ############################## hazard_detector_ = hazard_detector(MemRead_ex, Rt_ex, Rs_id, Rt_id, Stall) if DEBUG: @always(Clk.posedge) def debug_internals(): sep = "\n" + "=" * 31 + " cycle %i (%ins)" + "=" * 31 print sep % ( int(now()/2.0 + 0.5), now() ) #IF print "\n" + "." * 35 + " IF " + "." * 35 + "\n" print "PcAdderOut_if %i | BranchAdderO_mem %i | PCSrc_mem %i | NextIp %i | Ip %i" % (PcAdderOut_if, BranchAdderO_mem, PCSrc_mem, NextIp, Ip) print 'Instruction_if %s (%i)' % (bin(Instruction_if, 32), Instruction_if) if True: # now () > 2: #ID print "\n" + "." * 35 + " ID " + "." * 35 + "\n" print "PcAdderO_id %i | Instruction_id %s (%i) | Nop %i" % (PcAdderOut_id, bin(Instruction_id, 32), Instruction_id, NopSignal ) print 'Op %s | Rs %i | Rt %i | Rd %i | Func %i | Addr16 %i | Addr32 %i' % \ (bin(Opcode_id, 6), Rs_id, Rt_id, Rd_id, Func_id, Address16_id, Address32_id ) print 'Data1 %i | Data2 %i' % (Data1_id, Data2_id) print '-->CONTROL' print 'RegDst %i ALUop %s ALUSrc %i | Branch %i MemR %i MemW %i | RegW %i Mem2Reg %i ' % \ ( RegDst_id , bin(ALUop_id, 2), ALUSrc_id, Branch_id, MemRead_id, MemWrite_id, RegWrite_id, MemtoReg_id) print 'Stall --> %i' % Stall if True: #if now () > 4: #EX print "\n" + "." * 35 + " EX " + "." * 35 + "\n" print "PcAdderO_ex %i | BranchAdderO_ex %i " % (PcAdderOut_ex, BranchAdderO_ex) print "Rs %i | Rt %i | Rd %i | Func %i | Addr32 %i" % (Rs_ex, Rt_ex, Rd_ex, Func_ex, Address32_ex ) print 'Data1_ex %i | Data2_ex %i' % (Data1_ex, Data2_ex) print 'ForwardA %i | ForwardB %i' % (ForwardA, ForwardB) print 'ForwMux1Out %i | ForwMux2Out %i' % (ForwMux1Out, ForwMux2Out) print '-->CONTROL' print 'RegDst %i ALUop %s ALUSrc %i | Branch %i MemR %i MemW %i | RegW %i Mem2Reg %i ' % \ ( RegDst_ex , bin(ALUop_ex, 2), ALUSrc_ex, Branch_ex, MemRead_ex, MemWrite_ex, RegWrite_ex, MemtoReg_ex) print '--> ALU' print 'MuxAluDataSrc %i | AluCtrl %s | AluResult_ex %i | Zero_ex %i' % (MuxAluDataSrc_ex, bin(AluControl, 4), AluResult_ex, Zero_ex) print 'WrRegDest_ex %i' % WrRegDest_ex if True: #if now () > 6: #MEM print "\n" + "." * 35 + "MEM " + "." * 35 + "\n" print "BranchAdderO_mem %i " % (BranchAdderO_mem) print '-->CONTROL' print 'Branch %i MemR %i MemW %i | RegW %i Mem2Reg %i ' % \ ( Branch_mem, MemRead_mem, MemWrite_mem, RegWrite_mem, MemtoReg_mem) print '--> Branch' print 'Branch_mem %i Zero %i | PCSrc_mem %i' % (Branch_mem, Zero_mem, PCSrc_mem) print '--> Data mem' print 'AluResult_mem %i | Data2_mem %i | DataMemOut_mem %i | MemW %i MemR %i' \ % (AluResult_mem, Data2_mem, DataMemOut_mem, MemWrite_mem, MemRead_mem) print 'WrRegDest_mem %i' % WrRegDest_mem if True: #if now() > 8: #WB print "\n" + "." * 35 + "WB" + "." * 35 + "\n" print 'CONTROL --> RegW %i Mem2Reg %i ' % ( RegWrite_mem, MemtoReg_mem) print 'DataMemOut_wb %i | AluResult_wb %i | MuxMemO_wb %i ' % (DataMemOut_wb, AluResult_wb, MuxMemO_wb) print 'WrRegDest_wb %i | MuxMemO_wb %i' % (WrRegDest_wb, MuxMemO_wb) return instances()
def datapath(clk_period=1, reset=Signal(intbv(0)[1:]), zero=Signal(intbv(0)[1:])): ############################## # # clock settings # ############################## clk = Signal(intbv(0)[1:]) # internal clock clk_pc = Signal(intbv(0)[1:]) # frec should be almost 1/4 clk internal clk_driver = clock_driver(clk, clk_period) clk_driver_pc = clock_driver(clk_pc, clk_period * 4) ############################## # # internal signals # ############################## #program counter and branch signals ip = Signal(intbv(0)[32:]) # connect PC with intruction_memory pc_adder_out = Signal(intbv( 0)[32:]) # output of pc_adder - input0 branch_adder and mux_branch next_ip = Signal(intbv(0)[32:]) # output of mux_branch - input of pc branch_adder_out = Signal(intbv(0)[32:]) branchZ = Signal(intbv(0)[1:]) # control of mux_branch instruction = Signal(intbv(0)[32:]) # 32 bits instruction line. #control signals signals_1bit = [Signal(intbv(0)[1:]) for i in range(7)] RegDst, ALUSrc, MemtoReg, RegWrite, MemRead, MemWrite, Branch = signals_1bit #ALUop connect Control with ALUcontrol ALUop = Signal(intbv(0)[2:]) #intruction memory output connectors opcode = Signal(intbv(0)[6:]) # instruction 31:26 - to Control rs = Signal(intbv(0)[5:]) # instruction 25:21 - to read_reg_1 rt = Signal( intbv(0)[5:] ) # instruction 20:16 - to read_reg_2 and mux controlled by RegDst rd = Signal( intbv(0)[5:]) # instruction 15:11 - to the mux controlled by RegDst shamt = Signal(intbv(0)[5:]) # instruction 10:6 - func = Signal(intbv(0)[6:]) # instruction 5:0 - to ALUCtrl address = Signal(intbv(0, min=-(2**15), max=2**15 - 1)) # instruction 15:0 - to Sign Extend wr_reg_in = Signal( intbv(0)[5:]) # output of mux_wreg (it's rt or rd depends on RegDst) address32 = Signal(intbv(0, min=-(2**31), max=2**31 - 1)) # output of signextend #register file data vectors (input and outputs) data_in, data1, data2 = [ Signal(intbv(0, min=-(2**31), max=2**31 - 1)) for i in range(3) ] mux_alu_out = Signal(intbv(0, min=-(2**31), max=2**31 - 1)) # output of mux_alu_src #(data2 or address32 depends on ALUSrc) #ALU signals alu_control_out = Signal(intbv('1111')[4:]) alu_out = Signal(intbv(0, min=-(2**31), max=2**31 - 1)) zero = Signal(intbv(0)[1:]) #data memory signal ram_out = Signal(intbv(0, min=-(2**31), max=2**31 - 1)) mux_ram_out = Signal(intbv(0, min=-(2**31), max=2**31 - 1)) ############################## # # component instances # ############################## #program counter pc = program_counter(clk_pc, next_ip, ip) increment = 1 # it's 4 in the book, but my memory it's organized in 32bits words, not bytes pc_adder = ALU(Signal(0b0010), ip, Signal(increment), pc_adder_out, Signal(0)) # hardwire an ALU to works as an adder branch_adder = ALU(Signal(0b0010), pc_adder_out, address32, branch_adder_out, Signal(0)) branch_and_gate = and_gate(Branch, zero, branchZ) mux_branch = mux2(branchZ, next_ip, pc_adder_out, branch_adder_out) im = instruction_memory(ip, instruction) id = instruction_dec(instruction, opcode, rs, rt, rd, shamt, func, address) control_i = control(opcode, RegDst, Branch, MemRead, MemtoReg, ALUop, MemWrite, ALUSrc, RegWrite) mux_wreg = mux2(RegDst, wr_reg_in, rt, rd) register_file_i = register_file(clk, rs, rt, wr_reg_in, mux_ram_out, RegWrite, data1, data2, depth=32) sign_extend_i = sign_extend(address, address32) alu_control_i = alu_control(ALUop, func, alu_control_out) mux_alu_src = mux2(ALUSrc, mux_alu_out, data2, address32) alu_i = ALU(alu_control_out, data1, mux_alu_out, alu_out, zero) data_memory_i = data_memory(clk, alu_out, data2, ram_out, MemRead, MemWrite) mux_mem2reg = mux2(MemtoReg, mux_ram_out, alu_out, ram_out) if DEBUG: @always(clk.posedge) def debug_internals(): print "-" * 78 print "time %s | clk %i | clk_pc %i | ip %i " % (now(), clk, clk_pc, ip) print 'pc_add_o %i | branch_add_o %i | BranchZ %i | next_ip %i' % ( pc_adder_out, branch_adder_out, branchZ, next_ip) print 'instruction', bin(instruction, 32) print 'opcode %s | rs %i | rt %i | rd %i | shamt %i | func %i | address %i' % \ (bin(opcode, 6), rs, rt, rd, shamt, func, address) print 'wr_reg_in %i | dat1 %i | dat2 %i | muxALUo %i ' % \ (wr_reg_in, data1, data2, mux_alu_out) print 'RegDst %i | ALUSrc %i | Mem2Reg %i | RegW %i | MemR %i | MemW %i | Branch %i | ALUop %s' % ( RegDst, ALUSrc, MemtoReg, RegWrite, MemRead, MemWrite, Branch, bin(ALUop, 2)) print 'func: %s | aluop: %s | alu_c_out: %s' % (bin( func, 5), bin(ALUop, 2), bin(alu_control_out, 4)) print 'ALU_out: %i | Zero: %i' % (alu_out, zero) print 'ram_out %i | mux_ram_out %i ' % (ram_out, mux_ram_out) return instances()