The output should be (\d+:\d+) so which is required by the Verilog syntax I had to use.
Does the "Verilog syntax" have some sort of specification that says an N1..N2 range should be presented sometimes as "N1:N2" and other times as "N2:N1"? Do you know whether there is some reason for this fluctuation?
Regarding the code you posted, you are missing some fundamental points of Perl syntax. What do you think @digits ne '' is supposed to do? (Hint: an array in a scalar context always returns the number of elements in the array, which will never be the same as an empty string.)
If "Verilog syntax" supports the use of a consistent ordering of range components, I think this will be close to what you're looking for:
use strict;
use warnings;
my @test = qw/1 5:10 18:14 21 24:25 31:28/;
print get_reserved( \@test ), "\n";
sub get_reserved
{
my ( $bits_ref ) = @_; # should be an array ref
return "bad call to get_reserved()"
unless ( ref( $bits_ref ) eq 'ARRAY' and @$bits_ref );
my @reg32set;
for my $spec ( @$bits_ref ) {
if ( $spec =~ /(\d+):(\d+)/) {
my ( $bgn, $end ) = sort {$a<=>$b} ( $1, $2 );
$reg32set[$_] = 1 for ( $bgn .. $end );
}
else {
$reg32set[$spec] = 1;
}
}
my $verilog_string = '';
for my $seq ( 0 .. $#reg32set ) {
if ( defined( $reg32set[$seq] )) {
$verilog_string .= ", ";
} else {
$verilog_string .= "$seq:";
}
}
return "no intervals to report from get_reserved()"
unless ( $verilog_string =~ /\d/ );
$verilog_string =~ s/(?<=\d):[\d:]+:(?=\d)/:/g; # e.g. "2:3:4:5:6
+ -> 2:6
$verilog_string =~ s/^(?:, )+//;
$verilog_string =~ s/:(?:, )*$//;
$verilog_string =~ s/:,(?: ,)*/,/g;
return $verilog_string;
}
(updated to add diagnostic messages for a couple of edge conditions) |