* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: rz3_bitarray.v3.14b.h
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* ========== Copyright Header End ============================================
* utility code for rstzip3
* Copyright (C) 2003 Sun Microsystems, Inc.
#define rz3_bitarray_debug 0
// the rz3_bitarray is a space-efficient way to
// maintain lists of items whose size is not necessarily 8/16/32/64 bits.
// Access time is kept low by allocating a static array of size <maxsize_hint>.
// Exceeding this size involves memory reallocation() which may slow things down
// It is cheaper to specify a large maxsize_hint than to reallocate memory
enum consts_e
{ u64_per_line
= 128 };
// nbits is the size of the array element. Must be <= 64
rz3_bitarray(const char * arg_name
, int nbits
, int maxsize_hint
) {
fprintf(stderr
, "ERROR: rz3_bitarray: nbits cannot be > 64. Specified = %d\n", nbits
);
elems_per_line
= u64_per_line
*64/elemsize
;
elem_mask
= (~0ull) >> (64-elemsize
);
can_straddle
= ((64 % elemsize
) != 0);
nlines
= (maxsize_hint
+ elems_per_line
- 1)/elems_per_line
;
lines
= new uint64_t * [nlines
];
for (i
=0; i
<nlines
; i
++) {
for (i
=0; i
<nlines
; i
++) {
void Push(uint64_t data_nbits
) {
data_nbits
&= elem_mask
; // zero-out upper bits of local copy of input arg
if (rz3_bitarray_debug
) { printf("rz3_bitarray %s [%d] <= %llx\n", name
, count
, data_nbits
); fflush(stdout
); }
// printf("rz3_bitarray::Push: count %d data %llx\n", count, data_nbits);
int idx
= count
/ elems_per_line
;
nlines
= (nlines
+ 1) * 1.5;
uint64_t* * newlines
= new uint64_t* [nlines
];
for(i
=idx
; i
<nlines
; i
++) {
lines
[idx
] = new uint64_t[u64_per_line
];
int offset
= count
% elems_per_line
;
int u64_idx
= (offset
* elemsize
) >> 6;
int u64_offset
= (offset
* elemsize
) & 0x3f;
if (can_straddle
&& ((u64_offset
+ elemsize
) > 64)) {
int lbits
= (64-u64_offset
);
uint64_t lmask
= (1ull << lbits
) - 1;
uint64_t lowbits
= data_nbits
& lmask
;
lines
[idx
][u64_idx
] &= ~(lmask
<< u64_offset
);
lines
[idx
][u64_idx
] |= (lowbits
<< u64_offset
);
lines
[idx
][u64_idx
+1] = data_nbits
>> lbits
;
// printf(" lines[%d][%d] = %016llx, lines[%d][%d] = %016llx\n", idx, u64_idx, lines[idx][u64_idx], idx, u64_idx+1, lines[idx][u64_idx+1]);
lines
[idx
][u64_idx
] &= ~(elem_mask
<< u64_offset
); // zero out elem bits
lines
[idx
][u64_idx
] |= (data_nbits
<< u64_offset
);
// printf(" lines[%d][%d] = %016llx\n", idx, u64_idx, lines[idx][u64_idx]);
bool Get(int key
, uint64_t & value
) {
int idx
= key
/elems_per_line
;
int offset
= key
% elems_per_line
;
int u64_idx
= (offset
* elemsize
) >> 6;
int u64_offset
= (offset
* elemsize
) & 0x3f;
if (can_straddle
&& ((u64_offset
+elemsize
) > 64)) {
int lbits
= 64-u64_offset
;
value
= lines
[idx
][u64_idx
] >> u64_offset
;
int hbits
= (u64_offset
+elemsize
-64);
uint64_t hmask
= (1ull << hbits
) - 1;
uint64_t hval
= (lines
[idx
][u64_idx
+1] & hmask
);
value
|= (hval
<< lbits
);
value
= (lines
[idx
][u64_idx
] >> u64_offset
) & elem_mask
;
// GetNext() is a stateful function that returns elements in the order they were inserted
bool GetNext(uint64_t & value
)
bool rv
= Get(nextidx
, value
);
if (rz3_bitarray_debug
) { printf("rz3_bitarray %s [%d] <= %llx\n", name
, nextidx
, value
); fflush(stdout
); }
uint64_t ComputeMemBufSize(int n_elements
) {
uint64_t full_lines
= (n_elements
/elems_per_line
);
uint64_t partial_line_bits
= (n_elements
% elems_per_line
) * elemsize
;
uint64_t partial_line_u64_count
= (partial_line_bits
+ 63)/64;
return (full_lines
* u64_per_line
+ partial_line_u64_count
) * sizeof(uint64_t);
uint64_t GetMemBufSize() {
return ComputeMemBufSize(count
);
// returns number of bytes copied out - should be equal to SizeInBytes()
uint64_t CopyTo(unsigned char * membuf
) {
int full_lines
= (count
/elems_per_line
);
int partial_line_bits
= (count
% elems_per_line
) * elemsize
;
int partial_line_u64_count
= (partial_line_bits
+ 63)/64;
uint64_t bytes_copied
= 0;
int full_line_size
= u64_per_line
* sizeof(uint64_t);
for (i
=0; i
<full_lines
; i
++) {
memcpy(membuf
+bytes_copied
, lines
[i
], full_line_size
);
bytes_copied
+= full_line_size
;
memcpy(membuf
+bytes_copied
, lines
[i
], partial_line_u64_count
*sizeof(uint64_t));
bytes_copied
+= (partial_line_u64_count
* sizeof(uint64_t));
// returns number of bytes copied in - should be equal to GetMemBufSIze()
uint64_t CopyFrom(unsigned char * membuf
, int arg_count
) {
int full_lines
= (count
/elems_per_line
);
int partial_line_bits
= (count
% elems_per_line
) * elemsize
;
int partial_line_u64_count
= (partial_line_bits
+ 63)/64;
// do we have enough lines available?
int lines_needed
= full_lines
;
if (partial_line_u64_count
) {
if (lines_needed
> nlines
) {
// allocate more line pointers. 1.5X current count or needed count, whichever larger
int new_nlines
= (nlines
+1)*1.5;
if (lines_needed
> new_nlines
) {
new_nlines
= lines_needed
;
uint64_t ** newlines
= new uint64_t * [new_nlines
];
// copy over <nlines> pointers>
memcpy(newlines
, lines
, nlines
* sizeof(uint64_t *));
// zero pointers past nlines
bzero(newlines
+nlines
, (new_nlines
-nlines
)*sizeof(uint64_t *));
uint64_t bytes_copied
= 0;
for (i
=0; i
<full_lines
; i
++) {
lines
[i
] = new uint64_t [u64_per_line
];
int nbytes
= u64_per_line
*sizeof(uint64_t);
memcpy(lines
[i
], membuf
+bytes_copied
, nbytes
);
if (partial_line_u64_count
) {
lines
[i
] = new uint64_t [u64_per_line
];
int nbytes
= partial_line_u64_count
*sizeof(uint64_t);
memcpy(lines
[i
], membuf
+bytes_copied
, nbytes
);
uint64_t elem_mask
; // shift u64 then AND with this mask to extract element
uint64_t sum
; // useful for generating prediction efficiency stats for elemsize=1. (may also be useful in other situations)
#endif // _rz3_bitarray_h_