Exemple #1
0
    def setup_class(self):

        clock = Signal(bool(0))
        reset = ResetSignal(0, active=1, async=True)

        # DECODER SIGNALS


        pipe_dec = decSignal()

        # Input Signals to Execute
        pipe_imme = Signal(intbv(0)[16:])
        pipe_dm_addr = Signal(intbv(0)[DM_BITS:])
        pipe_pc = Signal(intbv(0)[IM_BITS:])

        back_acc = Signal(intbv(0)[16:])
        back_dm_data = Signal(intbv(0)[16:])

        self.signals = clock, reset, pipe_dec, pipe_imme, \
            pipe_dm_addr, pipe_pc, back_acc, back_dm_data

        self.fwd_accu = Signal(intbv(0)[16:])
        self.pipe_alu_op = Signal(alu_op_type.NOP)

        self.ioin = inpSignal()
Exemple #2
0
    def setup_class(self):

        clock = Signal(bool(0))
        reset = ResetSignal(0, active=1, async=True)

        # DECODER SIGNALS
        instr_hi = Signal(intbv(0)[8:])

        pipe_dec_sig = decSignal()
        pipe_alu_op = Signal(alu_op_type.NOP)

        # Input Signals to Execute
        in_imm = Signal(intbv(0)[16:])
        in_dm_addr = Signal(intbv(0)[DM_BITS:])
        in_pc = Signal(intbv(0)[IM_BITS:])

        out_acc = Signal(intbv(0)[16:])
        out_dm_data = Signal(intbv(0)[16:])

        fwd_accu = Signal(intbv(0)[16:])

        ioin = inpSignal()

        self.signals = clock, reset, instr_hi, pipe_dec_sig, in_imm, \
            in_dm_addr, in_pc, out_acc, out_dm_data

        self.decode_inst = decoder.pyleros_decoder(instr_hi, pipe_alu_op,
                                                   pipe_dec_sig)
        self.exec_inst = execute.pyleros_exec(clock, reset, pipe_alu_op, pipe_dec_sig, in_imm, in_dm_addr, in_pc, \
                                            out_acc, out_dm_data, fwd_accu, ioin, True)

        return self.decode_inst, self.exec_inst
Exemple #3
0
    def setup_class(self):

        clock = Signal(bool(0))
        reset = ResetSignal(0, active=1, async=True)

        # DECODER SIGNALS
        instr_hi = Signal(intbv(0)[8:])

        pipe_dec_sig = decSignal()
        pipe_alu_op = Signal(alu_op_type.NOP)

        # Input Signals to Execute
        in_imm = Signal(intbv(0)[16:])
        in_dm_addr = Signal(intbv(0)[DM_BITS:])
        in_pc = Signal(intbv(0)[IM_BITS:])

        out_acc = Signal(intbv(0)[16:])
        out_dm_data = Signal(intbv(0)[16:])

        fwd_accu = Signal(intbv(0)[16:])

        ioin = inpSignal()

        self.signals = clock, reset, instr_hi, pipe_dec_sig, in_imm, \
            in_dm_addr, in_pc, out_acc, out_dm_data

        self.decode_inst = decoder.pyleros_decoder(instr_hi, pipe_alu_op, pipe_dec_sig)
        self.exec_inst = execute.pyleros_exec(clock, reset, pipe_alu_op, pipe_dec_sig, in_imm, in_dm_addr, in_pc, \
                                            out_acc, out_dm_data, fwd_accu, ioin, True)

        return self.decode_inst, self.exec_inst
Exemple #4
0
def conv_decoder():

    dec_sig = decSignal()
    alu_op = Signal(alu_op_type.NOP)
    instr_hi = Signal(intbv(0)[8:])

    inst_dec = pyleros_decoder(instr_hi, alu_op, dec_sig)

    inst_dec.convert(hdl='VHDL', path=PATH)
Exemple #5
0
def conv_decoder():

	dec_sig = decSignal()
	alu_op = Signal(alu_op_type.NOP)
	instr_hi = Signal(intbv(0)[8:])

	inst_dec = pyleros_decoder(instr_hi, alu_op, dec_sig)

	inst_dec.convert(hdl = 'VHDL', path = PATH)
Exemple #6
0
def conv_alu():

	dec_sig = decSignal()
	alu_op = Signal(alu_op_type.NOP)
	acc = Signal(intbv(0)[16:])
	pre_acc = Signal(intbv(0)[16:])
	opd = Signal(intbv(0)[16:])
	ioin = inpSignal()

	inst_alu = pyleros_alu(alu_op, dec_sig, acc, opd, pre_acc, ioin)
	inst_alu.convert(hdl = 'VHDL', path = PATH)
Exemple #7
0
def conv_alu():

    dec_sig = decSignal()
    alu_op = Signal(alu_op_type.NOP)
    acc = Signal(intbv(0)[16:])
    pre_acc = Signal(intbv(0)[16:])
    opd = Signal(intbv(0)[16:])
    ioin = inpSignal()

    inst_alu = pyleros_alu(alu_op, dec_sig, acc, opd, pre_acc, ioin)
    inst_alu.convert(hdl='VHDL', path=PATH)
Exemple #8
0
def pyleros(clk, reset, ioin, ioout, filename=None):
    """The main pyleros module. Instantiates both the fedec 
    and execute modules corresponding to the two pipeline stages, 
    and connects them with signals

    Arguments (ports):
        clk: IN Clock signal
        reset: IN Async reset signal
        ioin: The input signal, contains a rd_data of 16 bits.
        ioout: Output signal, contains output of 16 bits, i/o addr,
            and read/write strobes. The output is given in the same cycle
            as the ioout.out_strobe, and is guaranteed to be valid for 1 cycle.
            The input strobe is given, and the input is read in the same cycle.
        
    Parameters:
        filename: The file/ list containing instructions
            to load into instruction memory.

    """

    # Data forward from exec to fedec
    back_acc = Signal(intbv(0)[16:])
    fwd_accu = Signal(intbv(0)[16:])
    back_dm_data = Signal(intbv(0)[16:])

    # Decoder Signals
    pipe_dec = decSignal()

    # Other pipeline registers/signals
    pipe_imm_val = Signal(intbv(0)[16:])
    pipe_alu_op = Signal(alu_op_type.NOP)
    pipe_dm_addr = Signal(intbv(0)[DM_BITS:])
    pipe_pc = Signal(intbv(0)[IM_BITS:])    

    inst_fedec = fedec.pyleros_fedec(clk, reset, back_acc, back_dm_data, fwd_accu, pipe_alu_op,
                                        pipe_dec, pipe_imm_val, pipe_dm_addr, pipe_pc, filename=filename)

    inst_exec = execute.pyleros_exec(clk, reset, pipe_alu_op, pipe_dec, pipe_imm_val, 
                                        pipe_dm_addr, pipe_pc, back_acc, back_dm_data, fwd_accu, ioin)

    @always_comb
    def io_write():
        ioout.rd_strobe.next = pipe_dec.inp
        ioout.wr_strobe.next = pipe_dec.outp
        ioout.wr_data.next = back_acc
        ioout.io_addr.next = pipe_imm_val


    return instances()
Exemple #9
0
def conv_exec():

    clock = Signal(bool(0))
    reset = ResetSignal(0, active=1, async=True)

    pipe_dec = decSignal()

    # Input Signals to Execute
    pipe_imme = Signal(intbv(0)[16:])
    pipe_dm_addr = Signal(intbv(0)[DM_BITS:])
    pipe_pc = Signal(intbv(0)[IM_BITS:])

    back_acc = Signal(intbv(0)[16:])
    back_dm_data = Signal(intbv(0)[16:])

    fwd_accu = Signal(intbv(0)[16:])
    pipe_alu_op = Signal(alu_op_type.NOP)
    ioin = inpSignal()

    exec_inst = pyleros_exec(clock, reset, pipe_alu_op, pipe_dec, pipe_imme, pipe_dm_addr, pipe_pc, \
                                           back_acc, back_dm_data, fwd_accu, ioin)
    exec_inst.convert(hdl='VHDL', path=PATH)
Exemple #10
0
def conv_fedec():

    clock = Signal(bool(0))
    reset = ResetSignal(0, active=1, async=True)

    pipe_dec = decSignal()

    # Input Signals to Execute
    pipe_imme = Signal(intbv(0)[16:])
    pipe_dm_addr = Signal(intbv(0)[DM_BITS:])
    pipe_pc = Signal(intbv(0)[IM_BITS:])

    back_acc = Signal(intbv(0)[16:])
    back_dm_data = Signal(intbv(0)[16:])

    fwd_accu = Signal(intbv(0)[16:])
    pipe_alu_op = Signal(alu_op_type.NOP)

    fedec_inst = pyleros_fedec(clock, reset, back_acc, back_dm_data, fwd_accu, \
                    pipe_alu_op, pipe_dec, pipe_imme, pipe_dm_addr, pipe_pc, filename=ROM_PATH + 'sum_n.rom')

    fedec_inst.convert(hdl='VHDL', path=CONVERSION_PATH)
Exemple #11
0
def conv_fedec():

	clock = Signal(bool(0))
	reset = ResetSignal(0, active=1, async=True)

	pipe_dec = decSignal()

	# Input Signals to Execute
	pipe_imme = Signal(intbv(0)[16:])
	pipe_dm_addr = Signal(intbv(0)[DM_BITS:])
	pipe_pc = Signal(intbv(0)[IM_BITS:])

	back_acc = Signal(intbv(0)[16:])
	back_dm_data = Signal(intbv(0)[16:])

	fwd_accu = Signal(intbv(0)[16:])
	pipe_alu_op = Signal(alu_op_type.NOP)

	fedec_inst = pyleros_fedec(clock, reset, back_acc, back_dm_data, fwd_accu, \
	                pipe_alu_op, pipe_dec, pipe_imme, pipe_dm_addr, pipe_pc, filename=ROM_PATH + 'sum_n.rom')

	fedec_inst.convert(hdl = 'VHDL', path = CONVERSION_PATH)
Exemple #12
0
def conv_exec():

	clock = Signal(bool(0))
	reset = ResetSignal(0, active=1, async=True)

	pipe_dec = decSignal()

	# Input Signals to Execute
	pipe_imme = Signal(intbv(0)[16:])
	pipe_dm_addr = Signal(intbv(0)[DM_BITS:])
	pipe_pc = Signal(intbv(0)[IM_BITS:])

	back_acc = Signal(intbv(0)[16:])
	back_dm_data = Signal(intbv(0)[16:])

	fwd_accu = Signal(intbv(0)[16:])
	pipe_alu_op = Signal(alu_op_type.NOP)
	ioin = inpSignal()

	exec_inst = pyleros_exec(clock, reset, pipe_alu_op, pipe_dec, pipe_imme, pipe_dm_addr, pipe_pc, \
                                        back_acc, back_dm_data, fwd_accu, ioin)
	exec_inst.convert(hdl = 'VHDL', path = PATH)
Exemple #13
0
    def setup_class(self):

        clock = Signal(bool(0))
        reset = ResetSignal(0, active=1, async=True)

        # DECODER SIGNALS

        pipe_dec = decSignal()

        # Input Signals to Execute
        pipe_imme = Signal(intbv(0)[16:])
        pipe_dm_addr = Signal(intbv(0)[DM_BITS:])
        pipe_pc = Signal(intbv(0)[IM_BITS:])

        back_acc = Signal(intbv(0)[16:])
        back_dm_data = Signal(intbv(0)[16:])

        self.signals = clock, reset, pipe_dec, pipe_imme, \
            pipe_dm_addr, pipe_pc, back_acc, back_dm_data

        self.fwd_accu = Signal(intbv(0)[16:])
        self.pipe_alu_op = Signal(alu_op_type.NOP)

        self.ioin = inpSignal()
Exemple #14
0
def pyleros_fedec(clk,
                  reset,
                  back_acc,
                  back_dm_data,
                  fwd_accu,
                  pipe_alu_op,
                  pipe_dec,
                  pipe_imme,
                  pipe_dm_addr,
                  pipe_pc,
                  filename=None,
                  debug=False):
    """The fedec module for pyleros, that is, the fetch
    and decode pipeline stage. The modules is purely 
    combinatorial, except for the updating the pipeline 
    register. The IM is instantied and only accessed
    in this stage. The main functions done here are decoding
    of instruction, setting up branch control signals, selection
    of other control signals(including the ALU ones), selection 
    of DM address. an ALU operation on two local variables takes
    two cycles to execute and another cycle if the result needs 
    to written back to a local variable
    
    Arguments (ports):
        clk: IN Clock signal
        reset: IN Async reset signal
        back_acc: IN Acc value accessed here, not written. This is
            needed for setting the branch control signals and
            for memory addredd of JAL
        back_dm_data: IN The data read from the DM, which is needed for
            an direct add or and indirect load/ store(which follows)
        fwd_accu: IN The value of the accumulator, forwarded from the 
                execute stage to provide proper branching. Currently unused. 
        pipe_dec: OUT List of the decode signals, pass on to the execute stage
        pipe_imme: OUT Immediate value, as taken from the lower bits 
                of the instruction, pass on to execute stage
        pipe_dm_addr: OUT DM read addr, pipeline register
        pipe_pc: OUT the value of PC, pipeline register

    Parameters:

        filename: Name of the file or a list containing the instructions
        debug: Debugging mode, the processor prints various error messages

    """

    im_addr = Signal(intbv(0)[IM_BITS:])

    instr = Signal(intbv(0)[16:])
    instr_hi = Signal(intbv(0)[8:])

    branch_en = Signal(bool(0))

    # PC start from 0x00 in this design, and each instruction is executed exactly once.
    # In the original design, PC started from 1. However, 0x00 is typically NOP
    pc = Signal(intbv(0)[IM_BITS:])
    pc_next = Signal(intbv(0)[IM_BITS:])
    pc_add = Signal(intbv(0)[IM_BITS:])
    pc_op = Signal(intbv(0, min=-2**(IM_BITS - 1), max=2**(IM_BITS - 1) - 1))
    decode = decSignal()
    alu_op = Signal(alu_op_type.NOP)

    # Instantiate the instruction memory
    im_inst = rom.pyleros_im(im_addr, instr, filename, debug)

    # Instantiate the decoder
    dec_inst = decoder.pyleros_decoder(instr_hi, alu_op, decode, debug)

    @always_comb
    def sync_sig():

        # if __debug__:
        #     if debug:
        #         print("hi_bits:",instr[16:8])

        instr_hi.next = instr[16:8]
        im_addr.next = pc

    @always_comb
    def mux_dm_addr():

        offset_addr = intbv(back_dm_data + instr[8:0])[DM_BITS:]

        if decode.indls:
            # Indirect Addressing(with offset)
            # for indirect load/store
            # if __debug__:
            #     if debug:
            #         print("offset address: " + str(int(offset_addr)))

            pipe_dm_addr.next = offset_addr[DM_BITS:]

        else:
            # Direct Addressing
            # if __debug__:
            #     if debug:
            #         print("direct address: " + str(int(instr[DM_BITS:])))
            pipe_dm_addr.next = instr[DM_BITS:]

    @always_comb
    def branch_sel():

        acc_z = True

        # if not reset == reset.active:
        if back_acc == 0:
            acc_z = True

        else:
            acc_z = False

        branch_en.next = 0

        if decode.br_op:
            br_type = instr[11:8]

            if br_type == 0b000:
                # BRANCH
                branch_en.next = True

            elif br_type == 0b001:
                # BRZ
                if acc_z:
                    branch_en.next = True
                else:
                    branch_en.next = False

            elif br_type == 0b010:
                # BRNZ
                if not acc_z:
                    branch_en.next = True
                else:
                    branch_en.next = False

            elif br_type == 0b011:
                # BRP
                if not back_acc[15]:
                    branch_en.next = True
                else:
                    branch_en.next = False

            elif br_type == 0b100:
                # BRN
                if back_acc[15]:
                    branch_en.next = True
                else:
                    branch_en.next = False

    # For selection of next PC address
    @always_comb
    def pc_addr():

        # if __debug__:
        #     if debug:
        #         print('start', pc, pc_op, instr, back_acc, pc_add, instr)

        if branch_en == 1:
            # Sign extend the low 8 bits
            # of instruction
            pc_op.next = instr[8:].signed()

        else:
            pc_op.next = 1

        # if __debug__:
        #     if debug:
        #         print(pc, pc_op)

    @always_comb
    def pc_next_set():
        pc_add.next = intbv(pc + pc_op)[IM_BITS:]

    @always_comb
    def pc_mux():
        # Add 1 or branch offset OR set the add
        # to the jump addr
        if decode.jal:
            pc_next.next = back_acc[IM_BITS:]

        else:
            pc_next.next = pc_add

        # if __debug__:
        #     if debug:
        #         print('end', pc, pc_op, instr, back_acc, pc_add, instr)

    @always_seq(clk.posedge, reset)
    def intr_pipe():

        # if decode.add_sub == True:
        # Set the immediate value

        if decode.loadh:
            if __debug__:
                pipe_imme.next = intbv(0)[16:]
            pipe_imme.next[16:8] = instr[8:]
            pipe_imme.next[8:0] = intbv(0)[8:]
        else:

            pipe_imme.next = instr[8:]

        pipe_pc.next = pc_add

        pipe_dec.al_ena.next = decode.al_ena
        pipe_dec.ah_ena.next = decode.ah_ena
        pipe_dec.log_add.next = decode.log_add
        pipe_dec.add_sub.next = decode.add_sub
        pipe_dec.shr.next = decode.shr
        pipe_dec.sel_imm.next = decode.sel_imm
        pipe_dec.store.next = decode.store
        pipe_dec.outp.next = decode.outp
        pipe_dec.inp.next = decode.inp
        pipe_dec.br_op.next = decode.br_op
        pipe_dec.jal.next = decode.jal
        pipe_dec.loadh.next = decode.loadh
        pipe_dec.indls.next = decode.indls

        pipe_alu_op.next = alu_op

        pc.next = pc_next

    return instances()
Exemple #15
0
    def tb_fedec_top():
        """Test the fetch/ decode module in pyleros

        """

        def create_instr_list():
            instr_list, bin_list = [], []


            for instr in codes:
                if (not codes[instr][2]) or (instr == 'NOP') or (instr == 'LOADH') or (instr == 'STORE'):
                    continue

                for trie in range(20):

                    op1 = randrange(2**15)
                    # 8-bit imm opd
                    op2 = randrange(2**7)

                    bin_code = codes[instr][0]
                    # Immediate version
                    bin_imme = bin_code | 0x01

                    instr_list.append([instr, op1, op2])

                    #Add operand op2 to instr
                    bin_code = (bin_imme << 8) | (op2 & 0xff)

                    bin_list.append(bin_code)
            return instr_list, bin_list



        clock = Signal(bool(0))
        reset = ResetSignal(0, active=1, async=True)

        # FEDEC SIGNALS
        back_acc, back_dm_data = [Signal(intbv(0)[16:])] * 2
        pipe_imme = Signal(intbv(0)[16:])
        pipe_dm_addr = Signal(intbv(0)[DM_BITS:])
        pipe_pc = Signal(intbv(0)[IM_BITS:])
        fwd_accu = Signal(intbv(0)[16:])

        out_dec = decSignal()
        test_dec = decSignal()
        alu_op = Signal(alu_op_type.NOP)
        pipe_alu_op = Signal(alu_op_type.NOP)
    
        instr_hi = Signal(intbv(0)[8:])
        dec_inst = decoder.pyleros_decoder(instr_hi, alu_op, test_dec)

        ioin = inpSignal()

        # ALU SIGNALS
        # out_list
        alu_acc = Signal(intbv(0)[16:])
        alu_opd = Signal(intbv(0)[16:])
        alu_res = Signal(intbv(0)[16:])
        
        instr_list, bin_list = create_instr_list()

        alu_inst = alu.pyleros_alu(pipe_alu_op, out_dec, alu_acc, alu_opd, alu_res, ioin)

        fedec_inst = fedec.pyleros_fedec(clock, reset, back_acc, back_dm_data, fwd_accu, pipe_alu_op,
                                        out_dec, pipe_imme, pipe_dm_addr, pipe_pc, filename=bin_list, debug = True)
    

        @always(delay(100))
        def tbclk():
            clock.next = not clock      

            

        @instance
        def tbstim():

            # To start the fetch/decoding
            # reset.next = not reset.active
            

            print("bin_list")
            for i in range(10):
                print(bin_list[i], instr_list[i][2])

            # In the first cycle nothing happens since
            # only the instuction is updated, and the 
            # decoder, the output from fedec doesn't change 
            # till after the second cycle.
            yield clock.posedge
            ninstr = len(instr_list)
            for addr in range(1,ninstr - 1):

                # if addr == 10:
                #   raise StopSimulation
                print(addr)
                # for the alu, op1 signifies the acc adn
                # op2 the opd
                instr, op1, op2 = instr_list[addr]
                instr_hi.next = (codes[instr][0] | 0x01)

                yield clock.posedge
                
                yield delay(3)
                

                for sig in dlist:
                    assert test_dec.signals[int(sig)] == out_dec.signals[int(sig)]

                print("Cmp Imm", op2, pipe_imme)
                alu_acc.next = op1
                alu_opd.next = pipe_imme
                yield delay(3)
                # print("alu ops", op1, alu_acc, pipe_imme, alu_opd)
                # print("alu types", type(op1), type(alu_acc), type(pipe_imme), type(alu_opd))
                # print(out_dec[int(dec_op_type.add_sub)], out_dec[int(dec_op_type.log_add)])

                #check for correct result
                if instr == 'NOP':
                    pass

                elif instr == 'ADD':
                    assert alu_res == int(op1) + int(op2)

                elif instr == 'SUB':
                    assert alu_res == ((op1 - op2) & 0xffff)

                elif instr == 'SHR':
                    assert alu_res == (op1 & 0xffff) >> 1

                elif instr == 'AND':
                    assert alu_res == (op1 & op2) & 0xffff

                elif instr == 'OR':
                    assert alu_res == (op1 | op2) & 0xffff

                elif instr == 'XOR':
                    assert alu_res == (op1 ^ op2) & 0xffff

                elif instr == 'LOAD':
                    assert alu_res == op2 & 0xffff


            


            raise StopSimulation

        return instances()
Exemple #16
0
    def tb_fedec_top():
        """Test the fetch/ decode module in pyleros

        """
        def create_instr_list():
            instr_list, bin_list = [], []

            for instr in codes:
                if (not codes[instr][2]) or (instr == 'NOP') or (
                        instr == 'LOADH') or (instr == 'STORE'):
                    continue

                for trie in range(20):

                    op1 = randrange(2**15)
                    # 8-bit imm opd
                    op2 = randrange(2**7)

                    bin_code = codes[instr][0]
                    # Immediate version
                    bin_imme = bin_code | 0x01

                    instr_list.append([instr, op1, op2])

                    #Add operand op2 to instr
                    bin_code = (bin_imme << 8) | (op2 & 0xff)

                    bin_list.append(bin_code)
            return instr_list, bin_list

        clock = Signal(bool(0))
        reset = ResetSignal(0, active=1, async=True)

        # FEDEC SIGNALS
        back_acc, back_dm_data = [Signal(intbv(0)[16:])] * 2
        pipe_imme = Signal(intbv(0)[16:])
        pipe_dm_addr = Signal(intbv(0)[DM_BITS:])
        pipe_pc = Signal(intbv(0)[IM_BITS:])
        fwd_accu = Signal(intbv(0)[16:])

        out_dec = decSignal()
        test_dec = decSignal()
        alu_op = Signal(alu_op_type.NOP)
        pipe_alu_op = Signal(alu_op_type.NOP)

        instr_hi = Signal(intbv(0)[8:])
        dec_inst = decoder.pyleros_decoder(instr_hi, alu_op, test_dec)

        ioin = inpSignal()

        # ALU SIGNALS
        # out_list
        alu_acc = Signal(intbv(0)[16:])
        alu_opd = Signal(intbv(0)[16:])
        alu_res = Signal(intbv(0)[16:])

        instr_list, bin_list = create_instr_list()

        alu_inst = alu.pyleros_alu(pipe_alu_op, out_dec, alu_acc, alu_opd,
                                   alu_res, ioin)

        fedec_inst = fedec.pyleros_fedec(clock,
                                         reset,
                                         back_acc,
                                         back_dm_data,
                                         fwd_accu,
                                         pipe_alu_op,
                                         out_dec,
                                         pipe_imme,
                                         pipe_dm_addr,
                                         pipe_pc,
                                         filename=bin_list,
                                         debug=True)

        @always(delay(100))
        def tbclk():
            clock.next = not clock

        @instance
        def tbstim():

            # To start the fetch/decoding
            # reset.next = not reset.active

            print("bin_list")
            for i in range(10):
                print(bin_list[i], instr_list[i][2])

            # In the first cycle nothing happens since
            # only the instuction is updated, and the
            # decoder, the output from fedec doesn't change
            # till after the second cycle.
            yield clock.posedge
            ninstr = len(instr_list)
            for addr in range(1, ninstr - 1):

                # if addr == 10:
                #   raise StopSimulation
                print(addr)
                # for the alu, op1 signifies the acc adn
                # op2 the opd
                instr, op1, op2 = instr_list[addr]
                instr_hi.next = (codes[instr][0] | 0x01)

                yield clock.posedge

                yield delay(3)

                for sig in dlist:
                    assert test_dec.signals[int(sig)] == out_dec.signals[int(
                        sig)]

                print("Cmp Imm", op2, pipe_imme)
                alu_acc.next = op1
                alu_opd.next = pipe_imme
                yield delay(3)
                # print("alu ops", op1, alu_acc, pipe_imme, alu_opd)
                # print("alu types", type(op1), type(alu_acc), type(pipe_imme), type(alu_opd))
                # print(out_dec[int(dec_op_type.add_sub)], out_dec[int(dec_op_type.log_add)])

                #check for correct result
                if instr == 'NOP':
                    pass

                elif instr == 'ADD':
                    assert alu_res == int(op1) + int(op2)

                elif instr == 'SUB':
                    assert alu_res == ((op1 - op2) & 0xffff)

                elif instr == 'SHR':
                    assert alu_res == (op1 & 0xffff) >> 1

                elif instr == 'AND':
                    assert alu_res == (op1 & op2) & 0xffff

                elif instr == 'OR':
                    assert alu_res == (op1 | op2) & 0xffff

                elif instr == 'XOR':
                    assert alu_res == (op1 ^ op2) & 0xffff

                elif instr == 'LOAD':
                    assert alu_res == op2 & 0xffff

            raise StopSimulation

        return instances()
Exemple #17
0
    def tb_alu_top(imen=False):
        """Test the alu module in pyleros

        """

        clock = Signal(bool(0))
        reset = ResetSignal(0, active=1, async=True)

        # DECODER SIGNALS
        instr_hi = Signal(intbv(0)[8:])

        dec_signal = decSignal()
        alu_op = Signal(alu_op_type.NOP)
        ioin = inpSignal()
        decode_inst = decoder.pyleros_decoder(instr_hi, alu_op, dec_signal)

        # ALU SIGNALS
        # dec_signal
        alu_acc = Signal(intbv(0)[16:])
        alu_opd = Signal(intbv(0)[16:])
        alu_res = Signal(intbv(0)[16:])

        alu_inst = alu.pyleros_alu(alu_op, dec_signal, alu_acc, alu_opd, alu_res, ioin)


        rd_addr = Signal(intbv(0)[IM_BITS:])
        rd_data = Signal(intbv(0)[16:])
        instr_list, bin_list = [], []
        # Create instruction memory if enabled.
        if imen:
            for instr in codes:

                for trie in range(20):

                    op1 = randrange(2**15)
                    op2 = randrange(2**15)

                    bin_code = codes[instr][0]

                    instr_list.append([instr, op1, op2])
                    bin_code = (bin_code << 8)

                    bin_list.append(bin_code)

            inst_im = rom.pyleros_im(rd_addr, rd_data, IM_array=tuple(bin_list))



        @always(delay(10))
        def tbclk():
            clock.next = not clock

        

        # def _bench_alu():
            

        @instance
        def tbstim():

            for i in range(5):
                yield clock.posedge

            if imen:

                ninstr = len(instr_list)
                for addr in range(ninstr):
                    instr, op1, op2 = instr_list[addr]

                    rd_addr.next = intbv(addr)[IM_BITS:]

                    yield clock.posedge
                    yield delay(2)

                    assert rd_data == bin_list[rd_addr]
                    upp = (int(rd_data)) >> 8
                    assert upp == codes[instr][0]
                    instr_hi.next = intbv(upp)[8:]

                    alu_acc.next = op1
                    alu_opd.next = op2

                    yield delay(33)

                    #check for correct result
                    if instr == 'NOP':
                        pass

                    elif instr == 'ADD':
                        assert alu_res == ((op1 + op2) & 0xffff)

                    elif instr == 'SUB':
                        assert alu_res == ((op1 - op2) & 0xffff)

                    elif instr == 'SHR':
                        assert alu_res == (op1 & 0xffff) >> 1

                    elif instr == 'AND':
                        assert alu_res == (op1 & op2) & 0xffff

                    elif instr == 'OR':
                        assert alu_res == (op1 | op2) & 0xffff

                    elif instr == 'XOR':
                        assert alu_res == (op1 ^ op2) & 0xffff

                    elif instr == 'LOAD':
                        assert alu_res == op2 & 0xffff


            else:

                for instr in codes:

                    for i in range(10):
                        # Choose random operands
                        op1 = randrange(2**15)
                        op2 = randrange(2**15)

                        # Set the decoder input
                        instr_op = codes[instr][0]
                        instr_hi.next = instr_op
                        
                        alu_acc.next = op1
                        alu_opd.next = op2

                        # Wait for operation
                        yield delay(33)

                        #check for correct result
                        if instr == 'NOP':
                            pass

                        elif instr == 'ADD':
                            assert alu_res == ((op1 + op2) & 0xffff)

                        elif instr == 'SUB':
                            assert alu_res == ((op1 - op2) & 0xffff)

                        elif instr == 'SHR':
                            assert alu_res == (op1 & 0xffff) >> 1

                        elif instr == 'AND':
                            assert alu_res == (op1 & op2) & 0xffff

                        elif instr == 'OR':
                            assert alu_res == (op1 | op2) & 0xffff

                        elif instr == 'XOR':
                            assert alu_res == (op1 ^ op2) & 0xffff

                        elif instr == 'LOAD':
                            assert alu_res == op2 & 0xffff


            raise StopSimulation

        return instances() #, decode_inst
Exemple #18
0
def tb_dec_top(args=None):
    """Test the decoder module in pyleros

    """
    clock = Signal(bool(0))
    reset = ResetSignal(0, active=0, async=True)

    # the high 8 bits of the instruction
    instr_hi = Signal(intbv(0)[8:])

    dec_signal = decSignal()
    alu_op = Signal(alu_op_type.NOP)

    @always(delay(10))
    def tbclk():
        clock.next = not clock



    # instantiate the decoder
    decode_inst = decoder.pyleros_decoder(instr_hi, alu_op, dec_signal)

    @instance
    def tbstim():

        for i in range(5):
            yield clock.posedge

        for instr in codes:

            # set the input to the decoder
            instr_op = codes[instr][0]
            instr_hi.next = instr_op
            yield delay(33)

            # check for correct decode
            for cs in dlist:
                if cs in codes[instr][1]:
                    assert dec_signal.signals[int(cs)] == True
                else:
                    assert dec_signal.signals[int(cs)] == False


            yield delay(33)

            if codes[instr][2] == True:

                instr_imm = instr_op | 0x01
                instr_hi.next = instr_imm
                yield delay(33)

                # check for correct decode
                for cs in dlist:

                    if (cs in codes[instr][1]) or (cs == dec_op_type.sel_imm):
                        assert dec_signal.signals[int(cs)] == True
                    else:
                        assert dec_signal.signals[int(cs)] == False

            for ii in range(5):
                yield clock.posedge


        raise StopSimulation

    return instances()
Exemple #19
0
    def tb_alu_top(imen=False):
        """Test the alu module in pyleros

        """

        clock = Signal(bool(0))
        reset = ResetSignal(0, active=1, async=True)

        # DECODER SIGNALS
        instr_hi = Signal(intbv(0)[8:])

        dec_signal = decSignal()
        alu_op = Signal(alu_op_type.NOP)
        ioin = inpSignal()
        decode_inst = decoder.pyleros_decoder(instr_hi, alu_op, dec_signal)

        # ALU SIGNALS
        # dec_signal
        alu_acc = Signal(intbv(0)[16:])
        alu_opd = Signal(intbv(0)[16:])
        alu_res = Signal(intbv(0)[16:])

        alu_inst = alu.pyleros_alu(alu_op, dec_signal, alu_acc, alu_opd,
                                   alu_res, ioin)

        rd_addr = Signal(intbv(0)[IM_BITS:])
        rd_data = Signal(intbv(0)[16:])
        instr_list, bin_list = [], []
        # Create instruction memory if enabled.
        if imen:
            for instr in codes:

                for trie in range(20):

                    op1 = randrange(2**15)
                    op2 = randrange(2**15)

                    bin_code = codes[instr][0]

                    instr_list.append([instr, op1, op2])
                    bin_code = (bin_code << 8)

                    bin_list.append(bin_code)

            inst_im = rom.pyleros_im(rd_addr,
                                     rd_data,
                                     IM_array=tuple(bin_list))

        @always(delay(10))
        def tbclk():
            clock.next = not clock

        # def _bench_alu():

        @instance
        def tbstim():

            for i in range(5):
                yield clock.posedge

            if imen:

                ninstr = len(instr_list)
                for addr in range(ninstr):
                    instr, op1, op2 = instr_list[addr]

                    rd_addr.next = intbv(addr)[IM_BITS:]

                    yield clock.posedge
                    yield delay(2)

                    assert rd_data == bin_list[rd_addr]
                    upp = (int(rd_data)) >> 8
                    assert upp == codes[instr][0]
                    instr_hi.next = intbv(upp)[8:]

                    alu_acc.next = op1
                    alu_opd.next = op2

                    yield delay(33)

                    #check for correct result
                    if instr == 'NOP':
                        pass

                    elif instr == 'ADD':
                        assert alu_res == ((op1 + op2) & 0xffff)

                    elif instr == 'SUB':
                        assert alu_res == ((op1 - op2) & 0xffff)

                    elif instr == 'SHR':
                        assert alu_res == (op1 & 0xffff) >> 1

                    elif instr == 'AND':
                        assert alu_res == (op1 & op2) & 0xffff

                    elif instr == 'OR':
                        assert alu_res == (op1 | op2) & 0xffff

                    elif instr == 'XOR':
                        assert alu_res == (op1 ^ op2) & 0xffff

                    elif instr == 'LOAD':
                        assert alu_res == op2 & 0xffff

            else:

                for instr in codes:

                    for i in range(10):
                        # Choose random operands
                        op1 = randrange(2**15)
                        op2 = randrange(2**15)

                        # Set the decoder input
                        instr_op = codes[instr][0]
                        instr_hi.next = instr_op

                        alu_acc.next = op1
                        alu_opd.next = op2

                        # Wait for operation
                        yield delay(33)

                        #check for correct result
                        if instr == 'NOP':
                            pass

                        elif instr == 'ADD':
                            assert alu_res == ((op1 + op2) & 0xffff)

                        elif instr == 'SUB':
                            assert alu_res == ((op1 - op2) & 0xffff)

                        elif instr == 'SHR':
                            assert alu_res == (op1 & 0xffff) >> 1

                        elif instr == 'AND':
                            assert alu_res == (op1 & op2) & 0xffff

                        elif instr == 'OR':
                            assert alu_res == (op1 | op2) & 0xffff

                        elif instr == 'XOR':
                            assert alu_res == (op1 ^ op2) & 0xffff

                        elif instr == 'LOAD':
                            assert alu_res == op2 & 0xffff

            raise StopSimulation

        return instances()  #, decode_inst
Exemple #20
0
def pyleros_fedec(clk, reset, back_acc, back_dm_data, fwd_accu, pipe_alu_op,
                 pipe_dec, pipe_imme, pipe_dm_addr, pipe_pc, filename=None, debug=False):
    """The fedec module for pyleros, that is, the fetch
    and decode pipeline stage. The modules is purely 
    combinatorial, except for the updating the pipeline 
    register. The IM is instantied and only accessed
    in this stage. The main functions done here are decoding
    of instruction, setting up branch control signals, selection
    of other control signals(including the ALU ones), selection 
    of DM address. an ALU operation on two local variables takes
    two cycles to execute and another cycle if the result needs 
    to written back to a local variable
    
    Arguments (ports):
        clk: IN Clock signal
        reset: IN Async reset signal
        back_acc: IN Acc value accessed here, not written. This is
            needed for setting the branch control signals and
            for memory addredd of JAL
        back_dm_data: IN The data read from the DM, which is needed for
            an direct add or and indirect load/ store(which follows)
        fwd_accu: IN The value of the accumulator, forwarded from the 
                execute stage to provide proper branching. Currently unused. 
        pipe_dec: OUT List of the decode signals, pass on to the execute stage
        pipe_imme: OUT Immediate value, as taken from the lower bits 
                of the instruction, pass on to execute stage
        pipe_dm_addr: OUT DM read addr, pipeline register
        pipe_pc: OUT the value of PC, pipeline register

    Parameters:

        filename: Name of the file or a list containing the instructions
        debug: Debugging mode, the processor prints various error messages

    """

    im_addr = Signal(intbv(0)[IM_BITS:])

    instr = Signal(intbv(0)[16:])
    instr_hi = Signal(intbv(0)[8:])

    branch_en = Signal(bool(0))


    # PC start from 0x00 in this design, and each instruction is executed exactly once. 
    # In the original design, PC started from 1. However, 0x00 is typically NOP
    pc = Signal(intbv(0)[IM_BITS:]) 
    pc_next = Signal(intbv(0)[IM_BITS:])
    pc_add = Signal(intbv(0)[IM_BITS:])
    pc_op = Signal(intbv(0, min = -2**(IM_BITS - 1), max = 2**(IM_BITS - 1) - 1))
    decode = decSignal()
    alu_op = Signal(alu_op_type.NOP)

    # Instantiate the instruction memory
    im_inst = rom.pyleros_im(im_addr, instr, filename, debug)

    # Instantiate the decoder
    dec_inst = decoder.pyleros_decoder(instr_hi, alu_op, decode, debug)

    @always_comb
    def sync_sig():

        # if __debug__:
        #     if debug:
        #         print("hi_bits:",instr[16:8])

        instr_hi.next = instr[16:8]
        im_addr.next = pc


    @always_comb
    def mux_dm_addr():

        offset_addr = intbv(back_dm_data + instr[8:0])[DM_BITS:]        
        
        if decode.indls:
            # Indirect Addressing(with offset) 
            # for indirect load/store
            # if __debug__:
            #     if debug:
            #         print("offset address: " + str(int(offset_addr)))

            pipe_dm_addr.next = offset_addr[DM_BITS:] 

        else:
            # Direct Addressing
            # if __debug__:
            #     if debug:
            #         print("direct address: " + str(int(instr[DM_BITS:])))
            pipe_dm_addr.next = instr[DM_BITS:]

    @always_comb
    def branch_sel():

        acc_z = True
        
        # if not reset == reset.active:
        if back_acc == 0:
            acc_z = True

        else:
            acc_z = False

        branch_en.next = 0

        if decode.br_op:
            br_type = instr[11:8]

            if br_type == 0b000:
                # BRANCH
                branch_en.next = True

            elif br_type == 0b001:
                # BRZ
                if acc_z:
                    branch_en.next = True
                else:
                    branch_en.next = False

            elif br_type == 0b010:
                # BRNZ
                if not acc_z:
                    branch_en.next = True
                else:
                    branch_en.next = False

            elif br_type == 0b011:
                # BRP
                if not back_acc[15]:
                    branch_en.next = True
                else:
                    branch_en.next = False

            elif br_type == 0b100:
                # BRN
                if back_acc[15]:
                    branch_en.next = True
                else:
                    branch_en.next = False

    # For selection of next PC address
    @always_comb
    def pc_addr():

        # if __debug__:
        #     if debug:
        #         print('start', pc, pc_op, instr, back_acc, pc_add, instr)

        if branch_en == 1:
            # Sign extend the low 8 bits
            # of instruction
            pc_op.next = instr[8:].signed()

        else:
            pc_op.next = 1

        # if __debug__:
        #     if debug:
        #         print(pc, pc_op)
        
    @always_comb
    def pc_next_set():
        pc_add.next = intbv(pc + pc_op)[IM_BITS:]


    @always_comb
    def pc_mux():
        # Add 1 or branch offset OR set the add
        # to the jump addr
        if decode.jal: 
            pc_next.next = back_acc[IM_BITS:]

        else:
            pc_next.next = pc_add

        # if __debug__:
        #     if debug:
        #         print('end', pc, pc_op, instr, back_acc, pc_add, instr)
    
    @always_seq(clk.posedge, reset)
    def intr_pipe():

        # if decode.add_sub == True:
        # Set the immediate value

        if decode.loadh:
            if __debug__:
                pipe_imme.next = intbv(0)[16:]
            pipe_imme.next[16:8] = instr[8:]
            pipe_imme.next[8:0] = intbv(0)[8:]
        else:

            pipe_imme.next = instr[8:]

        pipe_pc.next = pc_add 

        pipe_dec.al_ena.next = decode.al_ena
        pipe_dec.ah_ena.next = decode.ah_ena
        pipe_dec.log_add.next = decode.log_add
        pipe_dec.add_sub.next = decode.add_sub
        pipe_dec.shr.next = decode.shr
        pipe_dec.sel_imm.next = decode.sel_imm
        pipe_dec.store.next = decode.store
        pipe_dec.outp.next = decode.outp
        pipe_dec.inp.next = decode.inp
        pipe_dec.br_op.next = decode.br_op
        pipe_dec.jal.next = decode.jal
        pipe_dec.loadh.next = decode.loadh
        pipe_dec.indls.next = decode.indls

        pipe_alu_op.next = alu_op

        pc.next = pc_next        

    return instances()