http://qs321.pair.com?node_id=11114115

syedasadali95 has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

I am trying to read a file from my perl script and decide something based on the 6th bit of my address pattern which I read from the file. For example I have a file which has the following lines:

43307205 (26224) chn:req mon:orig cmd:SDP_CMD_RDBLKL tag:0x3bb504dd addr:0x1009dc0 qospri:0 len:0xf qosfw:0 vc:4 unit:0x0 thrd:15 chain:0 io:0 blklvl:0 noalloc:0

43331070 (26239) chn:req mon:orig cmd:SDP_CMD_WRSIZEDFULL tag:0x3bb508e1 addr:0xcf09dc0 qospri:0 len:0xf qosfw:0 vc:4 unit:0x0 thrd:14 chain:0 io:0 blklvl:0 noalloc:0

I want to do the following

1. Read the input file

2. Open two output files (Out1 & Out2)

3. Grep the address value from the input file (addr:0xcf09dc0)

4. If 6th bit of addr field is zero (addr[ 6 ]=0) then print the entire line to Out1 file/ If 6th bit is one (addr[ 6 ]=1) then print the entire line to Out2 file

############ Code starts #############

open (IN_FILE, "$ARGV[0]") or die "Please provide an input trace fi +le\n"; open (OUT_FILE1, ">>ccd0_sdp0.trc"); open (OUT_FILE2, ">>ccd0_sdp1.trc"); while (my $line1 = <IN_FILE>) { if( ($line1 =~ /addr/) ) { $line1 =~ /addr:([a-z0-9-]+)\s+/; my $address = hex $1; $address = sprintf "0x%x", $address; if($line1 =~ /SDP_CMD_RDBLKL/) { #$line1 =~ s/addr\:0x\S*/addr\:$address/; printf OUT_FILE1 ("$line1"); } elsif($line1 =~ /SDP_CMD_WRSIZEDFULL/) { printf OUT_FILE2 ("$line1"); } } else { printf OUT_FILE1 ("$line1"); printf OUT_FILE2 ("$line1"); } } close(OUT_FILE1); close(OUT_FILE2); close(IN_FILE); print "Converting SuccesS\n"; exit;

######## Code ends #########

From the above code, instead of checking for SDP_CMD_RDBLKL and SDP_CMD_WRSIZEDFULL, I need to check if addr[ 6 ] = 0/1

Please suggest any way to operate on bit positions in perl.

Replies are listed 'Best First'.
Re: Operate with bits
by GrandFather (Saint) on Mar 11, 2020 at 08:31 UTC

    Easy - use the bitwise and operator (Bitwise And):

    use strict; use warnings; for my $pattern (0xffd1, 0x0060, 0x0040, 1 << 6, 0xff8f) { if ($pattern & (1 << 6)) { printf "Bit 6 set in %04x\n", $pattern; } else { printf "Bit 6 not set in %04x\n", $pattern; } }

    Prints:

    Bit 6 set in ffd1 Bit 6 set in 0060 Bit 6 set in 0040 Bit 6 set in 0040 Bit 6 not set in ff8f
    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond

      Thank you for this suggestion

Re: Operate with bits
by rizzo (Curate) on Mar 11, 2020 at 11:04 UTC
    Two ways:

    1.) use split('', $address)

    2.) use substr($address,6)

      • 1.) would be correct for characters (or hex digits), but OP wants bits, so you would have to do split(//, sprintf("%b", $address))
      • 2.) additionally, for substr to count its offset from right, you have to use negative, so substr((sprintf "%b", $address), -6, 1)
        Yep. Thanks for the correction.

        Thanks rizzo & soonix. Actually substr((sprintf "%b", $address), -7, 1) is serving my need as we are starting from right side of the bit stream (LSB) and starting to count from bit 0 to bit 5, so total of six bits and keeping -7 in the substr func as index makes us catch the 6th bit from the bit stream. Thanks again for the help guys