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_mul.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 multiplier.
6
 * @details    Implemented algorithm provides 4 clocks per instruction
7
 */
8
 
9
#include "int_mul.h"
10
#include "api_utils.h"
11
 
12
namespace debugger {
13
 
14
IntMul::IntMul(sc_module_name name_) : 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_high;
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 IntMul::generateVCD(sc_trace_file *i_vcd, sc_trace_file *o_vcd) {
32
#if 0
33
    vcd = sc_create_vcd_trace_file("intmul");
34
    vcd->set_time_unit(1, SC_PS);
35
 
36
    sc_trace(vcd, i_clk, "i_clk");
37
    sc_trace(vcd, i_nrst, "i_nrst");
38
    sc_trace(vcd, i_ena, "i_ena");
39
    sc_trace(vcd, i_unsigned, "i_unsigned");
40
    sc_trace(vcd, i_rv32, "i_rv32");
41
    sc_trace(vcd, i_high, "i_high");
42
    sc_trace(vcd, i_a1, "i_a1");
43
    sc_trace(vcd, i_a2, "i_a2");
44
#endif
45
    if (o_vcd) {
46
        sc_trace(o_vcd, i_a1, "/top/proc0/exec0/mul0/i_a1");
47
        sc_trace(o_vcd, i_a2, "/top/proc0/exec0/mul0/i_a2");
48
        sc_trace(o_vcd, i_ena, "/top/proc0/exec0/mul0/i_ena");
49
        sc_trace(o_vcd, o_res, "/top/proc0/exec0/mul0/o_res");
50
        sc_trace(o_vcd, o_valid, "/top/proc0/exec0/mul0/o_valid");
51
        sc_trace(o_vcd, o_busy, "/top/proc0/exec0/mul0/o_busy");
52
        sc_trace(o_vcd, r.ena, "/top/proc0/exec0/mul0/r_ena");
53
    }
54
}
55
 
56
void IntMul::comb() {
57
    sc_uint<2> wb_mux_lvl0;
58
    Level0Type wb_lvl0;
59
    Level2Type wb_lvl2;
60
    Level4Type wb_lvl4;
61
    sc_biguint<128> wb_lvl5;
62
    sc_biguint<128> wb_res32;
63
    sc_uint<64> wb_res;
64
 
65
    v = r;
66
 
67
    v.ena = (r.ena.read() << 1) | (i_ena & !r.busy);
68
 
69
    if (i_ena.read()) {
70
        v.busy = 1;
71
        if (i_rv32.read()) {
72
            v.a1 = i_a1.read()(31, 0);
73
            if (!i_unsigned.read() && i_a1.read()[31]) {
74
                v.a1(63, 32) = ~0;
75
            }
76
            v.a2 = i_a2.read()(31, 0);
77
            if (!i_unsigned.read() && i_a2.read()[31]) {
78
                v.a2(63, 32) = ~0;
79
            }
80
        } else {
81
            v.a1 = i_a1;
82
            v.a2 = i_a2;
83
        }
84
        v.rv32 = i_rv32;
85
        v.unsign = i_unsigned;
86
        v.high = i_high;
87
 
88
        // Just for run-rime control (not for VHDL)
89
        v.a1_dbg = i_a1;
90
        v.a2_dbg = i_a2;
91
        v.reference_mul = compute_reference(i_unsigned.read(),
92
                                            i_rv32.read(),
93
                                            i_a1.read(),
94
                                            i_a2.read());
95
    }
96
 
97
    if (r.ena.read()[0]) {
98
        for (int i = 0; i < 32; i++) {
99
            wb_mux_lvl0 = r.a2(2*i + 1, 2*i);
100
            if (wb_mux_lvl0 == 0) {
101
                wb_lvl0.arr[i] = 0;
102
            } else if (wb_mux_lvl0 == 1) {
103
                wb_lvl0.arr[i] = sc_biguint<66>(r.a1);
104
            } else if (wb_mux_lvl0 == 2) {
105
                wb_lvl0.arr[i] = sc_biguint<66>(r.a1) << 1;
106
            } else {
107
                wb_lvl0.arr[i] = sc_biguint<66>(r.a1)
108
                              + (sc_biguint<66>(r.a1) << 1);
109
            }
110
        }
111
 
112
        for (int i = 0; i < 16; i++) {
113
            v.lvl1.arr[i] = (sc_biguint<69>(wb_lvl0.arr[2*i + 1]) << 2)
114
                          + sc_biguint<69>(wb_lvl0.arr[2*i]);
115
        }
116
    }
117
 
118
    if (r.ena.read()[1]) {
119
        for (int i = 0; i < 8; i++) {
120
            wb_lvl2.arr[i] = (sc_biguint<74>(r.lvl1.arr[2*i + 1]) << 4)
121
                       + sc_biguint<74>(r.lvl1.arr[2*i]);
122
        }
123
 
124
        for (int i = 0; i < 4; i++) {
125
            v.lvl3.arr[i] = (sc_biguint<83>(wb_lvl2.arr[2*i + 1]) << 8)
126
                          + sc_biguint<83>(wb_lvl2.arr[2*i]);
127
        }
128
    }
129
 
130
    if (r.ena.read()[2]) {
131
        v.busy = 0;
132
        for (int i = 0; i < 2; i++) {
133
            wb_lvl4.arr[i] = (sc_biguint<100>(r.lvl3.arr[2*i + 1]) << 16)
134
                           + sc_biguint<100>(r.lvl3.arr[2*i]);
135
        }
136
 
137
        wb_lvl5 = (sc_biguint<128>(wb_lvl4.arr[1]) << 32)
138
                        + sc_biguint<128>(wb_lvl4.arr[0]);
139
        if (r.rv32.read()) {
140
            wb_res32(31, 0) = wb_lvl5(31, 0);
141
            if (r.unsign.read() || wb_lvl5[31] == 0) {
142
                wb_res32(127, 32) = 0;
143
            } else {
144
                wb_res32(127, 32) = ~0;
145
            }
146
            v.result = wb_res32;
147
        } else {
148
            v.result = wb_lvl5;
149
        }
150
    }
151
 
152
    wb_res = r.result.read()(63, 0);
153
    if (r.high.read()) {
154
        wb_res = r.result.read()(127, 64);  // not tested yet
155
    }
156
 
157
    if (i_nrst.read() == 0) {
158
        v.busy = 0;
159
        v.result = 0;
160
        v.ena = 0;
161
        v.a1 = 0;
162
        v.a2 = 0;
163
        v.rv32 = 0;
164
        v.unsign = 0;
165
        v.high = 0;
166
        v.reference_mul = 0;
167
    }
168
 
169
    o_res = wb_res;
170
    o_valid = r.ena.read()[3];
171
    o_busy = r.busy;
172
}
173
 
174
void IntMul::registers() {
175
    // Debug purpose only"
176
    if (r.ena.read()[2]) {
177
        uint64_t t1 = v.result.read()(63,0).to_uint64();
178
        uint64_t t2 = r.reference_mul.to_uint64();
179
        if (t1 != t2) {
180
            char tstr[512];
181
            RISCV_sprintf(tstr, sizeof(tstr),
182
                "IntMul error: unsigned=%d, rv32=%d, high=%d,  "
183
                "(%016" RV_PRI64 "x/%016" RV_PRI64 "x) => "
184
                "%016" RV_PRI64 "x != %016" RV_PRI64 "x\n",
185
                r.unsign.read(), r.rv32.read(), r.high.read(),
186
                r.a1_dbg.to_uint64(), r.a2_dbg.to_uint64(), t1, t2);
187
            cout << tstr;
188
            cout.flush();
189
        }
190
    }
191
    r = v;
192
}
193
 
194
uint64_t IntMul::compute_reference(bool unsign, bool rv32, uint64_t a1, uint64_t a2) {
195
    uint64_t ret;
196
    if (rv32) {
197
        if (unsign) {
198
            ret = (uint32_t)a1 * (uint32_t)a2;
199
        } else {
200
            ret = (uint64_t)((int64_t)((int32_t)a1 * (int32_t)a2));
201
        }
202
    } else {
203
        // The results are the same but just for clearence
204
        if (unsign) {
205
            ret = a1 * a2;
206
        } else {
207
            ret = (int64_t)a1 * (int64_t)a2;
208
        }
209
    }
210
    return ret;
211
}
212
 
213
}  // namespace debugger
214
 

powered by: WebSVN 2.1.0

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