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()
Exemple #2
0
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()
Exemple #3
0
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()
Exemple #4
0
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()
Exemple #5
0
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()
Exemple #6
0
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()