Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F19839919
bit_operations.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Size
12 KB
Referenced Files
None
Subscribers
None
bit_operations.hpp
View Options
/* kitty: C++ truth table library
* Copyright (C) 2017-2022 EPFL
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*!
\file bit_operations.hpp
\brief Implements bit manipulation on truth tables
\author Mathias Soeken
*/
#pragma once
#include
<cstdint>
#include
<cassert>
#include
<numeric>
#include
<algorithm>
#include
"static_truth_table.hpp"
#include
"ternary_truth_table.hpp"
#include
"quaternary_truth_table.hpp"
#include
"partial_truth_table.hpp"
#include
"detail/mscfix.hpp"
namespace
kitty
{
/*! \brief Sets bit at index to true
\param tt Truth table
\param index Bit index
*/
template
<
typename
TT
>
void
set_bit
(
TT
&
tt
,
uint64_t
index
)
{
tt
.
_bits
[
index
>>
6
]
|=
uint64_t
(
1
)
<<
(
index
&
0x3f
);
}
/*! \cond PRIVATE */
template
<
uint32_t
NumVars
>
void
set_bit
(
static_truth_table
<
NumVars
,
true
>&
tt
,
uint64_t
index
)
{
tt
.
_bits
|=
uint64_t
(
1
)
<<
index
;
}
template
<
typename
TT
>
void
set_bit
(
ternary_truth_table
<
TT
>&
tt
,
uint64_t
index
,
bool
value
=
true
)
{
set_bit
(
tt
.
_care
,
index
);
if
(
value
)
set_bit
(
tt
.
_bits
,
index
);
else
clear_bit
(
tt
.
_bits
,
index
);
}
template
<
typename
TT
>
void
set_bit
(
quaternary_truth_table
<
TT
>&
tt
,
uint64_t
index
,
bool
value
=
true
)
{
if
(
value
)
{
set_bit
(
tt
.
_onset
,
index
);
clear_bit
(
tt
.
_offset
,
index
);
}
else
{
clear_bit
(
tt
.
_onset
,
index
);
set_bit
(
tt
.
_offset
,
index
);
}
}
/*! \endcond */
/*! \brief Gets bit at index
\param tt Truth table
\param index Bit index
\return 1 if bit is set, otherwise 0
*/
template
<
typename
TT
>
auto
get_bit
(
const
TT
&
tt
,
uint64_t
index
)
{
return
(
tt
.
_bits
[
index
>>
6
]
>>
(
index
&
0x3f
)
)
&
0x1
;
}
/*! \cond PRIVATE */
template
<
uint32_t
NumVars
>
auto
get_bit
(
const
static_truth_table
<
NumVars
,
true
>&
tt
,
uint64_t
index
)
{
return
(
tt
.
_bits
>>
index
)
&
0x1
;
}
/*! \brief Gets bit at index
\param tt Ternary truth table
\param index Bit index
\return 1 if bit is set, 0 if it is reset or if it is a don't care
*/
template
<
typename
TT
>
auto
get_bit
(
const
ternary_truth_table
<
TT
>&
tt
,
uint64_t
index
)
{
return
get_bit
(
tt
.
_bits
,
index
);
}
/*! \brief Gets bit at index
\param tt Ternary truth table
\param index Bit index
\return 1 if bit is set, 0 if it is reset, if it is a don't care, or if it is a don't know
*/
template
<
typename
TT
>
auto
get_bit
(
const
quaternary_truth_table
<
TT
>&
tt
,
uint64_t
index
)
{
return
get_bit
(
tt
.
_onset
,
index
)
&&
!
get_bit
(
tt
.
_offset
,
index
);
}
/*! \endcond */
/*! \brief Clears bit at index (sets bit at index to false)
\param tt Truth table
\param index Bit index
*/
template
<
typename
TT
>
void
clear_bit
(
TT
&
tt
,
uint64_t
index
)
{
tt
.
_bits
[
index
>>
6
]
&=
~
(
uint64_t
(
1
)
<<
(
index
&
0x3f
)
);
}
/*! \cond PRIVATE */
template
<
uint32_t
NumVars
>
void
clear_bit
(
static_truth_table
<
NumVars
,
true
>&
tt
,
uint64_t
index
)
{
tt
.
_bits
&=
~
(
uint64_t
(
1
)
<<
index
);
}
/*! \endcond */
/*! \brief Flips bit at index
\param tt Truth table
\param index Bit index
*/
template
<
typename
TT
>
void
flip_bit
(
TT
&
tt
,
uint64_t
index
)
{
tt
.
_bits
[
index
>>
6
]
^=
uint64_t
(
1
)
<<
(
index
&
0x3f
);
}
template
<
typename
TT
>
void
flip_bit
(
ternary_truth_table
<
TT
>&
tt
,
uint64_t
index
)
{
if
(
!
get_bit
(
tt
.
_care
,
index
)
)
return
;
flip_bit
(
tt
.
_bits
,
index
);
}
/*! \cond PRIVATE */
template
<
uint32_t
NumVars
>
void
flip_bit
(
static_truth_table
<
NumVars
,
true
>&
tt
,
uint64_t
index
)
{
tt
.
_bits
^=
uint64_t
(
1
)
<<
index
;
}
/*! \brief Checks if a bit in a ternary truth table is a don't care
\param tt Ternary truth table
\param index Bit index
*/
template
<
typename
TT
>
bool
is_dont_care
(
const
ternary_truth_table
<
TT
>&
tt
,
uint64_t
index
)
{
return
!
get_bit
(
tt
.
_care
,
index
);
}
/*! \brief Checks if a bit in a quaternary truth table is a don't care
\param tt Quaternary truth table
\param index Bit index
*/
template
<
typename
TT
>
bool
is_dont_care
(
const
quaternary_truth_table
<
TT
>&
tt
,
uint64_t
index
)
{
return
get_bit
(
tt
.
_onset
,
index
)
&&
get_bit
(
tt
.
_offset
,
index
);
}
/*! \cond PRIVATE */
template
<
typename
TT
>
bool
is_dont_care
(
const
TT
&
tt
,
uint64_t
index
)
{
return
false
;
}
/*! \brief Sets a bit in a ternary truth table as a don't care
\param tt Ternary truth table
\param index Bit index
*/
template
<
typename
TT
>
void
set_dont_care
(
ternary_truth_table
<
TT
>&
tt
,
uint64_t
index
)
{
clear_bit
(
tt
.
_care
,
index
);
clear_bit
(
tt
.
_bits
,
index
);
}
/*! \brief Sets a bit in a quaternary truth table as a don't care
\param tt Ternary truth table
\param index Bit index
*/
template
<
typename
TT
>
void
set_dont_care
(
quaternary_truth_table
<
TT
>&
tt
,
uint64_t
index
)
{
set_bit
(
tt
.
_onset
,
index
);
set_bit
(
tt
.
_offset
,
index
);
}
/*! \brief Checks if a bit in a ternary truth table is a don't know
\param tt Ternary truth table
\param index Bit index
*/
template
<
typename
TT
>
bool
is_dont_know
(
const
ternary_truth_table
<
TT
>&
tt
,
uint64_t
index
)
{
return
!
get_bit
(
tt
.
_care
,
index
);
}
/*! \brief Checks if a bit in a quaternary truth table is a don't care
\param tt Ternary truth table
\param index Bit index
*/
template
<
typename
TT
>
bool
is_dont_know
(
const
quaternary_truth_table
<
TT
>&
tt
,
uint64_t
index
)
{
return
!
get_bit
(
tt
.
_onset
,
index
)
&&
!
get_bit
(
tt
.
_offset
,
index
);
}
/*! \cond PRIVATE */
template
<
typename
TT
>
bool
is_dont_know
(
const
TT
&
tt
,
uint64_t
index
)
{
return
false
;
}
template
<
typename
TT
>
void
set_dont_know
(
quaternary_truth_table
<
TT
>&
tt
,
uint64_t
index
)
{
clear_bit
(
tt
.
_onset
,
index
);
clear_bit
(
tt
.
_offset
,
index
);
}
/*! Returns a block of bits vector.
*/
template
<
typename
TT
>
uint64_t
get_block
(
const
TT
&
tt
,
uint64_t
block_index
)
{
return
tt
.
_bits
[
block_index
];
}
template
<
uint32_t
NumVars
>
uint64_t
get_block
(
const
static_truth_table
<
NumVars
,
true
>&
tt
,
uint64_t
block_index
)
{
return
tt
.
_bits
;
}
/*! \brief Copies bit at index
Copy the bit from `tt_from` at index `index_from` to `tt_to` at index `index_to`.
\param tt_from Truth table to copy from
\param index_from Bit index to copy from
\param tt_to Truth table to write to
\param index_to Bit index to write to
*/
template
<
typename
TTfrom
,
typename
TTto
>
void
copy_bit
(
const
TTfrom
&
tt_from
,
uint64_t
index_from
,
TTto
&
tt_to
,
uint64_t
index_to
)
{
if
(
get_bit
(
tt_from
,
index_from
)
)
{
set_bit
(
tt_to
,
index_to
);
}
else
{
clear_bit
(
tt_to
,
index_to
);
}
}
/*! \brief Clears all bits
\param tt Truth table
*/
template
<
typename
TT
>
void
clear
(
TT
&
tt
)
{
std
::
fill
(
std
::
begin
(
tt
.
_bits
),
std
::
end
(
tt
.
_bits
),
0
);
}
/*! \cond PRIVATE */
template
<
uint32_t
NumVars
>
void
clear
(
static_truth_table
<
NumVars
,
true
>&
tt
)
{
tt
.
_bits
=
0
;
}
/*! \endcond */
/*! \brief Count ones in truth table
\param tt Truth table
*/
template
<
typename
TT
>
inline
uint64_t
count_ones
(
const
TT
&
tt
)
{
return
std
::
accumulate
(
tt
.
cbegin
(),
tt
.
cend
(),
uint64_t
(
0
),
[](
auto
accu
,
auto
word
)
{
return
accu
+
__builtin_popcount
(
word
&
0xffffffff
)
+
__builtin_popcount
(
word
>>
32
);
}
);
}
/*! \cond PRIVATE */
template
<
uint32_t
NumVars
>
inline
uint64_t
count_ones
(
const
static_truth_table
<
NumVars
,
true
>&
tt
)
{
return
__builtin_popcount
(
tt
.
_bits
&
0xffffffff
)
+
__builtin_popcount
(
tt
.
_bits
>>
32
);
}
/*! \endcond */
/*! \brief Count zeros in truth table
\param tt Truth table
*/
template
<
typename
TT
>
inline
uint64_t
count_zeros
(
const
TT
&
tt
)
{
return
count_ones
(
~
tt
);
}
/*! \cond PRIVATE */
inline
int64_t
find_first_bit_in_word
(
uint64_t
word
)
{
int64_t
n
=
0
;
if
(
word
==
0
)
{
return
-1
;
}
if
(
(
word
&
UINT64_C
(
0x00000000FFFFFFFF
)
)
==
0
)
{
n
+=
32
;
word
>>=
32
;
}
if
(
(
word
&
UINT64_C
(
0x000000000000FFFF
)
)
==
0
)
{
n
+=
16
;
word
>>=
16
;
}
if
(
(
word
&
UINT64_C
(
0x00000000000000FF
)
)
==
0
)
{
n
+=
8
;
word
>>=
8
;
}
if
(
(
word
&
UINT64_C
(
0x000000000000000F
)
)
==
0
)
{
n
+=
4
;
word
>>=
4
;
}
if
(
(
word
&
UINT64_C
(
0x0000000000000003
)
)
==
0
)
{
n
+=
2
;
word
>>=
2
;
}
if
(
(
word
&
UINT64_C
(
0x0000000000000001
)
)
==
0
)
{
n
++
;
}
return
n
;
}
inline
int64_t
find_last_bit_in_word
(
uint64_t
word
)
{
int64_t
n
=
0
;
if
(
word
==
0
)
{
return
-1
;
}
if
(
(
word
&
UINT64_C
(
0xFFFFFFFF00000000
)
)
==
0
)
{
n
+=
32
;
word
<<=
32
;
}
if
(
(
word
&
UINT64_C
(
0xFFFF000000000000
)
)
==
0
)
{
n
+=
16
;
word
<<=
16
;
}
if
(
(
word
&
UINT64_C
(
0xFF00000000000000
)
)
==
0
)
{
n
+=
8
;
word
<<=
8
;
}
if
(
(
word
&
UINT64_C
(
0xF000000000000000
)
)
==
0
)
{
n
+=
4
;
word
<<=
4
;
}
if
(
(
word
&
UINT64_C
(
0xC000000000000000
)
)
==
0
)
{
n
+=
2
;
word
<<=
2
;
}
if
(
(
word
&
UINT64_C
(
0x8000000000000000
)
)
==
0
)
{
n
++
;
}
return
63
-
n
;
}
/*! \endcond */
/*! \brief Finds least-significant one-bit
Returns -1, if truth table is constant 0.
\param tt Truth table
\param start Bit to start from (default is 0)
*/
template
<
typename
TT
>
int64_t
find_first_one_bit
(
const
TT
&
tt
,
int64_t
start
=
0
)
{
uint64_t
mask
=
~
(
(
UINT64_C
(
1
)
<<
uint64_t
(
start
%
64
)
)
-
1u
);
auto
it
=
tt
.
cbegin
()
+
(
start
>>
6
);
if
(
it
!=
tt
.
cend
()
&&
(
*
it
&
mask
)
!=
0
)
{
return
64
*
std
::
distance
(
tt
.
cbegin
(),
it
)
+
find_first_bit_in_word
(
*
it
&
mask
);
}
else
if
(
it
==
tt
.
cend
()
)
{
return
-1
;
}
it
=
std
::
find_if
(
it
+
1
,
tt
.
cend
(),
[](
auto
word
)
{
return
word
!=
0
;
}
);
if
(
it
==
tt
.
cend
()
)
{
return
-1
;
}
return
64
*
std
::
distance
(
tt
.
cbegin
(),
it
)
+
find_first_bit_in_word
(
*
it
);
}
/*! \brief Finds most-significant one-bit
Returns -1, if truth table is constant 0.
\param tt Truth table
*/
template
<
typename
TT
>
int64_t
find_last_one_bit
(
const
TT
&
tt
)
{
const
auto
it
=
std
::
find_if
(
tt
.
crbegin
(),
tt
.
crend
(),
[](
auto
word
)
{
return
word
!=
0
;
}
);
if
(
it
==
tt
.
crend
()
)
{
return
-1
;
}
return
64
*
(
std
::
distance
(
it
,
tt
.
crend
()
)
-
1
)
+
find_last_bit_in_word
(
*
it
);
}
/*! \brief Finds least-significant bit difference
Returns -1, if truth tables are the same
\param first First truth table
\param second Second truth table
*/
template
<
typename
TT
>
int64_t
find_first_bit_difference
(
const
TT
&
first
,
const
TT
&
second
)
{
if
constexpr
(
std
::
is_same
<
TT
,
partial_truth_table
>::
value
)
{
assert
(
first
.
num_bits
()
==
second
.
num_bits
()
);
}
else
{
assert
(
first
.
num_vars
()
==
second
.
num_vars
()
);
}
auto
it
=
first
.
cbegin
();
auto
it2
=
second
.
cbegin
();
auto
w
=
0
;
while
(
it
!=
first
.
cend
()
)
{
if
(
*
it
^
*
it2
)
{
return
64
*
w
+
find_first_bit_in_word
(
*
it
^
*
it2
);
}
++
it
;
++
it2
;
++
w
;
}
return
-1
;
}
/*! \brief Finds most-significant bit difference
Returns -1, if truth tables are the same
\param first First truth table
\param second Second truth table
*/
template
<
typename
TT
>
int64_t
find_last_bit_difference
(
const
TT
&
first
,
const
TT
&
second
)
{
if
constexpr
(
std
::
is_same
<
TT
,
partial_truth_table
>::
value
)
{
assert
(
first
.
num_bits
()
==
second
.
num_bits
()
);
}
else
{
assert
(
first
.
num_vars
()
==
second
.
num_vars
()
);
}
auto
it
=
first
.
crbegin
();
auto
it2
=
second
.
crbegin
();
auto
w
=
first
.
num_blocks
()
-
1
;
while
(
it
!=
first
.
crend
()
)
{
if
(
*
it
^
*
it2
)
{
return
64
*
w
+
find_last_bit_in_word
(
*
it
^
*
it2
);
}
++
it
;
++
it2
;
--
w
;
}
return
-1
;
}
}
// namespace kitty
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sun, Jul 12, 6:56 PM (20 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
351914
Default Alt Text
bit_operations.hpp (12 KB)
Attached To
Mode
R272 SoC_NEM_Synthesis
Attached
Detach File
Event Timeline
Log In to Comment