commit ef1f6e02acac83f1c32800a25739183bdeb2bed7
parent 5360a03924e8be5e9b17ec750fa442fc93eb0161
Author: Roberto Vargas <roberto.vargas@arm.com>
Date: Wed, 10 Oct 2018 15:17:52 +0100
Add scripts for rscb code generation from json files
Diffstat:
12 files changed, 368 insertions(+), 11 deletions(-)
diff --git a/include/.gitignore b/include/.gitignore
@@ -0,0 +1 @@
+types.h
diff --git a/include/types.h b/include/types.h
@@ -1,10 +0,0 @@
-#if __GNUC__ || __clang__
-#define UNPACKFMT __attribute__ ((format (scanf, 2, 3)))
-#define PACKFMT __attribute__ ((format (printf, 2, 3)))
-#else
-#define UNPACKFMT
-#define PACKFMT
-#endif
-
-extern int unpack(uint64_t buf[], const char *fmt, ...) UNPACKFMT;
-extern int pack(uint64_t buf[], const char *fmt, ...) PACKFMT;
diff --git a/scripts/gencode.sh b/scripts/gencode.sh
@@ -0,0 +1,113 @@
+#/bin/sh
+
+sed '/prototypes/q' "$@" |
+awk '
+BEGIN {RS=""; FS="\n"}
+/^struct/ {split($1, w, " "); parse(w[2])}
+END {for (tag in structs) {
+ gen("pack", tag)
+ gen("unpack", tag)}}
+
+function parse(tag, fldnam,nfields,i,j,v,typ)
+{
+ nfields = 0
+ for (i = 2; i < NF; i++) {
+ split($i, v, "#")
+ nbits = int(v[2])
+
+ sub(/^[ \t]*/, "", $i)
+ sub(/;.*/, "", $i)
+ n = split($i, v, /[ \t]*/)
+
+ fldnam = v[n]
+ typ = ""
+ for (j = 1; j < n; j++) {
+ if (typ != "")
+ typ = typ " "
+ typ = typ v[j]
+ }
+ fields[tag, nfields++] = typ SUBSEP fldnam SUBSEP nbits
+ }
+ structs[tag] = nfields
+}
+
+function buildfmt(tag, i,v,typ,nbits,fmt)
+{
+ for (i = 0; i < structs[tag]; i++) {
+ split(fields[tag, i], v, SUBSEP)
+ typ = v[1]
+ nbits = v[3]
+ if (typ ~ "struct")
+ fmt = fmt buildfmt(substr(typ, 8))
+ else if (typ ~ /unsigned char/)
+ fmt = fmt "%" nbits "c "
+ else if (typ ~ /unsigned short/)
+ fmt = fmt "%" nbits "hu "
+ else if (typ ~ /unsigned long long/)
+ fmt = fmt "%" nbits "llu "
+ else if (typ ~ /unsigned long/)
+ fmt = fmt "%" nbits "lu "
+ }
+ return fmt
+}
+
+function printfmt(tag,file, fmt,n,i,j,v)
+{
+ fmt = buildfmt(tag)
+ sub(/ *$/, "", fmt)
+ n = split(fmt, v, / /)
+
+ for (i = 1; i <= n; i += 7) {
+ fmt = ""
+ for (j = 0; j < 7 && i + j <= n; j++) {
+ if (fmt != "")
+ fmt = fmt " "
+ fmt = fmt v[i+j]
+ }
+ printf("\t \"%s\"%s",
+ fmt, (i+7 < n) ? "\n" : ",\n") >> file
+ }
+}
+
+function gen(fun, tag, file)
+{
+ file = fun "_" tag ".c"
+
+ printf("#include <assert.h>\n"\
+ "#include <stdint.h>\n\n"\
+ "#include <types.h>\n"\
+ "#include <arch/machine.h>\n\n"\
+ "int\n"\
+ "%s_%s(uint64_t buf[], struct %s *sp)\n"\
+ "{\n"\
+ "\tint n;\n\n"\
+ "\tn = %s(buf,\n", fun, tag, tag, fun) > file
+
+ printfmt(tag, file)
+ printargs(fun, tag, "", file)
+
+ print ");\n\n\tassert(n == sizeof(*sp));\n\n"\
+ "\treturn n;\n"\
+ "}" >> file
+
+ close(file)
+}
+
+function printargs(fun,tag,prefix,file, i,v,typ,fldnam)
+{
+ for (i = 0; i < structs[tag]; i++) {
+ split(fields[tag, i], v, SUBSEP)
+ fldnam = v[2]
+ typ = v[1]
+ if (typ ~ "struct") {
+ printargs(fun, substr(typ, 8), prefix fldnam ".", file)
+ } else {
+ printf("\t %ssp->%s%s",
+ (fun == "unpack") ? "&" : "",
+ prefix, fldnam) >> file
+ }
+ if (i != structs[tag]-1)
+ print "," >> file
+ }
+}
+'
diff --git a/scripts/genheaders.sh b/scripts/genheaders.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+awk '
+/^[^\t]/ {struct = $1; nbits = 1}
+
+/^\t[^\t]/ {if (fldname != "")
+ fldname = fldname "#"
+ fldname = fldname $1
+ fldsize[$1] = $2
+ fldbegin[$1] = nbits
+ last = $1
+ next}
+
+/^\t\t/ {bitnam[nbits] = $1
+ bitset[nbits] = $2
+ fldcnt[last]++
+ nbits++}
+
+END {split(fldname, names, "#")
+ gentypes()
+ genstruct()
+ genprotos()}
+
+function genprotos( t)
+{
+ print "/* prototypes */"
+ for (t in list) {
+ printf("extern int pack_%s(uint64_t buf[], struct %s *sp);\n"\
+ "extern int unpack_%s(uint64_t buf[], struct %s *sp);\n\n",
+ t, t, t, t);
+ }
+}
+
+function gentypes( f,bs,n,fld,off,res,i,name)
+{
+ for (f in names) {
+ fld = names[f]
+ if (fldcnt[fld] == 1)
+ continue
+ off = fldbegin[fld]
+ res = 0
+
+ print "struct " struct "_" fld " {"
+ for (i = 0; i < fldcnt[fld]; i++) {
+ n = off + i
+ name = bitnam[n]
+ if (name == "res0")
+ name = "res0_" res++
+ bs = bitset[n]
+ printf("\t%s %s;\t\t//#%d\n", type(bs), name, getbits(bs))
+ }
+ print "};\n"
+ list[struct "_" fld] = 1
+ }
+}
+
+function genstruct( f,fld,t,s,bs)
+{
+ printf("struct %s {\n", struct)
+ for (f in names) {
+ fld = names[f]
+ s = fldsize[fld]
+ t = (fldcnt[fld] == 1) ? type(s) : "struct rscb_" fld
+ printf("\t%s %s;\t\t//#%d\n", t, fld, s)
+ }
+ print "};\n"
+}
+
+
+function getbits(desc, arr,n)
+{
+ n = split(desc, arr, ":")
+ if (n == 1)
+ return 1
+ return arr[1] - arr[2]
+}
+
+function type(desc, siz)
+{
+ siz = getbits(desc)
+
+ if (siz <= 8)
+ return "unsigned char"
+ if (siz <= 16)
+ return "unsigned short"
+ if (siz <= 32)
+ return "unsigned long"
+ if (siz <= 64)
+ return "unsigned long long"
+ print "error"
+}
+' "$@"
diff --git a/scripts/genrscb.sh b/scripts/genrscb.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+set -e
+trap 'rm -f pack_*.c unpack_*.c rscb.h;exit 1' HUP INT QUIT
+
+for i
+do
+ case $i in
+ -j)
+ jsondir="-I $2"
+ shift 2
+ ;;
+ --)
+ shift
+ ;;
+ -*)
+ echo usage: genrscb.sh [-j jsondir] [file] >&2
+ exit 1
+ ;;
+ esac
+done
+
+jinc.sh $jsondir "$@" |
+rscb.sh |
+tr 'A-Z' 'a-z' |
+genheaders.sh |
+tee rscb.h |
+gencode.sh
diff --git a/scripts/gentbl.sh b/scripts/gentbl.sh
@@ -19,7 +19,6 @@ do
shift
;;
-*)
- echo i=$i
echo usage: gentbl.sh [-o file] >&2
exit 1
;;
diff --git a/scripts/jinc.sh b/scripts/jinc.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+
+include="."
+
+for i
+do
+ case $i in
+ -I)
+ include=$2
+ shift 2
+ ;;
+ --)
+ shift
+ ;;
+ -*)
+ echo usage: jinc.sh [-I dir] [file] >&2
+ exit 1
+ ;;
+ esac
+done
+
+awk -v inc=$include '
+match($0, /"_include" *: *"[^"]*"/) {
+ pre = substr($0, 1, RSTART-1)
+ post = substr($0, RSTART+RLENGTH)
+ incl = substr($0, RSTART, RLENGTH)
+
+
+ split(incl, v, /:/)
+ incl = v[2]
+ gsub(/ *" */, "", incl)
+ nf = split(incl, v, /\//)
+
+ file = v[nf]
+ dir = inc
+ for (i = 1; i < nf; i++)
+ dir = dir "/" v[i]
+
+ print pre, "\"_include\":"
+ system("cd " dir " && jinc.sh " file)
+ print post
+
+ next
+}
+ {print}' "$@"
diff --git a/scripts/rscb.sh b/scripts/rscb.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+jq -r '
+.register_blocks[0]._include |
+{name,
+ registers: .registers |
+ map(._include) |
+ map({name, fieldsets: .fieldsets |
+ map({width,
+ values: .values |
+ map({name, value, rangeset})})})} |
+.name,
+(.registers |
+ map("\t" +
+ (.name | ltrimstr("RSCB_")) +
+ "\t" + (.fieldsets[0].width | tostring),
+ (.fieldsets |
+ map(.values |
+ map("\t\t\t" +
+ .name +
+ .value +
+ "\t" +
+ .rangeset)[])[])))[]'
diff --git a/scripts/rules.mk b/scripts/rules.mk
@@ -7,6 +7,7 @@ BINDIR = $(PROJECTDIR)/bin
ARCHDIR = $(PROJECTDIR)/arch/$(ARCH)
SRCDIR = $(PROJECTDIR)/src
SCRIPTDIR= $(PROJECTDIR)/scripts
+JSONDIR = $(PROJECTDIR)/json
INCLUDES = -I$(INCDIR) -I$(INCDIR)/bits/$(ARCH)/ -I$(INCDIR)/bits/$(SYS)
RCODE_CFLAGS = $(MORECFLAGS) \
diff --git a/src/libtypes/.gitignore b/src/libtypes/.gitignore
@@ -0,0 +1 @@
+rscb.h
diff --git a/src/libtypes/Makefile b/src/libtypes/Makefile
@@ -2,12 +2,23 @@ PROJECTDIR=../..
include $(PROJECTDIR)/scripts/rules.mk
OBJS = pack.o unpack.o
+
+RMSA = $(JSONDIR)/RMSA.json
TARGET = $(LIBDIR)/libtypes.a
$(TARGET): $(OBJS)
all: $(TARGET)
+gen: rscb.h FORCE
+ ./gendep.sh -I $(INCDIR) rscb.h
+
+rscb.h: $(JSONDIR)/version
+ PATH=$(SCRIPTDIR):$$PATH genrscb.sh -j $(JSONDIR) $(RMSA)
+
$(TARGET): $(OBJS)
$(AR) $(ARFLAGS) $@ $?
ranlib $@
+
+clean:
+ rm -f rscb.h
diff --git a/src/libtypes/gendep.sh b/src/libtypes/gendep.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+set -e
+
+for i
+do
+ case $i in
+ -I)
+ inc=$2/
+ shift 2
+ ;;
+ --)
+ shift
+ ;;
+ -*)
+ echo usage: gendep.sh [-I dir] files ... >&2
+ exit 1
+ esac
+done
+
+tmp=tmp1.$$
+trap 'rm -f $tmp1 $tmp2;exit $?' EXIT HUP INT QUIT
+
+
+(cat <<'EOF'
+#if __GNUC__ || __clang__
+#define UNPACKFMT __attribute__ ((format (scanf, 2, 3)))
+#define PACKFMT __attribute__ ((format (printf, 2, 3)))
+#else
+#define UNPACKFMT
+#define PACKFMT
+#endif
+
+extern int unpack(uint64_t buf[], const char *fmt, ...) UNPACKFMT;
+extern int pack(uint64_t buf[], const char *fmt, ...) PACKFMT;
+EOF
+
+cat "$@") > $tmp && mv $tmp ${inc}types.h
+
+(echo H
+echo '/^OBJS/;/^$/c'
+printf 'OBJS = pack.o unpack.o \\\n'
+for i
+do
+ sed -n '/prototypes/,$ {
+ /prototypes/d
+ /^$/d
+ s/extern int \(.*\)(.*/ \1.o \\/p
+ }' $i
+done
+printf "\n.\nw\n"
+) | ed -s Makefile