mk-ccs-regs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. #!/usr/bin/perl -w
  2. # SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
  3. # Copyright (C) 2019--2020 Intel Corporation
  4. use Getopt::Long qw(:config no_ignore_case);
  5. use File::Basename;
  6. my $ccsregs = "ccs-regs.asc";
  7. my $header;
  8. my $regarray;
  9. my $limitc;
  10. my $limith;
  11. my $kernel;
  12. my $help;
  13. GetOptions("ccsregs|c=s" => \$ccsregs,
  14. "header|e=s" => \$header,
  15. "regarray|r=s" => \$regarray,
  16. "limitc|l=s" => \$limitc,
  17. "limith|L=s" => \$limith,
  18. "kernel|k" => \$kernel,
  19. "help|h" => \$help) or die "can't parse options";
  20. $help = 1 if ! defined $header || ! defined $limitc || ! defined $limith;
  21. if (defined $help) {
  22. print <<EOH
  23. $0 - Create CCS register definitions for C
  24. usage: $0 -c ccs-regs.asc -e header -r regarray -l limit-c -L limit-header [-k]
  25. -c ccs register file
  26. -e header file name
  27. -r register description array file name
  28. -l limit and capability array file name
  29. -L limit and capability header file name
  30. -k generate files for kernel space consumption
  31. EOH
  32. ;
  33. exit 0;
  34. }
  35. my $lh_hdr = ! defined $kernel
  36. ? '#include "ccs-os.h"' . "\n"
  37. : "#include <linux/bits.h>\n#include <linux/types.h>\n";
  38. my $uint32_t = ! defined $kernel ? 'uint32_t' : 'u32';
  39. my $uint16_t = ! defined $kernel ? 'uint16_t' : 'u16';
  40. open(my $R, "< $ccsregs") or die "can't open $ccsregs";
  41. open(my $H, "> $header") or die "can't open $header";
  42. my $A;
  43. if (defined $regarray) {
  44. open($A, "> $regarray") or die "can't open $regarray";
  45. }
  46. open(my $LC, "> $limitc") or die "can't open $limitc";
  47. open(my $LH, "> $limith") or die "can't open $limith";
  48. my %this;
  49. sub is_limit_reg($) {
  50. my $addr = hex $_[0];
  51. return 0 if $addr < 0x40; # weed out status registers
  52. return 0 if $addr >= 0x100 && $addr < 0xfff; # weed out configuration registers
  53. return 1;
  54. }
  55. my $uc_header = basename uc $header;
  56. $uc_header =~ s/[^A-Z0-9]/_/g;
  57. my $copyright = "/* Copyright (C) 2019--2020 Intel Corporation */\n";
  58. my $license = "SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause";
  59. my $note = "/*\n * Generated by $0;\n * do not modify.\n */\n";
  60. for my $fh ($A, $LC) {
  61. print $fh "// $license\n$copyright$note\n" if defined $fh;
  62. }
  63. for my $fh ($H, $LH) {
  64. print $fh "/* $license */\n$copyright$note\n";
  65. }
  66. sub bit_def($) {
  67. my $bit = shift @_;
  68. return "BIT($bit)" if defined $kernel;
  69. return "(1U << $bit)" if $bit =~ /^[a-zA-Z0-9_]+$/;
  70. return "(1U << ($bit))";
  71. }
  72. print $H <<EOF
  73. #ifndef __${uc_header}__
  74. #define __${uc_header}__
  75. EOF
  76. ;
  77. print $H "#include <linux/bits.h>\n\n" if defined $kernel;
  78. print $H <<EOF
  79. #define CCS_FL_BASE 16
  80. EOF
  81. ;
  82. print $H "#define CCS_FL_16BIT " . bit_def("CCS_FL_BASE") . "\n";
  83. print $H "#define CCS_FL_32BIT " . bit_def("CCS_FL_BASE + 1") . "\n";
  84. print $H "#define CCS_FL_FLOAT_IREAL " . bit_def("CCS_FL_BASE + 2") . "\n";
  85. print $H "#define CCS_FL_IREAL " . bit_def("CCS_FL_BASE + 3") . "\n";
  86. print $H <<EOF
  87. #define CCS_R_ADDR(r) ((r) & 0xffff)
  88. EOF
  89. ;
  90. print $A <<EOF
  91. #include <stdint.h>
  92. #include <stdio.h>
  93. #include "ccs-extra.h"
  94. #include "ccs-regs.h"
  95. EOF
  96. if defined $A;
  97. my $uc_limith = basename uc $limith;
  98. $uc_limith =~ s/[^A-Z0-9]/_/g;
  99. print $LH <<EOF
  100. #ifndef __${uc_limith}__
  101. #define __${uc_limith}__
  102. $lh_hdr
  103. struct ccs_limit {
  104. $uint32_t reg;
  105. $uint16_t size;
  106. $uint16_t flags;
  107. const char *name;
  108. };
  109. EOF
  110. ;
  111. print $LH "#define CCS_L_FL_SAME_REG " . bit_def(0) . "\n\n";
  112. print $LH <<EOF
  113. extern const struct ccs_limit ccs_limits[];
  114. EOF
  115. ;
  116. print $LC <<EOF
  117. #include "ccs-limits.h"
  118. #include "ccs-regs.h"
  119. const struct ccs_limit ccs_limits[] = {
  120. EOF
  121. ;
  122. my $limitcount = 0;
  123. my $argdescs;
  124. my $reglist = "const struct ccs_reg_desc ccs_reg_desc[] = {\n";
  125. sub name_split($$) {
  126. my ($name, $addr) = @_;
  127. my $args;
  128. $name =~ /([^\(]+?)(\(.*)/;
  129. ($name, $args) = ($1, $2);
  130. $args = [split /,\s*/, $args];
  131. foreach my $t (@$args) {
  132. $t =~ s/[\(\)]//g;
  133. $t =~ s/\//\\\//g;
  134. }
  135. return ($name, $addr, $args);
  136. }
  137. sub tabconv($) {
  138. $_ = shift;
  139. my @l = split "\n", $_;
  140. map {
  141. s/ {8,8}/\t/g;
  142. s/\t\K +//;
  143. } @l;
  144. return (join "\n", @l) . "\n";
  145. }
  146. sub elem_size(@) {
  147. my @flags = @_;
  148. return 2 if grep /^16$/, @flags;
  149. return 4 if grep /^32$/, @flags;
  150. return 1;
  151. }
  152. sub arr_size($) {
  153. my $this = $_[0];
  154. my $size = $this->{elsize};
  155. my $h = $this->{argparams};
  156. foreach my $arg (@{$this->{args}}) {
  157. my $apref = $h->{$arg};
  158. $size *= $apref->{max} - $apref->{min} + 1;
  159. }
  160. return $size;
  161. }
  162. sub print_args($$$) {
  163. my ($this, $postfix, $is_same_reg) = @_;
  164. my ($args, $argparams, $name) =
  165. ($this->{args}, $this->{argparams}, $this->{name});
  166. my $varname = "ccs_reg_arg_" . (lc $name) . $postfix;
  167. my @mins;
  168. my @sorted_args = @{$this->{sorted_args}};
  169. my $lim_arg;
  170. my $size = arr_size($this);
  171. $argdescs .= "static const struct ccs_reg_arg " . $varname . "[] = {\n";
  172. foreach my $sorted_arg (@sorted_args) {
  173. push @mins, $argparams->{$sorted_arg}->{min};
  174. }
  175. foreach my $sorted_arg (@sorted_args) {
  176. my $h = $argparams->{$sorted_arg};
  177. $argdescs .= "\t{ \"$sorted_arg\", $h->{min}, $h->{max}, $h->{elsize} },\n";
  178. $lim_arg .= defined $lim_arg ? ", $h->{min}" : "$h->{min}";
  179. }
  180. $argdescs .= "};\n\n";
  181. $reglist .= "\t{ CCS_R_" . (uc $name) . "(" . (join ",", (@mins)) .
  182. "), $size, sizeof($varname) / sizeof(*$varname)," .
  183. " \"" . (lc $name) . "\", $varname },\n";
  184. print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . "($lim_arg), " .
  185. $size . ", " . ($is_same_reg ? "CCS_L_FL_SAME_REG" : "0") .
  186. ", \"$name" . (defined $this->{discontig} ? " $lim_arg" : "") . "\" },\n"
  187. if is_limit_reg $this->{base_addr};
  188. }
  189. my $hdr_data;
  190. while (<$R>) {
  191. chop;
  192. s/^\s*//;
  193. next if /^[#;]/ || /^$/;
  194. if (s/^-\s*//) {
  195. if (s/^b\s*//) {
  196. my ($bit, $addr) = split /\t+/;
  197. $bit = uc $bit;
  198. $hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) ."_$bit", bit_def($addr) . "\n";
  199. } elsif (s/^f\s*//) {
  200. s/[,\.-]/_/g;
  201. my @a = split /\s+/;
  202. my ($msb, $lsb, $this_field) = reverse @a;
  203. @a = ( { "name" => "SHIFT", "addr" => $lsb, "fmt" => "%uU", },
  204. { "name" => "MASK", "addr" => (1 << ($msb + 1)) - 1 - ((1 << $lsb) - 1), "fmt" => "0x%" . join(".", ($this{"elsize"} >> 2) x 2) . "x" } );
  205. $this{"field"} = $this_field;
  206. foreach my $ar (@a) {
  207. #print $ar->{fmt}."\n";
  208. $hdr_data .= sprintf "#define %-62s " . $ar->{"fmt"} . "\n", "CCS_" . (uc $this{"name"}) . (defined $this_field ? "_" . uc $this_field : "") . "_" . $ar->{"name"}, $ar->{"addr"} . "\n";
  209. }
  210. } elsif (s/^e\s*//) {
  211. s/[,\.-]/_/g;
  212. my ($enum, $addr) = split /\s+/;
  213. $enum = uc $enum;
  214. $hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) . (defined $this{"field"} ? "_" . uc $this{"field"} : "") ."_$enum", $addr . ($addr =~ /0x/i ? "" : "U") . "\n";
  215. } elsif (s/^l\s*//) {
  216. my ($arg, $min, $max, $elsize, @discontig) = split /\s+/;
  217. my $size;
  218. foreach my $num ($min, $max) {
  219. $num = hex $num if $num =~ /0x/i;
  220. }
  221. $hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MIN_$arg"), $min . ($min =~ /0x/i ? "" : "U") . "\n";
  222. $hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MAX_$arg"), $max . ($max =~ /0x/i ? "" : "U") . "\n";
  223. my $h = $this{argparams};
  224. $h->{$arg} = { "min" => $min,
  225. "max" => $max,
  226. "elsize" => $elsize =~ /^0x/ ? hex $elsize : $elsize,
  227. "discontig" => \@discontig };
  228. $this{discontig} = $arg if @discontig;
  229. next if $#{$this{args}} + 1 != scalar keys %{$this{argparams}};
  230. my $reg_formula = "($this{addr}";
  231. my $lim_formula;
  232. foreach my $arg (@{$this{args}}) {
  233. my $d = $h->{$arg}->{discontig};
  234. my $times = $h->{$arg}->{elsize} != 1 ?
  235. " * " . $h->{$arg}->{elsize} : "";
  236. if (@$d) {
  237. my ($lim, $offset) = split /,/, $d->[0];
  238. $reg_formula .= " + (($arg) < $lim ? ($arg)$times : $offset + (($arg) - $lim)$times)";
  239. } else {
  240. $reg_formula .= " + ($arg)$times";
  241. }
  242. $lim_formula .= (defined $lim_formula ? " + " : "") . "($arg)$times";
  243. }
  244. $reg_formula .= ")\n";
  245. $lim_formula =~ s/^\(([a-z0-9]+)\)$/$1/i;
  246. print $H tabconv sprintf("#define %-62s %s", "CCS_R_" . (uc $this{name}) .
  247. $this{arglist}, $reg_formula);
  248. print $H tabconv $hdr_data;
  249. undef $hdr_data;
  250. # Sort arguments in descending order by size
  251. @{$this{sorted_args}} = sort {
  252. $h->{$a}->{elsize} <= $h->{$b}->{elsize}
  253. } @{$this{args}};
  254. if (defined $this{discontig}) {
  255. my $da = $this{argparams}->{$this{discontig}};
  256. my ($first_discontig) = split /,/, $da->{discontig}->[0];
  257. my $max = $da->{max};
  258. $da->{max} = $first_discontig - 1;
  259. print_args(\%this, "", 0);
  260. $da->{min} = $da->{max} + 1;
  261. $da->{max} = $max;
  262. print_args(\%this, $first_discontig, 1);
  263. } else {
  264. print_args(\%this, "", 0);
  265. }
  266. next unless is_limit_reg $this{base_addr};
  267. print $LH tabconv sprintf "#define %-63s%s\n",
  268. "CCS_L_" . (uc $this{name}) . "_OFFSET(" .
  269. (join ", ", @{$this{args}}) . ")", "($lim_formula)";
  270. }
  271. if (! @{$this{args}}) {
  272. print $H tabconv($hdr_data);
  273. undef $hdr_data;
  274. }
  275. next;
  276. }
  277. my ($name, $addr, @flags) = split /\t+/, $_;
  278. my $args = [];
  279. my $sp;
  280. ($name, $addr, $args) = name_split($name, $addr) if /\(.*\)/;
  281. $name =~ s/[,\.-]/_/g;
  282. my $flagstring = "";
  283. my $size = elem_size(@flags);
  284. $flagstring .= "| CCS_FL_16BIT " if $size eq "2";
  285. $flagstring .= "| CCS_FL_32BIT " if $size eq "4";
  286. $flagstring .= "| CCS_FL_FLOAT_IREAL " if grep /^float_ireal$/, @flags;
  287. $flagstring .= "| CCS_FL_IREAL " if grep /^ireal$/, @flags;
  288. $flagstring =~ s/^\| //;
  289. $flagstring =~ s/ $//;
  290. $flagstring = "($flagstring)" if $flagstring =~ /\|/;
  291. my $base_addr = $addr;
  292. $addr = "($addr | $flagstring)" if $flagstring ne "";
  293. my $arglist = @$args ? "(" . (join ", ", @$args) . ")" : "";
  294. $hdr_data .= sprintf "#define %-62s %s\n", "CCS_R_" . (uc $name), $addr
  295. if !@$args;
  296. $name =~ s/\(.*//;
  297. %this = ( name => $name,
  298. addr => $addr,
  299. base_addr => $base_addr,
  300. argparams => {},
  301. args => $args,
  302. arglist => $arglist,
  303. elsize => $size,
  304. );
  305. if (!@$args) {
  306. $reglist .= "\t{ CCS_R_" . (uc $name) . ", 1, 0, \"" . (lc $name) . "\", NULL },\n";
  307. print $H tabconv $hdr_data;
  308. undef $hdr_data;
  309. print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . ", " .
  310. $this{elsize} . ", 0, \"$name\" },\n"
  311. if is_limit_reg $this{base_addr};
  312. }
  313. print $LH tabconv sprintf "#define %-63s%s\n",
  314. "CCS_L_" . (uc $this{name}), $limitcount++
  315. if is_limit_reg $this{base_addr};
  316. }
  317. if (defined $A) {
  318. print $A $argdescs, $reglist;
  319. print $A "\t{ 0 }\n";
  320. print $A "};\n";
  321. }
  322. print $H "\n#endif /* __${uc_header}__ */\n";
  323. print $LH tabconv sprintf "#define %-63s%s\n", "CCS_L_LAST", $limitcount;
  324. print $LH "\n#endif /* __${uc_limith}__ */\n";
  325. print $LC "\t{ 0 } /* Guardian */\n";
  326. print $LC "};\n";
  327. close($R);
  328. close($H);
  329. close($A) if defined $A;
  330. close($LC);
  331. close($LH);