OpenCores
URL https://opencores.org/ocsvn/s80186/s80186/trunk

Subversion Repositories s80186

[/] [s80186/] [trunk/] [tests/] [rtl/] [TestModRMDecode.cpp] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jamieiles
// Copyright Jamie Iles, 2017
2
//
3
// This file is part of s80x86.
4
//
5
// s80x86 is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
//
10
// s80x86 is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
//
15
// You should have received a copy of the GNU General Public License
16
// along with s80x86.  If not, see <http://www.gnu.org/licenses/>.
17
 
18
#include <gtest/gtest.h>
19
#include <VModRMTestbench.h>
20
#include <deque>
21
#include <memory>
22
 
23
#include "VerilogTestbench.h"
24
#include "TestModRM.h"
25
#include "../common/TestModRM.cpp"
26
 
27
class RTLModRMDecoderTestbench : public VerilogTestbench<VModRMTestbench>,
28
                                 public ModRMDecoderTestBench
29
{
30
public:
31
    RTLModRMDecoderTestbench();
32
 
33
    void set_instruction(const std::vector<uint8_t> bytes)
34
    {
35
        stream.clear();
36
        stream.insert(stream.end(), bytes.begin(), bytes.end());
37
        stream.push_back(0x99);
38
        this->cycle();
39
    }
40
 
41
    void set_width(OperandWidth width)
42
    {
43
        is_8bit = width == OP_WIDTH_8;
44
    }
45
 
46
    void decode()
47
    {
48
        after_n_cycles(0, [&] {
49
            this->dut.start = 1;
50
            after_n_cycles(1, [&] { this->dut.start = 0; });
51
        });
52
 
53
        for (auto i = 0; i < 1000; ++i) {
54
            cycle();
55
            if (complete)
56
                return;
57
        }
58
 
59
        FAIL() << "failed to complete decode" << std::endl;
60
    }
61
 
62
    OperandType get_rm_type() const
63
    {
64
        return dut.rm_is_reg ? OP_REG : OP_MEM;
65
    }
66
 
67
    uint16_t get_effective_address() const
68
    {
69
        return dut.effective_address;
70
    }
71
 
72
    GPR get_register() const
73
    {
74
        return is_8bit ? static_cast<GPR>(dut.regnum + static_cast<int>(AL))
75
                       : static_cast<GPR>(dut.regnum);
76
    }
77
 
78
    GPR get_rm_register() const
79
    {
80
        return is_8bit ? static_cast<GPR>(dut.rm_regnum + static_cast<int>(AL))
81
                       : static_cast<GPR>(dut.rm_regnum);
82
    }
83
 
84
    bool is_complete() const
85
    {
86
        return complete;
87
    }
88
 
89
private:
90
    std::deque<uint8_t> stream;
91
    bool is_8bit;
92
    bool complete;
93
};
94
 
95
RTLModRMDecoderTestbench::RTLModRMDecoderTestbench()
96
    : is_8bit(false), complete(false)
97
{
98
    reset();
99
 
100
    dut.start = 0;
101
    dut.fifo_rd_en = 0;
102
 
103
    periodic(ClockSetup, [&] {
104
        this->dut.fifo_empty = this->stream.size() == 0;
105
 
106
        if (!this->dut.reset && this->dut.fifo_rd_en &&
107
            this->stream.size() == 0)
108
            FAIL() << "fifo underflow" << std::endl;
109
 
110
    });
111
 
112
    periodic(ClockCapture, [&] {
113
        this->complete = this->dut.complete;
114
 
115
        if (!this->dut.reset && this->dut.fifo_rd_en &&
116
            this->stream.size() > 0) {
117
            this->stream.pop_front();
118
        }
119
        after_n_cycles(1, [&] { this->dut.fifo_rd_data = this->stream[0]; });
120
    });
121
 
122
    periodic(ClockSetup, [&] {
123
        after_n_cycles(0, [&] {
124
            this->dut.regs[0] =
125
                regs.get(static_cast<GPR>(this->dut.reg_sel[0]));
126
            this->dut.regs[1] =
127
                regs.get(static_cast<GPR>(this->dut.reg_sel[1]));
128
        });
129
    });
130
}
131
 
132
typedef ::testing::Types<RTLModRMDecoderTestbench> ModRMImplTypes;
133
INSTANTIATE_TYPED_TEST_CASE_P(RTL, ModRMTestFixture, ModRMImplTypes);
134
 
135
class ModRMFixture : public RTLModRMDecoderTestbench, public ::testing::Test
136
{
137
};
138
 
139
TEST_F(ModRMFixture, BPBaseInfersSS)
140
{
141
    set_instruction({0x46, 0x00});
142
 
143
    decode();
144
 
145
    ASSERT_TRUE(dut.bp_as_base);
146
}
147
 
148
TEST_F(ModRMFixture, BXBaseDoesntInferSS)
149
{
150
    set_instruction({0x07});
151
 
152
    decode();
153
 
154
    ASSERT_FALSE(dut.bp_as_base);
155
}
156
 
157
TEST_F(ModRMFixture, EAHeld)
158
{
159
    regs.set(BX, 0x1234);
160
 
161
    set_instruction({0x07});
162
 
163
    decode();
164
 
165
    ASSERT_EQ(dut.effective_address, 0x1234);
166
    regs.set(BX, 0x0000);
167
    cycle();
168
    ASSERT_EQ(dut.effective_address, 0x1234);
169
}
170
 
171
TEST_F(ModRMFixture, BPAsBase)
172
{
173
    for (uint8_t mod = 0; mod < 4; ++mod) {
174
        for (uint8_t rm = 0; rm < 8; ++rm) {
175
            reset();
176
 
177
            set_instruction(
178
                {static_cast<uint8_t>((mod << 6) | rm), 0xff, 0xff});
179
            decode();
180
 
181
            if (mod == 0)
182
                EXPECT_TRUE(this->dut.bp_as_base == (rm == 2 || rm == 3));
183
            else if (mod == 1 || mod == 2)
184
                EXPECT_TRUE(this->dut.bp_as_base ==
185
                            (rm == 2 || rm == 3 || rm == 6));
186
            else
187
                EXPECT_FALSE(this->dut.bp_as_base);
188
        }
189
    }
190
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.