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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [cpu_sysc_plugin/] [riverlib/] [core/] [arith/] [int_div.cpp] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 sergeykhbr
/**
2
 * @file
3
 * @copyright  Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
5
 * @brief      Integer divider.
6
 */
7
 
8
#include "int_div.h"
9
#include "api_utils.h"
10
 
11
namespace debugger {
12
 
13
IntDiv::IntDiv(sc_module_name name_)
14
    : sc_module(name_) {
15
    SC_METHOD(comb);
16
    sensitive << i_nrst;
17
    sensitive << i_ena;
18
    sensitive << i_unsigned;
19
    sensitive << i_rv32;
20
    sensitive << i_residual;
21
    sensitive << i_a1;
22
    sensitive << i_a2;
23
    sensitive << r.result;
24
    sensitive << r.ena;
25
    sensitive << r.busy;
26
 
27
    SC_METHOD(registers);
28
    sensitive << i_clk.pos();
29
};
30
 
31
void IntDiv::generateVCD(sc_trace_file *i_vcd, sc_trace_file *o_vcd) {
32
#if 0
33
    sc_trace_file *t_vcd = sc_create_vcd_trace_file("intdiv");
34
    t_vcd->set_time_unit(1, SC_PS);
35
    sc_trace(t_vcd, i_clk, "i_clk");
36
    sc_trace(t_vcd, i_nrst, "i_nrst");
37
    sc_trace(t_vcd, i_ena, "i_ena");
38
    sc_trace(t_vcd, i_unsigned, "i_unsigned");
39
    sc_trace(t_vcd, i_rv32, "i_rv32");
40
    sc_trace(t_vcd, i_residual, "i_residual");
41
    sc_trace(t_vcd, i_a1, "i_a1");
42
    sc_trace(t_vcd, i_a2, "i_a2");
43
#endif
44
    if (o_vcd) {
45
        sc_trace(o_vcd, i_ena, "/top/proc0/exec0/div0/i_ena");
46
        sc_trace(o_vcd, o_res, "/top/proc0/exec0/div0/o_res");
47
        sc_trace(o_vcd, o_valid, "/top/proc0/exec0/div0/o_valid");
48
        sc_trace(o_vcd, r.ena, "/top/proc0/exec0/div0/r_ena");
49
        sc_trace(o_vcd, r.busy, "/top/proc0/exec0/div0/r_busy");
50
        sc_trace(o_vcd, r.qr, "/top/proc0/exec0/div0/r_qr");
51
        sc_trace(o_vcd, r.invert, "/top/proc0/exec0/div0/r_invert");
52
        sc_trace(o_vcd, r.rv32, "/top/proc0/exec0/div0/r_rv32");
53
        sc_trace(o_vcd, r.resid, "/top/proc0/exec0/div0/r_resid");
54
        sc_trace(o_vcd, r.reference_div, "/top/proc0/exec0/div0/r_reference_div");
55
        sc_trace(o_vcd, wb_qr1, "/top/proc0/exec0/div0/wb_qr1");
56
        sc_trace(o_vcd, wb_qr2, "/top/proc0/exec0/div0/wb_qr2");
57
    }
58
}
59
 
60
void IntDiv::comb() {
61
    sc_uint<64> wb_a1;
62
    sc_uint<64> wb_a2;
63
    sc_biguint<65> wb_divident = 0;
64
    sc_biguint<65> wb_divider = 0;
65
    bool w_invert64;
66
    bool w_invert32;
67
    v = r;
68
 
69
    w_invert32 = 0;
70
    w_invert64 = 0;
71
    wb_divident[64] = 0;
72
    wb_divider[64] = 0;
73
 
74
    if (i_rv32.read()) {
75
        wb_a1(63, 32) = 0;
76
        wb_a2(63, 32) = 0;
77
        if (i_unsigned.read() || i_a1.read()[31] == 0) {
78
            wb_a1(31, 0) = i_a1.read()(31, 0);
79
        } else {
80
            wb_a1(31, 0) = (~i_a1.read()(31, 0)) + 1;
81
        }
82
        if (i_unsigned.read() || i_a2.read()[31] == 0) {
83
            wb_a2(31, 0) = i_a2.read()(31, 0);
84
        } else {
85
            wb_a2(31, 0) = (~i_a2.read()(31, 0)) + 1;
86
        }
87
    } else {
88
        if (i_unsigned.read() || i_a1.read()[63] == 0) {
89
            wb_a1(63, 0) = i_a1.read();
90
        } else {
91
            wb_a1(63, 0) = (~i_a1.read()) + 1;
92
        }
93
        if (i_unsigned.read() || i_a2.read()[63] == 0) {
94
            wb_a2(63, 0) = i_a2.read();
95
        } else {
96
            wb_a2(63, 0) = (~i_a2.read()) + 1;
97
        }
98
    }
99
 
100
    wb_divident(63, 0) = wb_a1;
101
    wb_divider(63, 0) = wb_a2;
102
 
103
 
104
    v.ena = (r.ena.read() << 1) | (i_ena & !r.busy);
105
 
106
    // Level 2*i of 64:
107
    wb_diff1 = r.qr(127, 63) - r.divider;
108
    if (wb_diff1[64]) {
109
        wb_qr1 = r.qr << 1;
110
    } else {
111
        wb_qr1 = (wb_diff1(63, 0), r.qr(62, 0), 1);
112
    }
113
 
114
    // Level 2*i + 1 of 64:
115
    wb_diff2 = wb_qr1(127, 63) - r.divider;
116
    if (wb_diff2[64]) {
117
        wb_qr2 = wb_qr1 << 1;
118
    } else {
119
        wb_qr2 = (wb_diff2(63, 0), wb_qr1(62, 0), 1);
120
    }
121
 
122
 
123
    if (i_ena.read()) {
124
        v.qr(127, 65) = 0;
125
        v.qr(64, 0) = wb_divident;
126
        v.divider = wb_divider;
127
        v.busy = 1;
128
        v.rv32 = i_rv32;
129
        v.resid = i_residual;
130
 
131
        w_invert32 = !i_unsigned.read() &&
132
                ((!i_residual.read() && (i_a1.read()[31] ^ i_a2.read()[31]))
133
                || (i_residual.read() && i_a1.read()[31]));
134
        w_invert64 = !i_unsigned.read() &&
135
                ((!i_residual.read() && (i_a1.read()[63] ^ i_a2.read()[63]))
136
                || (i_residual.read() && i_a1.read()[63]));
137
        v.invert = (!i_rv32.read() && w_invert64)
138
                || (i_rv32.read() && w_invert32);
139
 
140
        v.a1_dbg = i_a1;
141
        v.a2_dbg = i_a2;
142
        v.reference_div = compute_reference(i_unsigned.read(), i_rv32.read(),
143
                                     i_residual.read(),
144
                                     i_a1.read(), i_a2.read());
145
    } else if (r.ena.read()[32]) {
146
        v.busy = 0;
147
        if (r.resid.read()) {
148
            if (r.invert.read()) {
149
                v.result = ~v.qr(127, 64).to_uint64() + 1;
150
            } else {
151
                v.result = v.qr(127, 64).to_uint64();
152
            }
153
        } else {
154
            if (r.invert.read()) {
155
                v.result = ~v.qr(63, 0).to_uint64() + 1;
156
            } else {
157
                v.result = v.qr(63, 0).to_uint64();
158
            }
159
        }
160
    } else if (r.busy.read()) {
161
        v.qr = wb_qr2;
162
    }
163
 
164
    if (i_nrst.read() == 0) {
165
        v.result = 0;
166
        v.ena = 0;
167
        v.busy = 0;
168
        v.rv32 = 0;
169
        v.invert = 0;
170
        v.qr = 0;
171
        v.resid = 0;
172
    }
173
 
174
    o_res = r.result;
175
    o_valid = r.ena.read()[33];
176
    o_busy = r.busy;
177
}
178
 
179
void IntDiv::registers() {
180
    // Debug purpose only"
181
    if (v.ena.read()[33]) {
182
        uint64_t t1 = v.result.read()(63,0).to_uint64();
183
        uint64_t t2 = r.reference_div.to_uint64();
184
        if (t1 != t2) {
185
            char tstr[512];
186
            RISCV_sprintf(tstr, sizeof(tstr),
187
                "IntDiv error: rv32=%d, resid=%d, invert=%d, "
188
                "(%016" RV_PRI64 "x/%016" RV_PRI64 "x) => "
189
                "%016" RV_PRI64 "x != %016" RV_PRI64 "x\n",
190
                r.rv32.read(), r.resid.read(), r.invert.read(),
191
                r.a1_dbg.to_uint64(), r.a2_dbg.to_uint64(), t1, t2);
192
            cout << tstr;
193
            cout.flush();
194
        }
195
    }
196
 
197
    r = v;
198
}
199
 
200
uint64_t IntDiv::compute_reference(bool unsign, bool rv32, bool resid,
201
                                   uint64_t a1, uint64_t a2) {
202
    uint64_t ret;
203
    if (a2 == 0) {
204
        ret = 0;
205
    } else if (rv32) {
206
        if (unsign) {
207
            if (resid) {
208
                ret = (uint32_t)a1 % (uint32_t)a2;
209
            } else {
210
                ret = (uint32_t)a1 / (uint32_t)a2;
211
            }
212
        } else {
213
            if (resid) {
214
                ret = (uint64_t)((int64_t)((int32_t)a1 % (int32_t)a2));
215
            } else {
216
                ret = (uint64_t)((int64_t)((int32_t)a1 / (int32_t)a2));
217
            }
218
        }
219
    } else {
220
        if (unsign) {
221
            if (resid) {
222
                ret = a1 % a2;
223
            } else {
224
                ret = a1 / a2;
225
            }
226
        } else {
227
            if (resid) {
228
                ret = (int64_t)a1 % (int64_t)a2;
229
            } else {
230
                ret = (int64_t)a1 / (int64_t)a2;
231
            }
232
        }
233
    }
234
    return ret;
235
}
236
 
237
}  // namespace debugger
238
 

powered by: WebSVN 2.1.0

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