Perl <<= and ^= Meaning - perl

Hello I´m trying to convert a bunch of Perl scripts to C#.
A have this piece of code and I don´t know what <<=, ^=, &= means. Can someone please tell me the meaning of the part (???) too?. Thanks in advance.
$cwl = 6;
$sr = 1;
for ($i=0; $i<$gf::field; $i++) {
$gf::log[$sr] = $i;
$gf::alog[$i] = $sr;
$sr <<= 1;
if ($sr & (1<<$cwl)) {$sr ^= $prim} (???)
$sr &= $gf::field;
}

These are:
<<= = Left shift equal operator, shifts the source variable's bits by n places to the left and assign back to source variable.
^= = Bitwise XOR equal operator. XORs the source variable by the right hand variable, and assigns to the source variable.
&= = Bitwise AND equal operator. ANDs the source variable and the right hand variable, and assigns the result to the source variable.
The C# equivalents from your code above:
Left Shift
# Perl code
$sr <<= 1;
// C# code
sr = sr << 1;
Bitwise XOR
# Perl code
$sr ^= $prim
// C# code
sr = sr ^ prim
Bitwise AND
# Perl code
$sr &= $gf::field
// C# code
sr = sr & gf.field // or whatever you've named $gf::field
Edit following OP comment
OP asked whether:
if ($sr & (1<<$cwl))
Can be translated to:
cwl=1 << cwl;
if (Convert.ToBoolean(sr) & Convert.ToBoolean(cwl))
I think you've made an error here. cwl is not reassigned in the original if statement in Perl.
In fact, the logic of the operation is to say:
Is sr bitwise AND 1 left-shifted by cwl true?
I'd be tempted to rewrite the Perl code to:
if ((sr & (1 << cwl)) != 0)
Why? The original statement ascertains whether the result of the if statement is true. Any non-zero value in Perl is true, therefore we need to perform the operation as per the Perl and test for a non-zero value.

Related

Why does the Streaming-Operator in SystemVerilog reverse the byte order?

I simulated the following example:
shortint j;
byte unsigned data_bytes[];
j = 16'b1111_0000_1001_0000;
data_bytes = { >>{j}};
`uvm_info(get_type_name(), $sformatf("j data_bytes: %b_%b", data_bytes[1], data_bytes[0]), UVM_LOW)
Result:
UVM_INFO Initiator.sv(84) # 0: uvm_test_top.sv_initiator [Initiator] j data_bytes: 10010000_11110000
However, this seems strange to me, since the byte-order is reversed, as I expect the LSB to be at index 0 of data_byte[0] and the MSB at index 7 of data_byte[1]. Why does this happen? According to documentation (Cadence Help) this should not be the case.
As defined in section 6.24.3 Bit-stream casting of the IEEE 1800-2017 LRM, the [0] element of an unpacked dynamic array is considered the left index, and streaming >> goes from left to right indexes. To get the results you want, write
data_bytes = { << byte {j}};
This reverses the stream, but keeps the individual bytes in right to left order.

Pack individual signal into an array

I have a bunch of signals like this:
logic [7:0] in0;
logic [7:0] in1;
logic [7:0] in2;
logic [7:0] in3;
That I want to assign to an array:
logic [7:0] in_array [4];
assign in_array[0] = in0;
assign in_array[1] = in1;
assign in_array[2] = in2;
assign in_array[3] = in3;
Easy enough, but if instead of 4 items I have 128 this gets annoying. I am sure there is a combination of defines and generates that can do this in a loop. Something like:
`define IN(x) inx
genvar i;
generate
for(i = 0; i<4; i++) begin
assign in_array[i] = `IN(i);
end
endgenerate
The above code doesn't work, but I think that I have done something like this before.
Simplifying that code is something that cannot be done in SystemVerilog. You can reduce you typing by creating a macro like below (note the double backticks ``), but you will still need to manually write each index. Macros are are resolved before generate loops and the input variable to the macro is treated as a literal.
// short named macro for reduced typing
// Note: using short named macro is typically a bad practice,
// but will be removed latter with an undef
`define A(idx) assign array_in[idx] = out``idx
//This works
`A(0);
`A(1);
`A(2);
`A(3);
// doesn't work. For example # gidx==0 will eval to 'assign array_in[0] = outgidx;'.
// There is not outgidx
genvar gidx;
generate
for(gidx=0; gidx<4; gidx++) begin
`A(gidx);
end
endgenerate
`undef A // prevent macro from from being used latter on
If it is just a small number of entries, it is best to do it manually. If it is large number of entries, then you need to consider a way to generate the for you, such as embedded coded.
There are also various embedded code (such as Perl's EP3, Ruby's eRuby/ruby_it, Python's prepro, etc.) that can generate the desired code. Pick your preference. You will need to per-process these files before giving to the compiler. Example with EP3 generating 400 assignments:
#perl_begin
foreach my $idx (0..400) {
printf "assign array_in[%0d] = out%0d;", $idx, $idx;
}
#perl_end
Use `` to separate text from argument.
`define IN(x) in``x
But there is another issue with the variable i not being declared at the time when the macro is evaluated. Thus the whole generate loop just connects to ini, because i is just another letter. Because of this macros cannot be assigned by dynamically allocated values.
The environment of your module already has to connect explicitly to each input assign in0 = out0; ... assign in127 = out127. So the simplest solution would be to have in_array as your modules input and let the environment connect to it assign array_in[0] = out0.
Something like this:
module parent_module();
/*some other stuff that has outputs out0, out1 etc.*/
logic [7:0] array_in[4];
assign array_in[0] = out0;
assign array_in[1] = out1;
assign array_in[2] = out2;
assign array_in[3] = out3;
my_module(.array_in(array_in));
endmodule

How does incrementation operator work within a loop

I've just started off with perl, and while trying out a few compound statements, I wrote this:
my $ct;
while ($ct++ < 10) {
print $ct;
}
It prints out:
12345678910
I was not expecting it to print 10. How does the logic for the loop really work?
According to perdoc, a TERM operator has the highest precedence. $ct gets incremented to 10 after iterating the loop where it is 9. When it becomes 10, while loop is supposed to exit. So why is 10 still printed out?
Think of it like
while ($ct < 10) {
$ct += 1;
print $ct;
}
(increment after comparison)
On the other hand, ++ on the left side of the variable will increment first, and then do comparison,
while (++$ct < 10) {
print $ct;
}
This is quite intuitive for someone with C background; from perldoc:
"++" and "--" work as in C. That is, if placed before a variable, they increment or decrement the variable by one before returning the value, and if placed after, increment or decrement after returning the value.
Its because you are using the postfix operator. its first compared then incremented.

Purpose of avalanching

I was researching different hash functions and came across SuperFastHash. This hashing function used a technique called "avalanching" which was defined like this:
/* Force "avalanching" of final 127 bits */
hash ^= hash << 3;
hash += hash >> 5;
hash ^= hash << 4;
hash += hash >> 17;
hash ^= hash << 25;
hash += hash >> 6;
What is the purpose of avalanching? Why are theese specific bit shift steps used (3, 5, 4..)?
Avalanching is just a term to define the "difussion" of small changes on input to the final result, for criptographic hashes where non-reversability is a really crucial having similar inputs provide really different results is a desirable feature to avoid an approximation attack crack a single hash.
See more info about this at http://en.wikipedia.org/wiki/Avalanche_effect
I can not see why it uses that steps but it is using AND and XOR with the own shifted result to increase the diffusion, probably other values will perform similar but that will need a deeper analysis

I'm using ELF Hash to write a specially tweaked version of hash map. Wanting to produce collisions

Can any one give an example of 2 strings, consisting of alphabetical characters only, that will produce the same hash value with ELFHash?
I need these to test my codes. But it doesn't seem like easy to produce. And to my surprise there there are a lot of example codes of various hash function on the internet but none of them provides examples of collided strings.
Below is the ELF Hash, in case you need it.
unsigned int ELFHash(const std::string& str)
{
unsigned int hash = 0;
unsigned int x = 0;
for(std::size_t i = 0; i < str.length(); i++)
{
hash = (hash << 4) + str[i];
if((x = hash & 0xF0000000L) != 0)
{
hash ^= (x >> 24);
hash &= ~x;
}
}
return (hash & 0x7FFFFFFF);
}
You can find collisions using a brute force method (e.g. compute all possible strings with length lower than 5).
Some example of collisions (that I got in that way):
hash = 23114:
-------------
UMz
SpJ
hash = 4543841:
---------------
AAAAQ
AAABA
hash = 5301994:
---------------
KYQYZ
KYQZJ
KYRIZ
KYRJJ
KZAYZ