#! /usr/bin/perl -w
# SPDX-License-Identifier: GPL-2 .0 -only OR BSD-3 -Clause
# Copyright (C) 2019 --2020 Intel Corporation
use Getopt::Long qw(:config no_ignore_case);
use File::Basename;
my $ccsregs = "ccs-regs.asc" ;
my $header;
my $regarray;
my $limitc;
my $limith;
my $kernel;
my $help;
GetOptions("ccsregs|c=s" => \$ccsregs,
"header|e=s" => \$header,
"regarray|r=s" => \$regarray,
"limitc|l=s" => \$limitc,
"limith|L=s" => \$limith,
"kernel|k" => \$kernel,
"help|h" => \$help) or die "can't parse options" ;
$help = 1 if ! defined $header || ! defined $limitc || ! defined $limith;
if (defined $help) {
print <<EOH
$0 - Create CCS register definitions for C
usage: $0 -c ccs-regs.asc -e header -r regarray -l limit-c -L limit-header [-k]
-c ccs register file
-e header file name
-r register description array file name
-l limit and capability array file name
-L limit and capability header file name
-k generate files for kernel space consumption
EOH
;
exit 0 ;
}
my $lh_hdr = ! defined $kernel
? '#include "ccs-os.h"' . "\n"
: "#include <linux/bits.h>\n#include <linux/types.h>\n" ;
my $uint32_t = ! defined $kernel ? 'uint32_t' : 'u32' ;
my $uint16_t = ! defined $kernel ? 'uint16_t' : 'u16' ;
open(my $R, "< $ccsregs" ) or die "can't open $ccsregs" ;
open(my $H, "> $header" ) or die "can't open $header" ;
my $A;
if (defined $regarray) {
open($A, "> $regarray" ) or die "can't open $regarray" ;
}
open(my $LC, "> $limitc" ) or die "can't open $limitc" ;
open(my $LH, "> $limith" ) or die "can't open $limith" ;
my %this ;
sub is_limit_reg($) {
my $addr = hex $_[0 ];
return 0 if $addr < 0 x40; # weed out status registers
return 0 if $addr >= 0 x100 && $addr < 0 xfff; # weed out configuration registers
return 1 ;
}
my $uc_header = basename uc $header;
$uc_header =~ s/[^A-Z0-9 ]/_/g;
my $copyright = "/* Copyright (C) 2019--2020 Intel Corporation */\n";
my $license = "SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause" ;
my $note = "/*\n * Generated by $0;\n * do not modify.\n */\n";
for my $fh ($A, $LC) {
print $fh "// $license\n$copyright$note\n" if defined $fh;
}
for my $fh ($H, $LH) {
print $fh "/* $license */\n$copyright$note\n";
}
print $H <<EOF
#ifndef __${uc_header}__
#define __${uc_header}__
EOF
;
print $H <<EOF
#include <linux/bits.h>
#include <media/v4l2-cci.h>
EOF
if defined $kernel;
print $H "#define CCS_FL_BASE " .
(defined $kernel ? "CCI_REG_PRIVATE_SHIFT" : 16 ) . "\n" ;
my $flag = -1 ;
my $all_flags;
sub bit_def($) {
my $bit = shift @_;
if (defined $kernel) {
return "BIT$bit" if $bit =~ /^\(.*\)$/;
return "BIT($bit)" ;
}
return "(1U << $bit)" ;
}
sub flag_str($$) {
my ($flag, $check) = @_;
$$flag++;
my $flag_str = !$$flag ? "CCS_FL_BASE" : "(CCS_FL_BASE + $$flag)" ;
$flag_str = bit_def($flag_str);
$$check .= " | " if defined $$check;
$$check .= $flag_str;
return $flag_str;
}
if (! defined $kernel) {
print $H "#define CCS_FL_16BIT " . flag_str(\$flag, \$all_flags) . "\n" ;
print $H "#define CCS_FL_32BIT " . flag_str(\$flag, \$all_flags) . "\n" ;
}
print $H "#define CCS_FL_FLOAT_IREAL " . flag_str(\$flag, \$all_flags) . "\n" ;
print $H "#define CCS_FL_IREAL " . flag_str(\$flag, \$all_flags) . "\n" ;
print $H "#define CCS_BUILD_BUG \\
BUILD_BUG_ON(~CCI_REG_PRIVATE_MASK & ($all_flags))\n"
if defined $kernel;
print $H <<EOF
#define CCS_R_ADDR(r) ((r) & 0 xffff)
EOF
if ! defined $kernel;
print $A <<EOF
#include <stdint.h>
#include <stdio.h>
#include "ccs-extra.h"
#include "ccs-regs.h"
EOF
if defined $A;
my $uc_limith = basename uc $limith;
$uc_limith =~ s/[^A-Z0-9 ]/_/g;
print $LH <<EOF
#ifndef __${uc_limith}__
#define __${uc_limith}__
$lh_hdr
struct ccs_limit {
$uint32_t reg;
$uint16_t size;
$uint16_t flags;
const char *name;
};
EOF
;
print $LH "#define CCS_L_FL_SAME_REG " . bit_def(0 ) . "\n\n" ;
print $LH <<EOF
extern const struct ccs_limit ccs_limits[];
EOF
;
print $LC <<EOF
#include "ccs-limits.h"
#include "ccs-regs.h"
const struct ccs_limit ccs_limits[] = {
EOF
;
my $limitcount = 0 ;
my $argdescs;
my $reglist = "const struct ccs_reg_desc ccs_reg_desc[] = {\n" ;
sub name_split($$) {
my ($name, $addr) = @_;
my $args;
$name =~ /([^\(]+?)(\(.*)/;
($name, $args) = ($1 , $2 );
$args = [split /,\s*/, $args];
foreach my $t (@$args) {
$t =~ s/[\(\)]//g;
$t =~ s/\//\\\//g;
}
return ($name, $addr, $args);
}
sub tabconv($) {
$_ = shift;
my @l = split "\n" , $_;
map {
s/ {8 ,8 }/\t/g;
s/\t\K +//;
} @l;
return (join "\n" , @l) . "\n" ;
}
sub elem_bits(@) {
my @flags = @_;
return 16 if grep /^16 $/, @flags;
return 32 if grep /^32 $/, @flags;
return 8 ;
}
sub arr_size($) {
my $this = $_[0 ];
my $size = $this ->{elsize};
my $h = $this ->{argparams};
foreach my $arg (@{$this ->{args}}) {
my $apref = $h->{$arg};
$size *= $apref->{max} - $apref->{min} + 1 ;
}
return $size;
}
sub print_args($$$) {
my ($this , $postfix, $is_same_reg) = @_;
my ($args, $argparams, $name) =
($this ->{args}, $this ->{argparams}, $this ->{name});
my $varname = "ccs_reg_arg_" . (lc $name) . $postfix;
my @mins;
my @sorted_args = @{$this ->{sorted_args}};
my $lim_arg;
my $size = arr_size($this );
$argdescs .= "static const struct ccs_reg_arg " . $varname . "[] = {\n" ;
foreach my $sorted_arg (@sorted_args) {
push @mins, $argparams->{$sorted_arg}->{min};
}
foreach my $sorted_arg (@sorted_args) {
my $h = $argparams->{$sorted_arg};
$argdescs .= "\t{ \" $sorted_arg\", $h->{min}, $h->{max}, $h->{elsize} },\n" ;
$lim_arg .= defined $lim_arg ? ", $h->{min}" : "$h->{min}" ;
}
$argdescs .= "};\n\n" ;
$reglist .= "\t{ CCS_R_" . (uc $name) . "(" . (join "," , (@mins)) .
"), $size, sizeof($varname) / sizeof(*$varname)," .
" \" " . (lc $name) . " \", $varname },\n" ;
print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . "($lim_arg), " .
$size . ", " . ($is_same_reg ? "CCS_L_FL_SAME_REG" : "0" ) .
", \" $name" . (defined $this->{discontig} ? " $lim_arg" : " ") . " \" },\n"
if is_limit_reg $this ->{base_addr};
}
my $hdr_data;
while (<$R>) {
chop;
s/^\s*//;
next if /^[#; ]/ || /^$/;
if (s/^-\s*//) {
if (s/^b\s*//) {
my ($bit, $addr) = split /\t+/;
$bit = uc $bit;
$hdr_data .= sprintf "#define %-62s %s" , "CCS_" . (uc ${this {name}}) ."_$bit" , bit_def($addr) . "\n" ;
} elsif (s/^f\s*//) {
s/[,\.-]/_/g;
my @a = split /\s+/;
my ($msb, $lsb, $this_field) = reverse @a;
@a = ( { "name" => "SHIFT" , "addr" => $lsb, "fmt" => "%uU" , },
{ "name" => "MASK" , "addr" => (1 << ($msb + 1 )) - 1 - ((1 << $lsb) - 1 ), "fmt" => "0x%" . join("." , ($this {"elsize" } >> 2 ) x 2 ) . "x" } );
$this {"field" } = $this_field;
foreach my $ar (@a) {
#print $ar->{fmt}."\n" ;
$hdr_data .= sprintf "#define %-62s " . $ar->{"fmt" } . "\n" , "CCS_" . (uc $this {"name" }) . (defined $this_field ? "_" . uc $this_field : "" ) . "_" . $ar->{"name" }, $ar->{"addr" } . "\n" ;
}
} elsif (s/^e\s*//) {
s/[,\.-]/_/g;
my ($enum , $addr) = split /\s+/;
$enum = uc $enum ;
$hdr_data .= sprintf "#define %-62s %s" , "CCS_" . (uc ${this {name}}) . (defined $this {"field" } ? "_" . uc $this {"field" } : "" ) ."_$enum" , $addr . ($addr =~ /0 x/i ? "" : "U" ) . "\n" ;
} elsif (s/^l\s*//) {
my ($arg, $min, $max, $elsize, @discontig) = split /\s+/;
my $size;
foreach my $num ($min, $max) {
$num = hex $num if $num =~ /0 x/i;
}
$hdr_data .= sprintf "#define %-62s %s" , "CCS_LIM_" . (uc ${this {name}} . "_MIN_$arg" ), $min . ($min =~ /0 x/i ? "" : "U" ) . "\n" ;
$hdr_data .= sprintf "#define %-62s %s" , "CCS_LIM_" . (uc ${this {name}} . "_MAX_$arg" ), $max . ($max =~ /0 x/i ? "" : "U" ) . "\n" ;
my $h = $this {argparams};
$h->{$arg} = { "min" => $min,
"max" => $max,
"elsize" => $elsize =~ /^0 x/ ? hex $elsize : $elsize,
"discontig" => \@discontig };
$this {discontig} = $arg if @discontig;
next if $#{ $this {args}} + 1 != scalar keys %{$this {argparams}};
my $reg_formula = "$this{addr}" ;
my $lim_formula;
chop $reg_formula;
$reg_formula = "(" . $reg_formula if $this {flagstring} ne "" ;
foreach my $arg (@{$this {args}}) {
my $d = $h->{$arg}->{discontig};
my $times = $h->{$arg}->{elsize} != 1 ?
" * " . $h->{$arg}->{elsize} : "" ;
if (@$d) {
my ($lim, $offset) = split /,/, $d->[0 ];
$reg_formula .= " + (($arg) < $lim ? ($arg)$times : $offset + (($arg) - $lim)$times)" ;
} else {
$reg_formula .= " + ($arg)$times" ;
}
$lim_formula .= (defined $lim_formula ? " + " : "" ) . "($arg)$times" ;
}
$reg_formula .= ")" ;
$lim_formula =~ s/^\(([a-z0-9 ]+)\)$/$1 /i;
print $H tabconv sprintf("#define %-62s %s" , "CCS_R_" . (uc $this {name}) .
$this {arglist}, $reg_formula .
(($this {flagstring} eq "" ) ? "" :
" | " . $this {flagstring} . ")" ) . "\n" );
print $H tabconv $hdr_data;
undef $hdr_data;
# Sort arguments in descending order by size
@{$this {sorted_args}} = sort {
$h->{$a}->{elsize} <= $h->{$b}->{elsize}
} @{$this {args}};
if (defined $this {discontig}) {
my $da = $this {argparams}->{$this {discontig}};
my ($first_discontig) = split /,/, $da->{discontig}->[0 ];
my $max = $da->{max};
$da->{max} = $first_discontig - 1 ;
print_args(\%this , "" , 0 );
$da->{min} = $da->{max} + 1 ;
$da->{max} = $max;
print_args(\%this , $first_discontig, 1 );
} else {
print_args(\%this , "" , 0 );
}
next unless is_limit_reg $this {base_addr};
print $LH tabconv sprintf "#define %-63s%s\n" ,
"CCS_L_" . (uc $this {name}) . "_OFFSET(" .
(join ", " , @{$this {args}}) . ")" , "($lim_formula)" ;
}
if (! @{$this {args}}) {
print $H tabconv($hdr_data);
undef $hdr_data;
}
next;
}
my ($name, $addr, @flags) = split /\t+/, $_;
my $args = [];
my $sp;
($name, $addr, $args) = name_split($name, $addr) if /\(.*\)/;
$name =~ s/[,\.-]/_/g;
my $flagstring = "" ;
my $bits = elem_bits(@flags);
if (! defined $kernel) {
$flagstring .= "| CCS_FL_16BIT " if $bits == 16 ;
$flagstring .= "| CCS_FL_32BIT " if $bits == 32 ;
}
$flagstring .= "| CCS_FL_FLOAT_IREAL " if grep /^float_ireal$/, @flags;
$flagstring .= "| CCS_FL_IREAL " if grep /^ireal$/, @flags;
$flagstring =~ s/^\| //;
$flagstring =~ s/ $//;
$flagstring = "($flagstring)" if $flagstring =~ /\|/;
my $base_addr = $addr;
$addr = "CCI_REG$bits($addr)" if defined $kernel;
if ($flagstring ne "" && !@$args) {
$addr = "($addr | $flagstring)" ;
$flagstring = "" ;
}
my $arglist = @$args ? "(" . (join ", " , @$args) . ")" : "" ;
$hdr_data .= sprintf "#define %-62s %s\n" , "CCS_R_" . (uc $name), $addr
if !@$args;
$name =~ s/\(.*//;
%this = ( name => $name,
addr => $addr,
flagstring => $flagstring,
base_addr => $base_addr,
argparams => {},
args => $args,
arglist => $arglist,
elsize => $bits / 8 ,
);
if (!@$args) {
$reglist .= "\t{ CCS_R_" . (uc $name) . ", 1, 0, \" " . (lc $name) . " \", NULL },\n" ;
print $H tabconv $hdr_data;
undef $hdr_data;
print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . ", " .
$this {elsize} . ", 0, \" $name\" },\n"
if is_limit_reg $this {base_addr};
}
print $LH tabconv sprintf "#define %-63s%s\n" ,
"CCS_L_" . (uc $this {name}), $limitcount++
if is_limit_reg $this {base_addr};
}
if (defined $A) {
print $A $argdescs, $reglist;
print $A "\t{ 0 }\n" ;
print $A "};\n" ;
}
print $H "\n#endif /* __${uc_header}__ */\n";
print $LH tabconv sprintf "#define %-63s%s\n" , "CCS_L_LAST" , $limitcount;
print $LH "\n#endif /* __${uc_limith}__ */\n";
print $LC "\t{ 0 } /* Guardian */\n";
print $LC "};\n" ;
close($R);
close($H);
close($A) if defined $A;
close($LC);
close($LH);
Messung V0.5 in Prozent C=96 H=93 G=94
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-07)
¤
*© Formatika GbR, Deutschland