I'm fairly new to VHDL and trying to convert two given C macros to be executed as a single instruction on my FPGA. The macros are:
#define m_in_bits(buf, num) (buf) >> (24 - (num)) // buf is uint32_t
#define m_ext_bits(buf, i) ((buf) < (1<<((i)-1)) ? (buf) + (((-1)<<(i)) + 1) : (buf))
And the C code that uses the macros is:
m_ext_bits(m_in_bits(buffer, size), size);
I'm having issues with getting m_ext_bits to properly compile. Here's my VHDL:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity myEntity is
port(
signal buffer: in std_logic_vector(31 downto 0);
signal result: out std_logic_vector(31 downto 0)
);
end entity myEntity;
architecture myArch of myEntity is
signal size : signed (3 downto 0);
begin
size <= signed(buffer(27 downto 24));
result(15 downto 0) <= std_logic_vector(signed(buffer(23 downto 0)) srl (24 - to_integer(size))
+ signed((-1 sll to_integer(size)) + 1)); -- the offending line
end architecture myArch ;
The long line beginning with result(15 downto 0) <= actually compiles without error (that implements the m_in_bits macro). However, when I add the following line, beginning with the +, errors occur. I tried playing around with casting the std_logic_vector and signed types and the errors change.
type of expression is ambiguous - "SIGNED" or "UNSIGNED" are two possible matches...
can't determine definition of operator ""sll"" -- found 0 possible definitions...
illegal SIGNED in expression...
I think it's a matter of proper casting and using the correct types to fulfill the required operations.
First, buffer is a reserved VHDL word, so change that; using argbuf below.
The expression -1 sll to_integer(size) is not defined in VHDL, since the
integer value -1 is a numerical expression only with no bit representation
specified by VHDL, so shifting is not possible. Neither are operations like
bitwise and, or, etc. on integers. A -1 representation in 24-bit signed type can be created as:
to_signed(-1, 24)
There is a length issue with the assign, since 16-bit signal (result(15 downto
0)) is assigned with 24-bit value (based on right side argbuf(23 downto 0)).
The srl should then compile when the above is addressed.
Code as:
result(15 downto 0) <= std_logic_vector(resize((signed(argbuf(23 downto 0)) srl (24 - to_integer(size)))
+ signed((to_signed(-1, 24) sll to_integer(size)) + 1), 16));
However, the VHDL shift operators, e.g. srl, may give unexpected results, as
described in this page "Arithmetic and logical shifts and rotates are done with
functions in VHDL, not
operators",
so you may consider using the shift functions defined in numeric_std instead,
e.g. shift_right, as a general coding style. Code with functions as:
result(15 downto 0) <= std_logic_vector(resize(shift_right(signed(argbuf(23 downto 0)), 24 - to_integer(size))
+ signed(shift_left(to_signed(-1, 24), to_integer(size)) + 1), 16));
Related
I have a code piece that concatenates two variable length vectors and XORs the result with another fixed-length vector. The variable lengths of related vectors does not affect the total length of concatenation result. Here is the respected code
-- Find the number of bits to be skipped.
-- This is done for better optimization of hardware.
bits2MSB := 15 - findHighestIndex(m_xorResult);
-- If there are sufficient number of remaining bits in the extended data
-- Then we can continue the XOR operation
if(bits2MSB < remainingXorCount) then
m_xorResult <= (m_xorResult((15 - bits2MSB - 1) downto 0) & m_dataExtended(remainingXorCount downto (remainingXorCount - bits2MSB))) xor STD_LOGIC_VECTOR(to_unsigned(polynom, 16));
remainingXorCount := remainingXorCount - bits2MSB - 1; -- Decrease remainingXorCount
-- If the remaining bit count of the extended data is equal to the number of bits to be skipped until the first HIGH bit
-- Then the last XOR operation for given data can be made.
elsif(bits2MSB = remainingXorCount) then
m_xorResult <= (m_xorResult((14 - remainingXorCount) downto 0) & m_dataExtended(remainingXorCount downto 0)) xor STD_LOGIC_VECTOR(to_unsigned(polynom, 16));
remainingXorCount := remainingXorCount - bits2MSB;
state <= FINISH;
-- If the remaining bits are not sufficient for a new XOR operation
-- Then the result is equal to the extended version of the last XOR result.
else
m_xorResult <= (m_xorResult((14 - remainingXorCount) downto 0) & m_dataExtended(remainingXorCount downto 0));
remainingXorCount := 0; -- Decrease remainingXorCount
state <= FINISH;
end if;
The error message points to the line below the if statement. It says that
[Synth 8-509] operands of logical operator '^' have different lengths (40 vs. 16)
The declaration of related vectors are as following
variable bits2MSB : integer range 0 to 8 := 0;
variable remainingXorCount : integer range 0 to 7 := 7;
signal m_xorResult : STD_LOGIC_VECTOR(15 downto 0);
signal m_dataExtended : STD_LOGIC_VECTOR(23 downto 0);
variable polynom : natural := 16#1021#;
In addition to these, the function findHighestIndex(...) can return an integer value in range 7 to 15.
The testbench for the given module works without any problem. I tested it for any given input to the module. Somehow, Vivado says that in some condition I can produce a length of 40 bits vector and try to XOR it with a length of 16 bit vector. What do you think the problem is?
Instead of concatenating variable width words to make a fixed width word, you can OR two fixed width words together, each with a variable number of bits masked out.
In outline, instead of
X"AAAA"(15 downto var) & X"5555"(var-1 downto 0) XOR X"1234";
compute
((X"AAAA" AND upper_mask(var)) OR (X"5555" AND not upper_mask(var))) XOR X"1234";
The masks can be generated by functions like this;
function upper_mask(var : natural) return std_logic_vector is
mask : std_logic_vector(15 downto 0) := (others => '1');
begin
mask(var - 1 downto 0) := (others => '0');
return mask;
end;
If Vivado still can't synthesise upper_mask, a loop over all bits in upper_mask should work:
for i in mask'range loop
if i < var then
mask(i) := '0';
end if;
end loop
I'm trying to reimplement some of the coreutils for a project, and I'm seeing TYPE_MINIMUM(some int) a lot, however I can't see where it's defined or any usage for it. I'm not sure if it's something that's generated during make, or if it was intentional. Any ideas?
I have included all the headers that are required for the functions, and everything works up until the TYPE_MINIMUM is called for a validation.
Complete source for file being used: https://github.com/coreutils/coreutils/blob/master/src/who.c
static const char *idle_string (time_t when, time_t boottime)
{
static time_t now = TYPE_MINIMUM (time_t);
if (now == TYPE_MINIMUM (time_t))
time (&now);
if (boottime < when && now - 24 * 60 * 60 < when && when <= now)
{
int seconds_idle = now - when;
if (seconds_idle < 60)
return " . ";
else
{
static char idle_hhmm[IDLESTR_LEN];
/* FIXME-in-2018: see if this assert is still required in order
to suppress gcc's unwarranted -Wformat-length= warning. */
assert (seconds_idle / (60 * 60) < 24);
sprintf (idle_hhmm, "%02d:%02d",
seconds_idle / (60 * 60),
(seconds_idle % (60 * 60)) / 60);
return idle_hhmm;
}
}
return (" old ");
}
error: ‘TYPE_MINIMUM’ was not declared in this scope
An implementation of this macro can be found in the Coreutils "intprops.h" file.
From that file:
/* The maximum and minimum values for the integer type T. */
#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t))
#define TYPE_MAXIMUM(t) \
((t) (! TYPE_SIGNED (t) \
? (t) -1 \
: ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1)))
Where TYPE_WIDTH gives the size of a type in bits:
/* The width in bits of the integer type or expression T.
Do not evaluate T.
Padding bits are not supported; this is checked at compile-time below. */
#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT)
It gets the minimum of a type by taking the one's complement of the maximum of that type. It gets that maximum by either:
If it's unsigned, casting the value -1 to that type
If it's signed, adding one to twice the value obtained by subtracting one from the value obtained by setting the second-highest bit.
Although it's not really needed for your question, I want to go through that signed case. Let's take int16_t as an example.
If we handle that ternary and TYPE_WIDTH ahead of time, and ignore extra parentheses that ensure a little more safety TYPE_MAXIMUM(int16_t) expands to:
(int16_t) ((((int16_t) (1 << 14)) - 1) * 2 + 1)
Then:
(int16_t) ((((int16_t) 0x4000) - 1) * 2 + 1)
Then:
(int16_t) (((int16_t) 0x3FFF) * 2 + 1)
Then:
(int16_t) ((int16_t) 0x7FFE + 1)
Then:
(int16_t) ((int16_t) 0x7FFE + 1)
Which is:
(int16_t) 0x7FFF
TYPE_MAXIMUM is way to efficiently set all but the upper bit without relying on signed overflow, which yields undefined behaviour and must not be used.
This TYPE_MAXIMUM method does assume that any signed type given doesn't use a model where the maximum signed value is not represented by all but the highest bit being set.
A TYPE_MINIMUM(int16_t) would invert those bits to get (int16_t) 0x8000.
This TYPE_MINIMUM from a maximum value method assumes that any signed type given doesn't use sign-and-magnitude arithmetic, or any other model where the one's complement of a maximum held value is not the minimum value.
With these two restrictions on signed representations, the representations given in this table that will work with the TYPE_MINIMUM macro is one's complement and two's complement.
In practice, this will likely never be an issue, almost everything uses two's complement representations of signed integers.
We have defined a vector as
A: in std_logic_vector(7 downto 0);
when assigning a literal to this vector such as
A <= {'1', '0', '0', '1'};
will this expession populate the vector positions of 7,6,5 & 4 or positions of 3,2,1 & 0
The idea is a vector of bits which we can sign extend to an 8 bit integer but it will only currently work if the latter is true.
Invalid syntax here. If you want to keep the various bits as a list you can make the assignment:
A(3 downto 0) <= (3 => '1', 2=> '0', 1=> '0', 0=> '1') ;
Bonus sign extension:
A <= (2=> '0', 1=> '0', 0=> '1', others => '1') ;
I don't think this is legal - at least it isn't in Xilinx ISE.
The right way to do it would be to specify the part of A that you want to assign:
A(3 downto 0) <= "1001";
Why are you using individual bits as a numeric constant? Is there some reason you're not doing something like:
A <= std_logic_vector(to_signed(-7,A'length));
You can get rid of the std_logic_vector cast if you A is a signed type to start with, and you can use unsigned types and conversion functions if you don't want sign extension.
If you want sign extension, use the appropriate type signed.
Then you can convert a proper number (like -1) to a vector of the appropriate width using the to_signed function, for example:
to_signed (-1, a'length)
Advantages to doing this over explicit bit setting are:
simpler code
everyone can read it and understand what you are doing (no comments necessary!)
when a changes length, it all (still) Just Works
I am somewhat curious about creating a macro to generate a bit mask for a device register, up to 64bits. Such that BIT_MASK(31) produces 0xffffffff.
However, several C examples do not work as thought, as I get 0x7fffffff instead. It is as-if the compiler is assuming I want signed output, not unsigned. So I tried 32, and noticed that the value wraps back around to 0. This is because of C standards stating that if the shift value is greater than or equal to the number of bits in the operand to be shifted, then the result is undefined. That makes sense.
But, given the following program, bits2.c:
#include <stdio.h>
#define BIT_MASK(foo) ((unsigned int)(1 << foo) - 1)
int main()
{
unsigned int foo;
char *s = "32";
foo = atoi(s);
printf("%d %.8x\n", foo, BIT_MASK(foo));
foo = 32;
printf("%d %.8x\n", foo, BIT_MASK(foo));
return (0);
}
If I compile with gcc -O2 bits2.c -o bits2, and run it on a Linux/x86_64 machine, I get the following:
32 00000000
32 ffffffff
If I take the same code and compile it on a Linux/MIPS (big-endian) machine, I get this:
32 00000000
32 00000000
On the x86_64 machine, if I use gcc -O0 bits2.c -o bits2, then I get:
32 00000000
32 00000000
If I tweak BIT_MASK to ((unsigned int)(1UL << foo) - 1), then the output is 32 00000000 for both forms, regardless of gcc's optimization level.
So it appears that on x86_64, gcc is optimizing something incorrectly OR the undefined nature of left-shifting 32 bits on a 32-bit number is being determined by the hardware of each platform.
Given all of the above, is it possible to programatically create a C macro that creates a bit mask from either a single bit or a range of bits?
I.e.:
BIT_MASK(6) = 0x40
BIT_FIELD_MASK(8, 12) = 0x1f00
Assume BIT_MASK and BIT_FIELD_MASK operate from a 0-index (0-31). BIT_FIELD_MASK is to create a mask from a bit range, i.e., 8:12.
Here is a version of the macro which will work for arbitrary positive inputs. (Negative inputs still invoke undefined behavior...)
#include <limits.h>
/* A mask with x least-significant bits set, possibly 0 or >=32 */
#define BIT_MASK(x) \
(((x) >= sizeof(unsigned) * CHAR_BIT) ?
(unsigned) -1 : (1U << (x)) - 1)
Of course, this is a somewhat dangerous macro as it evaluates its argument twice. This is a good opportunity to use a static inline if you use GCC or target C99 in general.
static inline unsigned bit_mask(int x)
{
return (x >= sizeof(unsigned) * CHAR_BIT) ?
(unsigned) -1 : (1U << x) - 1;
}
As Mysticial noted, shifting more than 32 bits with a 32-bit integer results in implementation-defined undefined behavior. Here are three different implementations of shifting:
On x86, only examine the low 5 bits of the shift amount, so x << 32 == x.
On PowerPC, only examine the low 6 bits of the shift amount, so x << 32 == 0 but x << 64 == x.
On Cell SPUs, examine all bits, so x << y == 0 for all y >= 32.
However, compilers are free to do whatever they want if you shift a 32-bit operand 32 bits or more, and they are even free to behave inconsistently (or make demons fly out your nose).
Implementing BIT_FIELD_MASK:
This will set bit a through bit b (inclusive), as long as 0 <= a <= 31 and 0 <= b <= 31.
#define BIT_MASK(a, b) (((unsigned) -1 >> (31 - (b))) & ~((1U << (a)) - 1))
Shifting by more than or equal to the size of the integer type is undefined behavior.
So no, it's not a GCC bug.
In this case, the literal 1 is of type int which is 32-bits in both systems that you used. So shifting by 32 will invoke this undefined behavior.
In the first case, the compiler is not able to resolve the shift-amount to 32. So it likely just issues the normal shift-instruction. (which in x86 uses only the bottom 5-bits) So you get:
(unsigned int)(1 << 0) - 1
which is zero.
In the second case, GCC is able to resolve the shift-amount to 32. Since it is undefined behavior, it (apparently) just replaces the entire result with 0:
(unsigned int)(0) - 1
so you get ffffffff.
So this is a case of where GCC is using undefined behavior as an opportunity to optimize.
(Though personally, I'd prefer that it emits a warning instead.)
Related: Why does integer overflow on x86 with GCC cause an infinite loop?
Assuming you have a working mask for n bits, e.g.
// set the first n bits to 1, rest to 0
#define BITMASK1(n) ((1ULL << (n)) - 1ULL)
you can make a range bitmask by shifting again:
// set bits [k+1, n] to 1, rest to 0
#define BITNASK(n, k) ((BITMASK(n) >> k) << k)
The type of the result is unsigned long long int in any case.
As discussed, BITMASK1 is UB unless n is small. The general version requires a conditional and evaluates the argument twice:
#define BITMASK1(n) (((n) < sizeof(1ULL) * CHAR_BIT ? (1ULL << (n)) : 0) - 1ULL)
#define BIT_MASK(foo) ((~ 0ULL) >> (64-foo))
I'm a bit paranoid about this. I think this assumes that unsigned long long is exactly 64 bits. But it's a start and it works up to 64 bits.
Maybe this is correct:
define BIT_MASK(foo) ((~ 0ULL) >> (sizeof(0ULL)*8-foo))
A "traditional" formula (1ul<<n)-1 has different behavior on different compilers/processors for n=8*sizeof(1ul). Most commonly it overflows for n=32. Any added conditionals will evaluate n multiple times. Going 64-bits (1ull<<n)-1 is an option, but problem migrates to n=64.
My go-to formula is:
#define BIT_MASK(n) (~( ((~0ull) << ((n)-1)) << 1 ))
It does not overflow for n=64 and evaluates n only once.
As downside it will compile to 2 LSH instructions if n is a variable. Also n cannot be 0 (result will be compiler/processor-specific), but it is a rare possibility for all uses that I have(*) and can be dealt with by adding a guarding "if" statement only where necessary (and even better an "assert" to check both upper and lower boundaries).
(*) - usually data comes from a file or pipe, and size is in bytes. If size is zero, then there's no data, so code should do nothing anyway.
What about:
#define BIT_MASK(n) (~(((~0ULL) >> (n)) << (n)))
This works on all endianess system, doing -1 to invert all bits doesn't work on big-endian system.
Since you need to avoid shifting by as many bits as there are in the type (whether that's unsigned long or unsigned long long), you have to be more devious in the masking when dealing with the full width of the type. One way is to sneak up on it:
#define BIT_MASK(n) (((n) == CHAR_BIT * sizeof(unsigned long long)) ? \
((((1ULL << (n-1)) - 1) << 1) | 1) : \
((1ULL << (n )) - 1))
For a constant n such as 64, the compiler evaluates the expression and generates only the case that is used. For a runtime variable n, this fails just as badly as before if n is greater than the number of bits in unsigned long long (or is negative), but works OK without overflow for values of n in the range 0..(CHAR_BIT * sizeof(unsigned long long)).
Note that CHAR_BIT is defined in <limits.h>.
#iva2k's answer avoids branching and is correct when the length is 64 bits. Working on that, you can also do this:
#define BIT_MASK(length) ~(((unsigned long long) -2) << length - 1);
gcc would generate exactly the same code anyway, though.
I been a long time since I wrote a C code. Does anyone knows how to translate this piece of code to Delphi 2010?
char * pAlignedBuf = (char *) ((int(buf) + 7) & ~7);
where buf is char * buf.
I know that char * is Pchar, but I dont know what & and ~7are.
& is the bitwise and operator.
~ id the bitwise unary not operator.
~7 is a number with all the lower 3 bits set to 0.
& ~7 makes all the lower 3 bits 0 for whatever is on the left side.
The (char *) at the right of the assignment is a hard cast to char *
int(buf) is a hard cast of buf to integer.
That code can be written, in pascal, like this:
var pAlignedBuf: PChar;
pAlignedBuf := PChar((integer(Buf) + 7) and (not 7))
And it's a way to obtain an 8 byte aligned buffer from whatever Buf is. It works by incrementing the Buf with 7 and then clearing the lower 3 bits.
Edit
To be on the safe side, since Delphi 64 bit is somewhat around the corner, that code can be expressed as:
var pAlignedBuf: PChar;
pAlignedBuf := PChar(NativeUInt(Buf) + 7) and (not 7))
And for those that don't like bitwise logic-fu, it can be again re-written as:
var pAlignedBuf: PChar;
pAlignedBuf := PChar(((NativeUInt(Buf) + 7) div 8) * 8);
& is the binary "bitwise and" operator, which you write and in Delphi. ~ is unary "bitwise not" operator, which you write not in Delphi.
The translation is therefore
var
PAlignedBuf: PChar;
begin
pAlignedBuf := PChar((cardinal(buf) + 7) and not 7).
(Well, strictly speaking, the literal translation is integer(buf), not cardinal(buf), but I think cardinal is better. But I am not 100 % sure since I don't know the actual case.)
& is the bitwise-and operation. Example: 0b0011 & 0b0110 == 0b0010.
~ is the bitwise-negation operation. Example: ~0b0111 == 0b1000 (assuming 4-bit numbers).
Assuming all the casts are legal, the statement
char * pAlignedBuf = (char *) ((int(buf) + 7) & ~7);
puts in pAlignedBuf the address pointed to buf aligned to 8 bytes (last 3 bits set to 0).
`buf` `pAlignedBuf`
0x...420 0x...420
0x...421 0x...428
0x...422 0x...428
...
0x...427 0x...428
0x...428 0x...428
...
0x...429 0x...430