Exemple #1
0
async def test_regfile_concurrentrw(dut):
    """Test regfile concurrent read/write to same address"""

    clkedge = init_posedge_clk(dut.regfile_clk)

    # Reset
    dut.regfile_nreset <= 0
    await clkedge
    dut.regfile_nreset <= 1
    await clkedge

    test_addr = 4
    test_value = 0xbeefbeef

    dut.regfile_write_addr1.setimmediatevalue(0)
    dut.regfile_write_enable1.setimmediatevalue(0)
    dut.regfile_write_value1.setimmediatevalue(0)
    dut.regfile_read_addr1.setimmediatevalue(0)
    dut.regfile_read_addr2.setimmediatevalue(0)
    await clkedge
    await Timer(1, 'us')
    assert_neq(dut.regfile_read_value1, test_value)
    assert_neq(dut.regfile_read_value2, test_value)

    dut.regfile_write_addr1.setimmediatevalue(test_addr)
    dut.regfile_write_value1.setimmediatevalue(test_value)
    dut.regfile_write_enable1.setimmediatevalue(1)
    # Read out value as soon as we can
    dut.regfile_read_addr1.setimmediatevalue(test_addr)
    dut.regfile_read_addr2.setimmediatevalue(test_addr)
    await clkedge
    await Timer(1, 'us')
    assert_eq(dut.regfile_read_value1, test_value)
    assert_eq(dut.regfile_read_value2, test_value)
Exemple #2
0
async def test_decoder_assert(dut):
    """Test decoder assertions against the lab test code"""

    clkedge = init_posedge_clk(dut.decoder_clk)

    # Reset and enable
    dut.decoder_nreset <= 0
    await clkedge
    dut.decoder_nreset <= 1
    dut.decoder_enable <= 1

    # Read instruction hex
    with open('cpu/init/code.hex') as code_hex:
        for inst_hexstr in code_hex.read().splitlines():
            dut._log.debug('Testing decoder instruction:', inst_hexstr)
            instr = int(inst_hexstr, 16)
            dut.decoder_fetcher_inst.setimmediatevalue(instr)
            assert dut.decoder_fetcher_inst == instr
            await clkedge
            # We need to wait a little since the values just became available
            # at the last clkedge
            await Timer(1, 'us')
            assert dut.decoder_ready.value.integer
            assert dut.decoder_fetcher_inst == instr
            assert dut.decoder_decoder_inst == instr

    # Reset dut to initial state
    dut.decoder_enable.setimmediatevalue(0)
Exemple #3
0
async def test_decoder_stall_for_ldr(dut):
    """Test decoder's stalling for LDR"""

    clkedge = init_posedge_clk(dut.decoder_clk)

    # Need to add PC offset when setting decoder_pc due to pipelining
    decoder_pc_offset = 8

    # Reset and enable
    dut.decoder_nreset <= 0
    await clkedge
    dut.decoder_nreset <= 1
    dut.decoder_enable <= 1

    dut.decoder_fetcher_inst <= 0xe79842a9  # ldr r4, [r8, r9, lsr #5]
    await clkedge
    # We need to wait a little since the values just became available
    # at the last clkedge
    await Timer(1, 'us')
    assert dut.decoder_ready.value.integer
    assert_eq(dut.decoder_regfile_read_addr1, 8)
    assert_eq(dut.decoder_regfile_read_addr2, 9)

    dut.decoder_fetcher_inst <= 0xe1a05004  # mov r5, r4
    await clkedge
    # We need to wait a little since the values just became available
    # at the last clkedge
    await Timer(1, 'us')
    assert dut.decoder_ready.value.integer
    assert_eq(dut.decoder_regfile_read_addr2, 4)  # r4
    assert dut.decoder_stall_for_ldr.value.integer
Exemple #4
0
async def test_executor_data_single(dut):
    """Test executor on a single data instruction"""

    clkedge = init_posedge_clk(dut.executor_clk)

    # Reset and enable
    dut.executor_nreset <= 0
    await clkedge
    dut.executor_nreset <= 1
    dut.executor_enable <= 1

    # Test result of one data instruction

    dut.executor_decoder_inst <= int('e0864007', 16) # add	r4, r6, r7
    Rn_value = 3 # r6
    Rd_Rm_value = 5 # r7
    dut.executor_decoder_Rn_value <= Rn_value
    dut.executor_decoder_Rd_Rm_value <= Rd_Rm_value
    await clkedge
    # We need to wait a little since the values just became available
    # at the last clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert dut.executor_update_Rd.value.integer
    assert not dut.executor_flush_for_pc.value.integer
    assert dut.executor_databranch_Rd_value == Rn_value + Rd_Rm_value
Exemple #5
0
async def test_regfile_pc(dut):
    """Test regfile PC-specific updates"""

    clkedge = init_posedge_clk(dut.regfile_clk)

    # Reset
    dut.regfile_nreset <= 0
    await clkedge
    dut.regfile_nreset <= 1
    await clkedge
    dut._log.info('Reset complete')

    # PC should be initialized to zero
    assert dut.regfile_pc == 0

    # Try setting new value
    dut.regfile_update_pc.setimmediatevalue(1)
    dut.regfile_new_pc.setimmediatevalue(42)

    await clkedge
    # Wait a little bit after clkedge to check immediate values
    await Timer(1, 'us')

    assert dut.regfile_pc == 42

    # Stop modifying PC so other tests can reset the PC
    dut.regfile_update_pc.setimmediatevalue(0)
Exemple #6
0
async def test_regfile_write(dut):
    """Test regfile writes"""
    clkedge = init_posedge_clk(dut.regfile_clk)
    expected_regfile = read_regfile_init(mutable=True)

    async def _check_regfile_expected():
        # Set read to some instruction to not trigger PC-specific behavior
        dut._log.info('Checking regfile values')
        dut.regfile_read_inst.setimmediatevalue(int('e1540005',
                                                    16))  # cmp r4, r5
        for addr in range(len(expected_regfile)):
            dut.regfile_read_addr1.setimmediatevalue(addr)
            dut.regfile_read_addr2.setimmediatevalue(addr)
            await clkedge
            # Wait a little bit after clkedge to check immediate values
            await Timer(1, 'us')
            assert dut.regfile_read_value1 == expected_regfile[addr]
            assert dut.regfile_read_value2 == expected_regfile[addr]

    async def _write_and_check(new_addr, new_value):
        """Do a quick check of the value written"""
        dut._log.info(
            f"Start write and check for r{new_addr} = {hex(new_value)}")
        assert expected_regfile[new_addr] != new_value
        expected_regfile[new_addr] = new_value
        dut.regfile_write_addr1.setimmediatevalue(new_addr)
        dut.regfile_write_value1.setimmediatevalue(new_value)
        dut.regfile_write_enable1.setimmediatevalue(1)
        # Read out value as soon as we can
        dut.regfile_read_addr1.setimmediatevalue(new_addr)

        await clkedge
        # Wait a little bit after clkedge to check immediate values
        await Timer(1, 'us')

        assert_eq(dut.regfile_read_value1, new_value)

    # Reset
    dut.regfile_nreset <= 0
    await clkedge
    dut.regfile_nreset <= 1
    await clkedge
    dut._log.info('Reset complete')

    # Save original files so we can restore them at the end of the test
    orig_r4 = expected_regfile[4]
    orig_r5 = expected_regfile[5]

    await _check_regfile_expected()

    await _write_and_check(4, 0xdead)
    await _write_and_check(4, 0xdeadbeef)
    await _write_and_check(5, 0xbeef)

    await _check_regfile_expected()

    await _write_and_check(4, orig_r4)
    await _write_and_check(5, orig_r5)
Exemple #7
0
async def _setup_data_memory(dut):
    clkedge = init_posedge_clk(dut.data_memory_clk)

    # Reset and enable
    dut.data_memory_nreset <= 0
    await clkedge
    dut.data_memory_nreset <= 1

    return clkedge
async def _setup_memaccessor(dut):
    clkedge = init_posedge_clk(dut.memaccessor_clk)

    # Reset and enable
    dut.memaccessor_nreset <= 0
    await clkedge
    dut.memaccessor_nreset <= 1

    return clkedge
Exemple #9
0
async def test_fetcher_disable(dut):
    """Test if fetcher persists outputs when disabled"""

    clkedge = init_posedge_clk(dut.fetcher_clk)

    code_memory = read_code_memory()

    # Need to add PC offset when setting fetcher_pc due to pipelining
    fetcher_pc_offset = 8

    # Reset and enable
    dut.fetcher_nreset <= 0
    await clkedge
    dut.fetcher_nreset <= 1
    dut.fetcher_enable <= 1

    initial_inputs = {
        dut.fetcher_pc: 64,
    }
    expected_outputs = {
        dut.fetcher_fetcher_inst:
        code_memory[initial_inputs[dut.fetcher_pc] >> 2],
    }

    def _check_expected():
        for signal, value in expected_outputs.items():
            try:
                assert_eq(signal, value)
            except AssertionError as exc:
                raise AssertionError(
                    'Failed expected value on signal {} with error: {}'.format(
                        signal._name, str(exc)))

    # Set initial inputs
    for signal, value in initial_inputs.items():
        signal <= value

    await clkedge
    await Timer(1, 'us')
    assert dut.fetcher_ready.value.integer
    # Check expected_outputs
    _check_expected()

    # Disable module
    dut.fetcher_enable <= 0

    # Scramble inputs
    for signal in initial_inputs:
        signal <= 1
    await clkedge
    await Timer(1, 'us')
    assert not dut.fetcher_ready.value.integer
    # Check expected outputs
    _check_expected()
async def _setup_regfilewriter(dut):
    clkedge = init_posedge_clk(dut.regfilewriter_clk)

    # Reset and enable
    dut.regfilewriter_nreset <= 0
    await clkedge
    dut.regfilewriter_nreset <= 1
    dut.regfilewriter_enable <= 1

    # Set default pc value
    current_pc = 20
    dut.regfilewriter_pc <= current_pc

    return clkedge, current_pc
Exemple #11
0
async def test_executor_data_conditional(dut):
    """Test executor on conditional data instructions"""

    clkedge = init_posedge_clk(dut.executor_clk)

    # Reset and enable
    dut.executor_nreset <= 0
    await clkedge
    dut.executor_nreset <= 1
    dut.executor_enable <= 1

    # Set CPSR
    dut.executor_decoder_inst <= int('e1540005', 16) # cmp r4, r5
    Rn_value = 65535 # r4
    Rd_Rm_value = 65535 # r5
    dut.executor_decoder_Rn_value <= Rn_value
    dut.executor_decoder_Rd_Rm_value <= Rd_Rm_value
    await clkedge
    # We need to wait a little since the values just became available
    # at the last clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert not dut.executor_update_Rd.value.integer
    assert not dut.executor_flush_for_pc.value.integer

    # Test non-execution
    dut.executor_decoder_inst <= int('13a0e000', 16) # movne lr, #0
    await clkedge
    # We need to wait a little since the values just became available
    # at the last clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert not dut.executor_update_Rd.value.integer
    assert not dut.executor_flush_for_pc.value.integer

    # Test execution
    dut.executor_decoder_inst <= int('01a0f00e', 16) # moveq pc, lr
    Rd_Rm_value = 42 # r5
    dut.executor_decoder_Rd_Rm_value <= Rd_Rm_value
    await clkedge
    # We need to wait a little since the values just became available
    # at the last clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert dut.executor_update_Rd.value.integer
    assert dut.executor_databranch_Rd_value == Rd_Rm_value
    assert dut.executor_flush_for_pc.value.integer

    # Reset dut to initial state
    dut.executor_enable.setimmediatevalue(0)
Exemple #12
0
async def test_executor_memory(dut):
    """Test executor on memory instructions"""

    clkedge = init_posedge_clk(dut.executor_clk)

    # Reset and enable
    dut.executor_nreset <= 0
    await clkedge
    dut.executor_nreset <= 1
    dut.executor_enable <= 1

    dut._log.info("Test LDR")
    dut.executor_decoder_inst <= int('e79842a9', 16) # ldr r4, [r8, r9, lsr #5]
    Rn_value = 4 # r8
    Rd_Rm_value = 0b1100000 # r9, final value after LSR #5 should be 3
    dut.executor_decoder_Rn_value <= Rn_value
    dut.executor_decoder_Rd_Rm_value <= Rd_Rm_value
    await clkedge
    # We need to wait a little since the values just became available
    # at the last clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert dut.executor_update_Rd.value.integer
    assert not dut.executor_flush_for_pc.value.integer
    assert not dut.executor_mem_write_enable.value.integer
    assert dut.executor_mem_read_addr == Rn_value+(Rd_Rm_value>>5)

    dut._log.info("Test STR")
    dut.executor_decoder_inst <= int('e5885000', 16) # str r5, [r8]
    Rd_Rm_value = 0xdeadbeef # r5
    Rn_value = 1 # r8
    dut.executor_decoder_Rn_value <= Rn_value
    dut.executor_decoder_Rd_Rm_value <= Rd_Rm_value
    await clkedge
    # We need to wait a little since the values just became available
    # at the last clkedge
    await Timer(1, 'us')
    # STR should not update Rd
    assert not dut.executor_update_Rd.value.integer
    assert not dut.executor_flush_for_pc.value.integer
    assert dut.executor_mem_write_enable.value.integer
    assert dut.executor_mem_write_addr == Rn_value
    assert dut.executor_mem_write_value == Rd_Rm_value

    # Reset dut to initial state
    dut.executor_enable.setimmediatevalue(0)
Exemple #13
0
async def test_executor_branch(dut):
    """Test executor on branch instructions"""

    clkedge = init_posedge_clk(dut.executor_clk)

    # Need to add PC offset when setting executor_pc due to pipelining
    executor_pc_offset = 8

    # Reset and enable
    dut.executor_nreset <= 0
    await clkedge
    dut.executor_nreset <= 1
    dut.executor_enable <= 1

    # Test regular branch
    dut.executor_decoder_inst <= int('eafffffa', 16) # b 0x68 (relative to 0x78)
    pc_init = 20
    dut.executor_pc <= pc_init + executor_pc_offset
    await clkedge
    # We need to wait a little since the values just became available
    # at the last clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert not dut.executor_update_Rd.value.integer
    assert dut.executor_flush_for_pc.value.integer
    assert dut.executor_update_pc.value.integer
    assert_eq(dut.executor_new_pc, pc_init + (0x68 - 0x78))

    # Test branch with link
    dut.executor_decoder_inst <= int('ebfffffb', 16) # bl 0x68 (relative to 0x74)
    pc_init = 16
    dut.executor_pc <= pc_init + executor_pc_offset
    await clkedge
    # We need to wait a little since the values just became available
    # at the last clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert dut.executor_update_Rd.value.integer
    assert dut.executor_flush_for_pc.value.integer
    assert dut.executor_databranch_Rd_value == pc_init + 4
    assert dut.executor_update_pc.value.integer
    assert_eq(dut.executor_new_pc, pc_init + (0x68 - 0x74))

    # Reset dut to initial state
    dut.executor_enable.setimmediatevalue(0)
Exemple #14
0
async def test_regfile_read(dut):
    """Test regfile reads"""

    clkedge = init_posedge_clk(dut.regfile_clk)
    regfile_init = read_regfile_init()

    # Reset
    dut.regfile_nreset <= 0
    await clkedge
    dut.regfile_nreset <= 1
    await clkedge
    dut._log.debug('Reset complete')

    # Test reads
    # NOTE: All regfile reads are clocked, so we set immediates here and then
    # wait for clkedge
    dut.regfile_read_inst.setimmediatevalue(int('e1540005', 16))  # cmp r4, r5
    dut.regfile_read_addr1.setimmediatevalue(4)  # r4
    dut.regfile_read_addr2.setimmediatevalue(5)  # r5

    await clkedge
    # Wait a little bit after clkedge to check immediate values
    await Timer(1, 'us')

    assert dut.regfile_read_value1 == regfile_init[4]
    assert dut.regfile_read_value2 == regfile_init[5]
    # Test new instruction right away
    dut.regfile_read_inst.setimmediatevalue(int('e08fe004',
                                                16))  # add lr, pc, r4
    dut.regfile_read_addr1.setimmediatevalue(15)  # pc
    dut.regfile_read_addr2.setimmediatevalue(4)  # r4

    await clkedge
    # Wait a little bit after clkedge to check immediate values
    await Timer(1, 'us')

    # PC should be read directly out, which is zero
    assert dut.regfile_read_value1 == 0
    assert dut.regfile_read_value2 == regfile_init[4]
Exemple #15
0
async def test_cpu(dut):
    """Run cpu normally and process debug port outputs"""

    clkedge = init_posedge_clk(dut.cpu_clk)

    # Reset CPU
    dut.cpu_nreset <= 0
    await clkedge
    dut.cpu_nreset <= 1
    await clkedge
    dut._log.debug('Reset complete')

    with open('cpu/init/code.hex') as code_file:
        num_instructions = len(code_file.read().splitlines())

    print("===========BEGIN PARSED DEBUG PORT OUTPUT===========")
    for cycle_count in range(num_instructions + PIPELINE_PADDING):
        dut._log.debug(f'Running CPU cycle {cycle_count}')
        debug_port_bytes = dut.cpu_debug_port_vector.value.integer.to_bytes(
            DEBUG_BYTES, 'big')
        parse_cycle_output(cycle_count, debug_port_bytes)
        await clkedge
    print("===========END PARSED DEBUG PORT OUTPUT===========")
Exemple #16
0
async def test_decoder_disable(dut):
    """Test if decoder persists outputs when disabled"""

    clkedge = init_posedge_clk(dut.decoder_clk)

    # Need to add PC offset when setting decoder_pc due to pipelining
    decoder_pc_offset = 8

    # Reset and enable
    dut.decoder_nreset <= 0
    await clkedge
    dut.decoder_nreset <= 1
    dut.decoder_enable <= 1

    initial_inputs = {
        dut.decoder_fetcher_inst: 0xe79842a9,  # ldr r4, [r8, r9, lsr #5]
        dut.decoder_regfile_read_value1: 0xdeadbeef,
        dut.decoder_regfile_read_value2: 0xbeefdead,
    }
    # Inputs that need to be scrambled later since they're updated after ready
    # is asserted
    delay_scramble = {
        dut.decoder_regfile_read_value1,
        dut.decoder_regfile_read_value2,
    }
    expected_outputs = {
        dut.decoder_decoder_inst: initial_inputs[dut.decoder_fetcher_inst],
        dut.decoder_stall_for_ldr: 0,
        dut.decoder_regfile_read_inst:
        initial_inputs[dut.decoder_fetcher_inst],
        dut.decoder_regfile_read_addr1: 8,  # r8
        dut.decoder_regfile_read_addr2: 9,  # r9
        dut.decoder_Rn_value: initial_inputs[dut.decoder_regfile_read_value1],
        dut.decoder_Rd_Rm_value:
        initial_inputs[dut.decoder_regfile_read_value2],
    }

    def _check_expected():
        for signal, value in expected_outputs.items():
            try:
                assert_eq(signal, value)
            except AssertionError as exc:
                raise AssertionError(
                    'Failed expected value on signal {} with error: {}'.format(
                        signal._name, str(exc)))

    # Set initial inputs
    for signal, value in initial_inputs.items():
        signal <= value

    await clkedge
    await Timer(1, 'us')
    assert dut.decoder_ready.value.integer
    # Check expected_outputs
    _check_expected()

    # Disable module
    dut.decoder_enable <= 0

    # Scramble inputs
    for signal in initial_inputs:
        if signal not in delay_scramble:
            signal <= 1  # set to non-zero to not conflate with Verilator's default value
    await clkedge
    await Timer(1, 'us')
    assert not dut.decoder_ready.value.integer
    # Check expected outputs
    _check_expected()

    # Scramble inputs that need a delay to take effect
    for signal in delay_scramble:
        signal <= 1
    await clkedge
    await Timer(1, 'us')
    assert not dut.decoder_ready.value.integer
    # Check expected outputs
    _check_expected()
Exemple #17
0
async def test_executor_disable(dut):
    """Test if executor persists outputs when disabled"""

    clkedge = init_posedge_clk(dut.executor_clk)

    # Need to add PC offset when setting executor_pc due to pipelining
    executor_pc_offset = 8

    # Reset and enable
    dut.executor_nreset <= 0
    await clkedge
    dut.executor_nreset <= 1

    async def _test_disable(initial_inputs, expected_outputs, delay_scramble=tuple()):
        def _check_expected():
            for signal, value in expected_outputs.items():
                try:
                    assert_eq(signal, value)
                except AssertionError as exc:
                    raise AssertionError(
                        'Failed expected value on signal {} with error: {}'.format(
                            signal._name, str(exc)
                        )
                    )

        # Enable module
        dut.executor_enable <= 1

        # Set initial inputs
        for signal, value in initial_inputs.items():
            signal <= value

        await clkedge
        await Timer(1, 'us')
        assert dut.executor_ready.value.integer
        # Check expected_outputs
        _check_expected()

        # Disable module
        dut.executor_enable <= 0

        # Scramble inputs
        for signal in initial_inputs:
            if signal not in delay_scramble:
                signal <= 1 # set to non-zero to not conflate with Verilator's default value
        await clkedge
        await Timer(1, 'us')
        assert not dut.executor_ready.value.integer
        # Check expected outputs
        _check_expected()

        if delay_scramble:
            # Scramble inputs that need a delay to take effect
            for signal in delay_scramble:
                signal <= 1
            await clkedge
            await Timer(1, 'us')
            assert not dut.executor_ready.value.integer
            # Check expected outputs
            _check_expected()

    Rn_value = 4 # r8
    Rd_Rm_value = 0b1100000 # r9, final value after LSR #5 should be 3
    initial_inputs = {
        dut.executor_pc: 64,
        dut.executor_decoder_inst: 0xe79842a9, # ldr r4, [r8, r9, lsr #5]
        dut.executor_decoder_Rn_value: Rn_value,
        dut.executor_decoder_Rd_Rm_value: Rd_Rm_value,
        dut.executor_memaccessor_fwd_has_Rd: False,
        # Should be unused values
        dut.executor_memaccessor_fwd_Rd_addr: 5,
        dut.executor_memaccessor_fwd_Rd_value: 0xdedebeef,
    }
    # Inputs that need to be scrambled later since they're updated after ready
    # is asserted
    delay_scramble = set()
    expected_outputs = {
        dut.executor_cpsr: 0b0000,
        dut.executor_condition_passes: True,
        dut.executor_executor_inst: initial_inputs[dut.executor_decoder_inst],
        dut.executor_update_pc: False,
        dut.executor_update_Rd: True,
        dut.executor_flush_for_pc: False,
        dut.executor_mem_read_addr: Rn_value+(Rd_Rm_value>>5),
        dut.executor_mem_write_enable: False,
    }
    await _test_disable(
        initial_inputs, expected_outputs, delay_scramble=delay_scramble)

    Rd_Rm_value_unused = 0xdeadbeef # r4, should not be used in STR below
    Rd_Rm_value = 0xbabafafa # r4
    initial_inputs = {
        dut.executor_pc: 64,
        dut.executor_decoder_inst: 0xe1a05004, # mov r5, r4
        dut.executor_decoder_Rn_value: 42, # unused
        dut.executor_decoder_Rd_Rm_value: Rd_Rm_value_unused,
        dut.executor_memaccessor_fwd_has_Rd: True,
        dut.executor_memaccessor_fwd_Rd_addr: 4, # r4
        dut.executor_memaccessor_fwd_Rd_value: Rd_Rm_value,
    }
    delay_scramble = set()
    expected_outputs = {
        dut.executor_cpsr: 0b0000,
        dut.executor_condition_passes: True,
        dut.executor_executor_inst: initial_inputs[dut.executor_decoder_inst],
        dut.executor_update_pc: False,
        dut.executor_update_Rd: True,
        dut.executor_databranch_Rd_value: Rd_Rm_value,
        dut.executor_flush_for_pc: False,
        dut.executor_mem_write_enable: False,
    }
    await _test_disable(
        initial_inputs, expected_outputs, delay_scramble=delay_scramble)

    # Test branch with link
    # Need to add PC offset when setting executor_pc due to pipelining
    executor_pc_offset = 8
    pc_init = 16
    initial_inputs = {
        dut.executor_pc: pc_init + executor_pc_offset,
        dut.executor_decoder_inst: 0xebfffffb, # bl 0x68 (relative to 0x74)
        # Unused values
        dut.executor_decoder_Rn_value: 42,
        dut.executor_decoder_Rd_Rm_value: 0xbeef,
        dut.executor_memaccessor_fwd_has_Rd: True,
        dut.executor_memaccessor_fwd_Rd_addr: 4,
        dut.executor_memaccessor_fwd_Rd_value: 0xdead,
    }
    delay_scramble = set()
    expected_outputs = {
        dut.executor_cpsr: 0b0000,
        dut.executor_condition_passes: True,
        dut.executor_executor_inst: initial_inputs[dut.executor_decoder_inst],
        dut.executor_update_pc: True,
        dut.executor_new_pc: pc_init + (0x68 - 0x74),
        dut.executor_update_Rd: True,
        dut.executor_databranch_Rd_value: pc_init + 4,
        dut.executor_flush_for_pc: True,
        dut.executor_mem_write_enable: False,
    }
    await _test_disable(
        initial_inputs, expected_outputs, delay_scramble=delay_scramble)
Exemple #18
0
async def test_executor_memaccessor_forward(dut):
    """Test executor's data forwarding from memaccessor"""

    clkedge = init_posedge_clk(dut.executor_clk)

    # Need to add PC offset when setting executor_pc due to pipelining
    executor_pc_offset = 8

    # Reset and enable
    dut.executor_nreset <= 0
    await clkedge
    dut.executor_nreset <= 1
    dut.executor_enable <= 1

    # Steps:
    # 1. Override r4 value in "mov r5, r4"
    # 2. Use executor forwarding to move r5 value from "mov r5, r4" to "str r5, [r8]"

    Rd_Rm_value_unused = 0xdeadbeef # r4, should not be used in STR below
    Rd_Rm_value = 0xbabafafa # r4

    dut.executor_decoder_inst <= 0xe1a05004 # mov r5, r4
    dut.executor_decoder_Rn_value <= 42 # unused
    dut.executor_decoder_Rd_Rm_value <= Rd_Rm_value_unused
    dut.executor_memaccessor_fwd_has_Rd <= 1
    dut.executor_memaccessor_fwd_Rd_addr <= 4 # r4
    dut.executor_memaccessor_fwd_Rd_value <= Rd_Rm_value
    await clkedge
    # We need to wait a little since the values just became available
    # at the last clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert dut.executor_update_Rd.value.integer
    assert not dut.executor_flush_for_pc.value.integer
    assert_eq(dut.executor_databranch_Rd_value, Rd_Rm_value)
    assert not dut.executor_update_pc.value.integer

    dut.executor_decoder_inst <= 0xe5885000 # str r5, [r8]
    Rn_value = 1 # r8
    dut.executor_decoder_Rn_value <= Rn_value
    dut.executor_decoder_Rd_Rm_value <= Rd_Rm_value_unused
    await clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert not dut.executor_update_Rd.value.integer
    assert not dut.executor_flush_for_pc.value.integer
    assert not dut.executor_update_pc.value.integer
    assert dut.executor_mem_write_enable.value.integer
    assert_eq(dut.executor_mem_write_value, Rd_Rm_value)

    # Repeat same as above, but replace STR with "mov r4, r5"

    dut.executor_decoder_inst <= 0xe1a05004 # mov r5, r4
    dut.executor_decoder_Rn_value <= 42 # unused
    dut.executor_decoder_Rd_Rm_value <= Rd_Rm_value_unused
    dut.executor_memaccessor_fwd_has_Rd <= 1
    dut.executor_memaccessor_fwd_Rd_addr <= 4 # r4
    dut.executor_memaccessor_fwd_Rd_value <= Rd_Rm_value
    await clkedge
    # We need to wait a little since the values just became available
    # at the last clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert dut.executor_update_Rd.value.integer
    assert not dut.executor_flush_for_pc.value.integer
    assert_eq(dut.executor_databranch_Rd_value, Rd_Rm_value)
    assert not dut.executor_update_pc.value.integer

    dut.executor_decoder_inst <= 0xe1a04005 # mov r4, r5
    dut.executor_decoder_Rn_value <= 42 # unused
    dut.executor_decoder_Rd_Rm_value <= Rd_Rm_value_unused
    await clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert dut.executor_update_Rd.value.integer
    assert not dut.executor_flush_for_pc.value.integer
    assert not dut.executor_update_pc.value.integer
    assert not dut.executor_mem_write_enable.value.integer
    assert_eq(dut.executor_databranch_Rd_value, Rd_Rm_value)
Exemple #19
0
async def test_executor_executor_forward(dut):
    """Test executor's data forwarding to itself"""

    clkedge = init_posedge_clk(dut.executor_clk)

    # Need to add PC offset when setting executor_pc due to pipelining
    executor_pc_offset = 8

    # Reset and enable
    dut.executor_nreset <= 0
    await clkedge
    dut.executor_nreset <= 1
    dut.executor_enable <= 1

    Rd_Rm_value = 0xdeadbeef # r4

    # Try mov, then str (memory forwarding)

    dut.executor_decoder_inst <= 0xe1a05004 # mov r5, r4
    dut.executor_decoder_Rn_value <= 42 # unused
    dut.executor_decoder_Rd_Rm_value <= Rd_Rm_value
    await clkedge
    # We need to wait a little since the values just became available
    # at the last clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert dut.executor_update_Rd.value.integer
    assert not dut.executor_flush_for_pc.value.integer
    assert_eq(dut.executor_databranch_Rd_value, Rd_Rm_value)
    assert not dut.executor_update_pc.value.integer

    dut.executor_decoder_inst <= 0xe5885000 # str r5, [r8]
    Rd_Rm_value_unused = 0xbabafafa # r5, should not be used
    Rn_value = 1 # r8
    dut.executor_decoder_Rn_value <= Rn_value
    dut.executor_decoder_Rd_Rm_value <= Rd_Rm_value_unused
    await clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert not dut.executor_update_Rd.value.integer
    assert not dut.executor_flush_for_pc.value.integer
    assert not dut.executor_update_pc.value.integer
    assert dut.executor_mem_write_enable.value.integer
    assert_eq(dut.executor_mem_write_value, Rd_Rm_value)

    # Try mov r5, r4, then mov r4, r5 (data forwarding)

    dut.executor_decoder_inst <= 0xe1a05004 # mov r5, r4
    dut.executor_decoder_Rn_value <= 42 # unused
    dut.executor_decoder_Rd_Rm_value <= Rd_Rm_value
    await clkedge
    # We need to wait a little since the values just became available
    # at the last clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert dut.executor_update_Rd.value.integer
    assert not dut.executor_flush_for_pc.value.integer
    assert_eq(dut.executor_databranch_Rd_value, Rd_Rm_value)
    assert not dut.executor_update_pc.value.integer

    dut.executor_decoder_inst <= 0xe1a04005 # mov r4, r5
    Rd_Rm_value_unused = 0xbabafafa # r5, should not be used
    dut.executor_decoder_Rn_value <= 42 # unused
    dut.executor_decoder_Rd_Rm_value <= Rd_Rm_value_unused
    await clkedge
    await Timer(1, 'us')
    assert dut.executor_ready.value.integer
    assert dut.executor_update_Rd.value.integer
    assert not dut.executor_flush_for_pc.value.integer
    assert not dut.executor_update_pc.value.integer
    assert not dut.executor_mem_write_enable.value.integer
    assert_eq(dut.executor_databranch_Rd_value, Rd_Rm_value)
Exemple #20
0
async def test_decoder_regfile(dut):
    """Test decoder regfile addresses"""

    clkedge = init_posedge_clk(dut.decoder_clk)

    # Reset and enable
    dut.decoder_nreset <= 0
    await clkedge
    dut.decoder_nreset.setimmediatevalue(1)
    dut.decoder_enable.setimmediatevalue(1)

    # Test data inst
    dut.decoder_fetcher_inst.setimmediatevalue(int('e0864007',
                                                   16))  # add r4, r6, r7
    # Make immediates take effect
    await Timer(1, 'us')
    assert dut.decoder_regfile_read_addr1 == 6
    assert dut.decoder_regfile_read_addr2 == 7

    # Test memory inst
    dut.decoder_fetcher_inst.setimmediatevalue(int(
        'e79842a9', 16))  # ldr r4, [r8, r9, lsr #5]
    # Make immediates take effect
    await Timer(1, 'us')
    assert dut.decoder_regfile_read_addr1 == 8
    assert dut.decoder_regfile_read_addr2 == 9

    # Test PC read
    dut.decoder_fetcher_inst.setimmediatevalue(int('e08fe004',
                                                   16))  # add lr, pc, r4
    # Make immediates take effect
    await Timer(1, 'us')
    assert dut.decoder_regfile_read_addr1 == 15  # pc
    assert dut.decoder_regfile_read_addr2 == 4  # r4
    # Test that PC is not modified since Rn is PC
    # Need to await clkedge to simulate regfile read
    await clkedge
    dut.decoder_regfile_read_value1.setimmediatevalue(42)
    dut.decoder_regfile_read_value2.setimmediatevalue(24)
    # Make immediates take effect
    await Timer(1, 'us')
    assert dut.decoder_Rn_value == 42
    assert dut.decoder_Rd_Rm_value == 24

    # Test PC read with fix for operand2 pc value
    dut.decoder_fetcher_inst.setimmediatevalue(int('e084e00f',
                                                   16))  # add lr, r4, pc
    # Make immediates take effect
    await Timer(1, 'us')
    assert dut.decoder_regfile_read_addr1 == 4  # r4
    assert dut.decoder_regfile_read_addr2 == 15  # pc
    # Test that PC is not modified since Rn is PC
    # Need to await clkedge to simulate regfile read
    await clkedge
    dut.decoder_regfile_read_value1.setimmediatevalue(24)
    dut.decoder_regfile_read_value2.setimmediatevalue(42)  # orig_pc + 8
    # Make immediates take effect
    await Timer(1, 'us')
    assert dut.decoder_Rn_value == 24
    assert dut.decoder_Rd_Rm_value == 42 + 4  # orig_pc + 12 = (orig_pc + 8) + 4

    # Reset dut to initial state
    dut.decoder_enable.setimmediatevalue(0)