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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [bench/] [sysc/] [src/] [JtagDriverSC.cpp] - Blame information for rev 862

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

Line No. Rev Author Line
1 63 julius
// ----------------------------------------------------------------------------
2
 
3
// SystemC JTAG driver
4
 
5
// Copyright (C) 2008  Embecosm Limited <info@embecosm.com>
6
 
7
// Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8
 
9
// This file is part of the cycle accurate model of the OpenRISC 1000 based
10
// system-on-chip, ORPSoC, built using Verilator.
11
 
12
// This program is free software: you can redistribute it and/or modify it
13
// under the terms of the GNU Lesser General Public License as published by
14
// the Free Software Foundation, either version 3 of the License, or (at your
15
// option) any later version.
16
 
17
// This program is distributed in the hope that it will be useful, but WITHOUT
18
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
20
// License for more details.
21
 
22
// You should have received a copy of the GNU Lesser General Public License
23
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
 
25
// ----------------------------------------------------------------------------
26
 
27
// $Id: JtagDriverSC.cpp 317 2009-02-22 19:52:12Z jeremy $
28
 
29
#include <iostream>
30
#include <iomanip>
31
 
32
#include "JtagDriverSC.h"
33
 
34 462 julius
SC_HAS_PROCESS(JtagDriverSC);
35 63 julius
 
36
//! Constructor for the JTAG driver.
37
 
38
//! We create a SC_THREAD in which we can spit out some actions. Must be a
39
//! thread, since we need to wait for the actions to complete.
40
 
41
//! @param[in] name             Name of this module, passed to the parent
42
//!                             constructor. 
43
//! @param[in] _tapActionQueue  Pointer to fifo of actions to perform
44
 
45 462 julius
JtagDriverSC::JtagDriverSC(sc_core::sc_module_name name, sc_core::sc_fifo < TapAction * >*_tapActionQueue):
46
sc_module(name),
47
tapActionQueue(_tapActionQueue), currentScanChain(OR1K_SC_UNDEF)
48 63 julius
{
49 462 julius
        SC_THREAD(queueActions);
50 63 julius
 
51 462 julius
}                               // JtagDriverSC ()
52 63 julius
 
53
//! SystemC thread to queue some actions
54
 
55
//! Have to use a thread, since we will end up waiting for actions to
56
//! complete.
57
 
58 462 julius
void JtagDriverSC::queueActions()
59 63 julius
{
60 462 julius
        uint32_t res;           // General result variable
61 63 julius
 
62 462 julius
        // Reset the JTAG
63
        reset();
64 63 julius
 
65 462 julius
        // Select the register scan chain to stall the processor, stall the
66
        // processor and check it has stalled
67
        selectChain(OR1K_SC_REGISTER);
68
        writeReg(OR1K_RSC_RISCOP, RISCOP_STALL);
69 63 julius
 
70 462 julius
        do {
71
                res = readReg(OR1K_RSC_RISCOP);
72
                std::cout << sc_core::sc_time_stamp().to_seconds() * 1000000
73
                    << "us: RISCOP = " << std::hex << res << std::endl;
74
        }
75
        while ((res & RISCOP_STALL) != RISCOP_STALL);
76 63 julius
 
77 462 julius
        // Write the NPC SPR. Select the RISC_DEBUG scan chain, read the
78
        // register, write the register and read it back.
79
        selectChain(OR1K_SC_RISC_DEBUG);
80 63 julius
 
81 462 julius
        res = readReg(0x10);    // NPC
82
        std::cout << sc_core::sc_time_stamp().to_seconds() * 1000000
83 63 julius
            << "us: Old NPC = " << std::hex << res << std::endl;
84
 
85 462 julius
        writeReg(0x10, 0x4000100);
86 63 julius
 
87 462 julius
        res = readReg(0x10);    // NPC
88
        std::cout << sc_core::sc_time_stamp().to_seconds() * 1000000
89 63 julius
            << "us: New NPC = " << std::hex << res << std::endl;
90
 
91 462 julius
        // Unstall and check it has unstalled
92
        selectChain(OR1K_SC_REGISTER);
93
        writeReg(OR1K_RSC_RISCOP, 0);
94 63 julius
 
95 462 julius
        do {
96
                res = readReg(OR1K_RSC_RISCOP);
97
                std::cout << sc_core::sc_time_stamp().to_seconds() * 1000000
98
                    << "us: RISCOP = " << std::hex << res << std::endl;
99
        }
100
        while ((res & RISCOP_STALL) == RISCOP_STALL);
101 63 julius
 
102 462 julius
}                               // queueActions ()
103 63 julius
 
104
//! Reset the JTAG
105
 
106
//! @note Must be called from a SystemC thread, because of the use of wait()
107
 
108 462 julius
void JtagDriverSC::reset()
109 63 julius
{
110 462 julius
        sc_core::sc_event * actionDone = new sc_core::sc_event();
111
        TapActionReset *resetAction;
112 63 julius
 
113 462 julius
        // Create and queue the reset action and wait for it to complete
114
        resetAction = new TapActionReset(actionDone);
115
        tapActionQueue->write(resetAction);
116
        wait(*actionDone);
117 63 julius
 
118 462 julius
        delete resetAction;
119
        delete actionDone;
120 63 julius
 
121 462 julius
}                               // reset ()
122 63 julius
 
123
//! Select an OpenRISC 1000 scan chain
124
 
125
//! Built on top of the JTAG commands to shift registers
126
//! We only do something if the scan chain needs to be changed.
127
//! - Shift-IR the CHAIN_SELECT instruction
128
//! - Shift-DR the specified chain
129
//! - Shift-IR the DEBUG instruction
130
 
131
//! @note Must be called from a SystemC thread, because of the use of wait()
132
 
133
//! @param[in] chain  The desired scan chain
134
 
135 462 julius
void JtagDriverSC::selectChain(int chain)
136 63 julius
{
137 462 julius
        if (chain == currentScanChain) {
138
                return;
139
        } else {
140
                currentScanChain = chain;
141
        }
142 63 julius
 
143 462 julius
        sc_core::sc_event * actionDone = new sc_core::sc_event();
144
        TapActionIRScan *iRScan;
145
        TapActionDRScan *dRScan;
146 63 julius
 
147 462 julius
        // Create and queue the IR-Scan action for CHAIN_SELECT (no CRC)
148
        iRScan = new TapActionIRScan(actionDone, CHAIN_SELECT_IR, JTAG_IR_LEN);
149
        tapActionQueue->write(iRScan);
150
        wait(*actionDone);
151 63 julius
 
152 462 julius
        delete iRScan;
153 63 julius
 
154 462 julius
        // Create and queue the DR-Scan action for the specified chain (which we
155
        // know will fit into 64 bits)
156
        uint64_t chainReg = crc8(chain, CHAIN_DR_LEN) << (CHAIN_DR_LEN) | chain;
157
        dRScan =
158
            new TapActionDRScan(actionDone, chainReg, CHAIN_DR_LEN + CRC_LEN);
159
        tapActionQueue->write(dRScan);
160
        wait(*actionDone);
161 63 julius
 
162 462 julius
        delete dRScan;
163 63 julius
 
164 462 julius
        // Create and queue the IR-Scan action for DEBUG (no CRC)
165
        iRScan = new TapActionIRScan(actionDone, DEBUG_IR, JTAG_IR_LEN);
166
        tapActionQueue->write(iRScan);
167
        wait(*actionDone);
168 63 julius
 
169 462 julius
        delete iRScan;
170
        delete actionDone;
171 63 julius
 
172 462 julius
}                               // selectChain()
173 63 julius
 
174
//! Read an OpenRISC 1000 JTAG register
175
 
176
//! Built on top of the JTAG commands to shift registers
177
//! - Shift-DR the specified address with R/W field unset
178
//! - read out the data shifted out.
179
 
180
//! DR register fields depend on the scan chain in use. For SC_REGISTER:
181
//! -   [4:0] Address to read from
182
//! -     [5] 0 indicating read
183
//! -  [37:6] Unused
184
//! - [45:38] CRC (CRC-8-ATM)
185
 
186
//! For SC_RISC_DEBUG (i.e. SPRs) and SC_WISHBONE:
187
//! -  [31:0] Address to read from
188
//! -    [32] 0 indicating read
189
//! - [64:33] unused
190
//! - [72:65] CRC (CRC-8-ATM)
191
 
192
//! In general two Scan-DR loops are needed. The first will cause the value
193
//! associated with the address to be loaded into the shift register, the
194
//! second will actually shift that value out. So we use a subsidiary call to
195
//! do the read (::readReg1()). This allows a future extension, where a block
196
//! of registers are read efficiently by overlapping ScanDR actions.
197
 
198
//! We can also provide a variant of ::readReg1 () that is optimized for
199
//! "small" value.
200
 
201
//! @note Must be called from a SystemC thread, because of the use of wait()
202
 
203
//! @param[in] addr  The address of the register
204
 
205
//! @return  The register value read
206
 
207 462 julius
uint32_t JtagDriverSC::readReg(uint32_t addr)
208 63 julius
{
209 462 julius
        bool firstTime = true;
210
        int bitSizeNoCrc;       // Size of reg w/o its CRC field
211 63 julius
 
212 462 julius
        // Determine the size of register to read.
213
        switch (currentScanChain) {
214
        case OR1K_SC_RISC_DEBUG:
215
                bitSizeNoCrc = RISC_DEBUG_DR_LEN;
216
                break;
217 63 julius
 
218 462 julius
        case OR1K_SC_REGISTER:
219
                bitSizeNoCrc = REGISTER_DR_LEN;
220
                break;
221 63 julius
 
222 462 julius
        case OR1K_SC_WISHBONE:
223
                bitSizeNoCrc = WISHBONE_DR_LEN;
224
                break;
225
        }
226 63 julius
 
227 462 julius
        // Read the register twice. Use an optimized version if the register is
228
        // "small".
229
        if ((bitSizeNoCrc + CRC_LEN) < 64) {
230
                (void)readReg1(addr, bitSizeNoCrc);
231
                return readReg1(addr, bitSizeNoCrc);
232
        } else {
233
                uint64_t *dReg =
234
                    new uint64_t[(bitSizeNoCrc + CRC_LEN + 63) / 64];
235
                (void)readReg1(dReg, addr, bitSizeNoCrc);
236
                uint32_t res = readReg1(dReg, addr, bitSizeNoCrc);
237
                delete[]dReg;
238
 
239
                return res;
240
        }
241
}                               // readReg ()
242
 
243 63 julius
//! Single read of an OpenRISC 1000 JTAG register
244
 
245
//! Built on top of the JTAG commands to shift registers
246
//! - Shift-DR the specified address with R/W field unset
247
//! - read out the data shifted out.
248
 
249
//! This version is for "small" values represented as a uint64_t.
250
 
251
//! @note Must be called from a SystemC thread, because of the use of wait()
252
 
253
//! @param[in]     addr          The address to read
254
//! @param[in]     bitSizeNoCrc  Size of the register excluding its CRC field
255
 
256
//! @return  The register value read
257
 
258 462 julius
uint32_t JtagDriverSC::readReg1(uint32_t addr, int bitSizeNoCrc)
259 63 julius
{
260 462 julius
        // Useful fields and sizes and the register itself
261
        int fullBitSize = bitSizeNoCrc + CRC_LEN;
262
        int dataOffset = bitSizeNoCrc - DR_DATA_LEN;
263
        uint64_t dReg;
264 63 julius
 
265 462 julius
        // Allocate space for the shifted reg and a SystemC completion event
266
        sc_core::sc_event * actionDone = new sc_core::sc_event();
267 63 julius
 
268 462 julius
        // Loop until CRCs match
269
        while (true) {
270
                // Create the data to shift in
271
                dReg = 0ULL;
272
                dReg |= addr;
273
                uint8_t crc_in = crc8(dReg, bitSizeNoCrc);
274
                dReg |= (uint64_t) crc_in << bitSizeNoCrc;
275 63 julius
 
276 462 julius
                // Prepare the action, queue it and wait for it to complete
277
                TapActionDRScan *dRScan = new TapActionDRScan(actionDone, dReg,
278
                                                              fullBitSize);
279
                tapActionQueue->write(dRScan);
280
                wait(*actionDone);
281
                dReg = dRScan->getDRegOut();
282
                delete dRScan;
283 63 julius
 
284 462 julius
                // Check CRCs
285
                uint8_t crc_out = dReg >> bitSizeNoCrc;
286
                uint8_t crc_calc = crc8(dReg, bitSizeNoCrc);
287 63 julius
 
288 462 julius
                // All done if CRC matches
289
                if (crc_out == crc_calc) {
290
                        delete actionDone;
291
                        return (dReg >> dataOffset) & ((1ULL << DR_DATA_LEN) -
292
                                                       1);
293
                }
294 63 julius
        }
295 462 julius
}                               // readReg1 ()
296 63 julius
 
297
//! Single read of an OpenRISC 1000 JTAG register
298
 
299
//! Built on top of the JTAG commands to shift registers
300
//! - Shift-DR the specified address with R/W field unset
301
//! - read out the data shifted out.
302
 
303
//! This version is for "large" values represented as an array of uint64_t.
304
 
305
//! @note Must be called from a SystemC thread, because of the use of wait()
306
 
307
//! @param[in,out] dRegArray     The shift register to use
308
//! @param[in]     addr          The address to read
309
//! @param[in]     bitSizeNoCrc  Size of the register excluding its CRC field
310
 
311
//! @return  The register value read
312
 
313
uint32_t
314 462 julius
    JtagDriverSC::readReg1(uint64_t * dRegArray,
315
                           uint32_t addr, int bitSizeNoCrc)
316 63 julius
{
317 462 julius
        // Useful fields and sizes
318
        int fullBitSize = bitSizeNoCrc + CRC_LEN;
319
        int dataOffset = bitSizeNoCrc - DR_DATA_LEN;
320 63 julius
 
321 462 julius
        // Allocate a SystemC completion event
322
        sc_core::sc_event * actionDone = new sc_core::sc_event();
323 63 julius
 
324 462 julius
        // Loop until CRCs match
325
        while (true) {
326
                // Create the data to shift in
327
                memset(dRegArray, 0, fullBitSize / 8);
328
                dRegArray[0] |= addr;
329
                uint8_t crc_in = crc8(dRegArray, bitSizeNoCrc);
330
                insertBits(crc_in, CRC_LEN, dRegArray, bitSizeNoCrc);
331 63 julius
 
332 462 julius
                // Prepare the action, queue it and wait for it to complete
333
                TapActionDRScan *dRScan =
334
                    new TapActionDRScan(actionDone, dRegArray,
335
                                        fullBitSize);
336
                tapActionQueue->write(dRScan);
337
                wait(*actionDone);
338
                dRScan->getDRegOut(dRegArray);
339
                delete dRScan;
340 63 julius
 
341 462 julius
                // Check CRCs
342
                uint8_t crc_out = extractBits(dRegArray, bitSizeNoCrc, CRC_LEN);
343
                uint8_t crc_calc = crc8(dRegArray, bitSizeNoCrc);
344 63 julius
 
345 462 julius
                // All done if CRC matches
346
                if (crc_out == crc_calc) {
347
                        delete actionDone;
348
                        return extractBits(dRegArray, dataOffset, DR_DATA_LEN);
349
                }
350 63 julius
        }
351 462 julius
}                               // readReg1 ()
352 63 julius
 
353
//! Write an OpenRISC 1000 JTAG register
354
 
355
//! Built on top of the JTAG commands to shift registers
356
//! - Shift-DR the specified address with R/W field set and data to write
357
 
358
//! DR register fields depend on the scan chain in use. For SC_REGISTER:
359
//! -   [4:0] Address to write to
360
//! -     [5] 1 indicating write
361
//! -  [37:6] Value to write
362
//! - [45:38] CRC (CRC-8-ATM)
363
 
364
//! For SC_RISC_DEBUG (i.e. SPRs) and SC_WISHBONE:
365
//! -  [31:0] Address to write to
366
//! -    [32] 1 indicating write
367
//! - [64:33] Value to write
368
//! - [72:65] CRC (CRC-8-ATM)
369
 
370
//! @note Must be called from a SystemC thread, because of the use of wait()
371
 
372
//! @param[in] addr  The address of the register
373
//! @param[in] data  The register data to write
374
 
375
void
376 462 julius
 JtagDriverSC::writeReg(uint32_t addr, uint32_t data)
377 63 julius
{
378 462 julius
        int bitSizeNoCrc;       // Size of reg w/o its CRC field
379
        uint64_t writeBit;      // Mask for the write enable bit
380 63 julius
 
381 462 julius
        // Determine the size of register to write.
382
        switch (currentScanChain) {
383
        case OR1K_SC_RISC_DEBUG:
384
                bitSizeNoCrc = RISC_DEBUG_DR_LEN;
385
                writeBit = RISC_DEBUG_RW;
386
                break;
387 63 julius
 
388 462 julius
        case OR1K_SC_REGISTER:
389
                bitSizeNoCrc = REGISTER_DR_LEN;
390
                writeBit = REGISTER_RW;
391
                break;
392 63 julius
 
393 462 julius
        case OR1K_SC_WISHBONE:
394
                bitSizeNoCrc = WISHBONE_DR_LEN;
395
                writeBit = WISHBONE_RW;
396
                break;
397
        }
398 63 julius
 
399 462 julius
        // Create the register in an array
400
        int wordSize = (bitSizeNoCrc + CRC_LEN + 63) / 64;
401
        uint64_t *dReg = new uint64_t[wordSize];
402 63 julius
 
403 462 julius
        // Create the data to shift in
404
        memset(dReg, 0, wordSize * 8);
405
        dReg[0] |= writeBit | addr;
406
        insertBits(data, DR_DATA_LEN, dReg, bitSizeNoCrc - DR_DATA_LEN);
407
        insertBits(crc8(dReg, bitSizeNoCrc), CRC_LEN, dReg, bitSizeNoCrc);
408 63 julius
 
409 462 julius
        // Prepare the action, queue it and wait for it to complete
410
        sc_core::sc_event * actionDone = new sc_core::sc_event();
411
        TapActionDRScan *dRScan = new TapActionDRScan(actionDone, dReg,
412
                                                      bitSizeNoCrc + CRC_LEN);
413 63 julius
 
414 462 julius
        tapActionQueue->write(dRScan);
415
        wait(*actionDone);
416 63 julius
 
417 462 julius
        delete[]dReg;
418
        delete dRScan;
419
        delete actionDone;
420 63 julius
 
421 462 julius
}                               // writeReg ()
422 63 julius
 
423
//! Compute CRC-8-ATM
424
 
425
//! The data is in a uint64_t, for which we use the first size bits to compute
426
//! the CRC.
427
 
428
//! @Note I am using the same algorithm as the ORPSoC debug unit, but I
429
//!       believe its function is broken! I don't believe the data bit should
430
//!       feature in the computation of bits 2 & 1 of the new CRC.
431
 
432
//! @Note I've realized that this is an algorithm for LSB first, so maybe it
433
//!       is correct!
434
 
435
//! @param data  The data whose CRC is desired
436
//! @param size  The number of bits in the data
437
 
438 462 julius
uint8_t JtagDriverSC::crc8(uint64_t data, int size)
439 63 julius
{
440 462 julius
        uint8_t crc = 0;
441 63 julius
 
442 462 julius
        for (int i = 0; i < size; i++) {
443
                uint8_t d = data & 1;   // Latest data bit
444
                data >>= 1;
445 63 julius
 
446 462 julius
                uint8_t oldCrc7 = (crc >> 7) & 1;
447
                uint8_t oldCrc1 = (crc >> 1) & 1;
448
                uint8_t oldCrc0 = (crc >> 0) & 1;
449
                uint8_t newCrc2 = d ^ oldCrc1 ^ oldCrc7;        // Why d?
450
                uint8_t newCrc1 = d ^ oldCrc0 ^ oldCrc7;        // Why d?
451
                uint8_t newCrc0 = d ^ oldCrc7;
452 63 julius
 
453 462 julius
                crc =
454
                    ((crc << 1) & 0xf8) | (newCrc2 << 2) | (newCrc1 << 1) |
455
                    newCrc0;
456
        }
457 63 julius
 
458 462 julius
        return crc;
459 63 julius
 
460 462 julius
}                               // crc8 ()
461 63 julius
 
462
//! Compute CRC-8-ATM
463
 
464
//! The data is in an array of uint64_t, for which we use the first size bits
465
//! to compute the CRC.
466
 
467
//! @Note I am using the same algorithm as the ORPSoC debug unit, but I
468
//!       believe its function is broken! I don't believe the data bit should
469
//!       feature in the computation of bits 2 & 1 of the new CRC.
470
 
471
//! @Note I've realized that this is an algorithm for LSB first, so maybe it
472
//!       is correct!
473
 
474
//! @param dataArray  The array of data whose CRC is desired
475
//! @param size       The number of bits in the data
476
 
477 462 julius
uint8_t JtagDriverSC::crc8(uint64_t dataArray[], int size)
478 63 julius
{
479 462 julius
        uint8_t crc = 0;
480 63 julius
 
481 462 julius
        for (int i = 0; i < size; i++) {
482
                uint8_t d = (dataArray[i / 64] >> (i % 64)) & 1;
483
                uint8_t oldCrc7 = (crc >> 7) & 1;
484
                uint8_t oldCrc1 = (crc >> 1) & 1;
485
                uint8_t oldCrc0 = (crc >> 0) & 1;
486
                uint8_t newCrc2 = d ^ oldCrc1 ^ oldCrc7;        // Why d?
487
                uint8_t newCrc1 = d ^ oldCrc0 ^ oldCrc7;        // Why d?
488
                uint8_t newCrc0 = d ^ oldCrc7;
489 63 julius
 
490 462 julius
                crc =
491
                    ((crc << 1) & 0xf8) | (newCrc2 << 2) | (newCrc1 << 1) |
492
                    newCrc0;
493
        }
494 63 julius
 
495 462 julius
        return crc;
496 63 julius
 
497 462 julius
}                               // crc8 ()
498 63 julius
 
499
//! Utility to insert a string of bits into array
500
 
501
//! This is a simple overwriting
502
 
503
//! @param  str       Bits to insert
504
//! @param  strLen    Number of bits to insert
505
//! @param  array     Array into which to insert
506
//! @param  startBit  Offset at which to insert bits
507
 
508 462 julius
void JtagDriverSC::insertBits(uint64_t str,
509
                              int strLen, uint64_t * array, int startBit)
510 63 julius
{
511 462 julius
        int startWord = startBit / 64;
512
        int endWord = (startBit + strLen - 1) / 64;
513 63 julius
 
514 462 julius
        startBit = startBit % 64;
515 63 julius
 
516 462 julius
        // Deal with the startWord. Get enough bits for the mask and put them in the
517
        // right place
518
        uint64_t startMask = ((1ULL << strLen) - 1ULL) << startBit;
519 63 julius
 
520 462 julius
        array[startWord] &= ~startMask;
521
        array[startWord] |= str << startBit;
522 63 julius
 
523 462 julius
        // If we were all in one word, we can give up now.
524
        if (startWord == endWord) {
525
                return;
526
        }
527
        // Deal with the endWord. Get enough bits for the mask. No need to shift
528
        // these up - they're always at the bottom of the word
529
        int bitsToDo = (startBit + strLen) % 64;
530 63 julius
 
531 462 julius
        uint64_t endMask = (1ULL << bitsToDo) - 1ULL;
532 63 julius
 
533 462 julius
        array[endWord] &= ~endMask;
534
        array[endWord] |= str >> (strLen - bitsToDo);
535 63 julius
 
536 462 julius
}                               // insertBits()
537 63 julius
 
538
//! Utility to extract a string of bits from an array
539
 
540
//! @param  array     Array from which to extract
541
//! @param  startBit  Offset at which to extract bits
542
//! @param  strLen    Number of bits to extract
543
 
544
//! @return  Extracted bits
545
 
546 462 julius
uint64_t JtagDriverSC::extractBits(uint64_t * array, int startBit, int strLen)
547 63 julius
{
548 462 julius
        int startWord = startBit / 64;
549
        int endWord = (startBit + strLen - 1) / 64;
550 63 julius
 
551 462 julius
        startBit = startBit % 64;
552 63 julius
 
553 462 julius
        // Deal with the startWord. Get enough bits for the mask and put them in the
554
        // right place
555
        uint64_t startMask = ((1ULL << strLen) - 1ULL) << startBit;
556
        uint64_t res = (array[startWord] & startMask) >> startBit;
557 63 julius
 
558 462 julius
        // If we were all in one word, we can give up now.
559
        if (startWord == endWord) {
560
                return res;
561
        }
562
        // Deal with the endWord. Get enough bits for the mask. No need to shift
563
        // these up - they're always at the bottom of the word
564
        int bitsToDo = (startBit + strLen) % 64;
565
        uint64_t endMask = (1ULL << bitsToDo) - 1ULL;
566 63 julius
 
567 462 julius
        return res | ((array[endWord] & endMask) << (strLen - bitsToDo));
568 63 julius
 
569 462 julius
}                               // extractBits ()

powered by: WebSVN 2.1.0

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