Move gen_fx_consts to NitroSDK folder

This commit is contained in:
Nomura 2023-07-18 18:45:56 +02:00
parent 31fc5236cb
commit ef8cd95c12
8 changed files with 138 additions and 301 deletions

View File

@ -0,0 +1,138 @@
#!/usr/bin/env python3
import argparse
import csv
import math
class FxSpec:
intpart_dict = {
'fx32': 19,
'fx64': 51,
'fx64c': 31,
'fx16': 3
}
fracpart_dict = {
'fx32': 12,
'fx64': 12,
'fx64c': 32,
'fx16': 12
}
l_suffix_dict = {
'fx32': 'L',
'fx64': 'LL',
'fx64c': 'LL',
'fx16': ''
}
def __init__(self, name: str) -> 'FxSpec':
self.name = name
@property
def intpart(self):
return self._intpart
@intpart.getter
def intpart(self):
return self.intpart_dict[self.name]
@property
def fracpart(self):
return self._fracpart
@fracpart.getter
def fracpart(self):
return self.fracpart_dict[self.name]
@property
def l_suffix(self):
return self._l_suffix
@l_suffix.getter
def l_suffix(self):
return self.l_suffix_dict[self.name]
class FxConst:
def __init__(self, name: str, fxtype: FxSpec, value: float) -> 'FxConst':
self.fxtype = fxtype
self.name = name
self.value = value
@property
def name(self):
return self._name
@name.setter
def name(self, value: str):
self._name = f'{self.fxtype.name.upper()}_{value}'
def encode(self) -> int:
if self.value == 0:
return 0
ret_di = 0.0
ret_df = 0.0
value_abs = 0.0
ret_ii = 0
ret_if = 0
ret_val = 0
value_abs = abs(self.value)
ret_di = math.floor(value_abs)
ret_df = value_abs - ret_di
ret_ii = int(value_abs * (1 << self.fxtype.fracpart))
ret_if = int(ret_df * (1 << self.fxtype.fracpart) + 0.5)
ret_ii &= ~((1 << self.fxtype.fracpart) - 1)
ret_if &= (1 << self.fxtype.fracpart) - 1
ret_val = ret_ii + ret_if
if self.value < 0:
ret_val = -ret_val
return ret_val
def generate_define(c: FxConst) -> str:
hex_value = f'(({c.fxtype.name}) 0x{hex(c.encode())[2:].zfill(16)}{c.fxtype.l_suffix})'
comment = f'// {c.value:.12f}'
return f'#define {c.name: <20} {hex_value: ^20} {comment: >25}'
def generate_header(constants: list[FxConst]) -> str:
guard_top = '\n'.join(['#ifndef FX_CONST_H', '#define FX_CONST_H', str()])
body = '\n'.join(generate_define(c) for c in constants)
guard_bottom = '\n'.join(['', '#endif // FX_CONST_H', ''])
return '\n'.join([guard_top, body, guard_bottom])
def main():
args = parse_args()
constants = parse_csv(args.input)
header = generate_header(constants)
with open(args.output, 'w') as out:
out.write(header)
def parse_args():
parser = argparse.ArgumentParser(description='fx_const.h header generator')
parser.add_argument('input', type=str)
parser.add_argument('output', type=str)
return parser.parse_args()
def parse_csv(path: str) -> list[FxConst]:
with open(path, newline='') as file:
reader = csv.reader(file)
return list(
FxConst(
row[0], FxSpec(row[1]), float(row[2]))
for row in reader if not row[0].startswith('#'))
if __name__ == '__main__':
main()

View File

@ -1 +0,0 @@
gen_fx_consts

View File

@ -1,31 +0,0 @@
#ifndef GUARD_FX_H
#define GUARD_FX_H
#include <string.h>
struct FxSpec {
const char *name;
int intpart;
int fracpart;
};
struct FxConst {
char *name;
const struct FxSpec *fxtype;
double value;
};
extern struct FxConst *gFxConstTable;
extern size_t gNFxConstTable;
// Init and delete the above two objects
void FxConstTableInit(void);
void FxConstTableEnd(void);
// Generates the integer value of the fixed-point value represented by FxConst*
long long MakeFix(const struct FxConst *constdef);
// For FxSpec*, get the width in bits.
int GetFxWidth(const struct FxSpec *fxtype);
#endif //GUARD_FX_H

View File

@ -1,128 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include "fx.h"
#include "global.h"
const struct FxSpec fx32 = {"fx32", 19, 12};
const struct FxSpec fx64 = {"fx64", 51, 12};
const struct FxSpec fx64c = {"fx64c", 31, 32};
const struct FxSpec fx16 = {"fx16", 3, 12};
const struct FxSpec *const sFxSpecPtrs[] = {
&fx32,
&fx64,
&fx64c,
&fx16,
};
struct FxConst *gFxConstTable = NULL;
size_t gNFxConstTable = 0;
void FxConstTableInit(void) {
FILE *file;
char *contents;
char *ptr;
char *linetok;
char *linetok_r;
char *commatok;
char *commatok_r;
char *_realpath;
int i, j, k;
long fsize;
long readsz;
static const char filename[] = SOURCE_DIR "/fx_const.csv";
atexit(FxConstTableEnd);
file = fopen(filename, "r");
if (file == NULL) {
fatal_error("Unable to open file '%s' for reading", filename);
}
fseek(file, 0, SEEK_END);
fsize = ftell(file);
fseek(file, 0, SEEK_SET);
contents = malloc(fsize + 1);
if (contents == NULL) {
fclose(file);
fatal_error("Unable to allocate CSV read buffer");
}
readsz = fread(contents, 1, fsize, file);
fclose(file);
if (readsz != fsize) {
free(contents);
fatal_error("Read error");
}
contents[fsize] = 0;
ptr = contents - 1;
gNFxConstTable = 0;
do {
ptr++;
gNFxConstTable += (*ptr != '#' && *ptr != '\n');
ptr = strchr(ptr, '\n');
} while (ptr != NULL);
if (gNFxConstTable == 0) {
free(contents);
fatal_error("Malformatted CSV file");
}
gFxConstTable = malloc(gNFxConstTable * sizeof(struct FxConst));
if (gFxConstTable == NULL) {
free(contents);
fatal_error("Unable to allocate gFxConstTable");
}
ptr = contents;
for (i = 0; i < gNFxConstTable; i++) {
linetok = strtok_r(ptr, "\n", &linetok_r);
ptr = NULL;
if (linetok == NULL) {
gNFxConstTable = i;
break;
}
if (*linetok == '#') {
i--;
continue;
}
for (j = 0; j < 3; j++) {
commatok = strtok_r(linetok, ",", &commatok_r);
linetok = NULL;
if (commatok == NULL) {
free(contents);
fatal_error("Malformatted CSV file at line %d col %d", i, j);
}
switch (j) {
case 0:
gFxConstTable[i].name = strdup(commatok);
break;
case 1:
for (k = 0; k < len(sFxSpecPtrs); k++) {
if (strcmp(commatok, sFxSpecPtrs[k]->name) == 0) {
break;
}
}
if (k == len(sFxSpecPtrs)) {
free(contents);
fatal_error("Invalid fx type %s", commatok);
}
gFxConstTable[i].fxtype = sFxSpecPtrs[k];
break;
case 2:
gFxConstTable[i].value = strtod(commatok, NULL);
break;
}
}
}
free(contents);
}
void FxConstTableEnd(void) {
int i;
if (gFxConstTable != NULL) {
for (i = 0; i < gNFxConstTable; i++) {
if (gFxConstTable[i].name != NULL) {
free(gFxConstTable[i].name);
}
}
free(gFxConstTable);
gFxConstTable = NULL;
}
gNFxConstTable = 0;
}

View File

@ -1,28 +0,0 @@
#include <math.h>
#include "fx.h"
long long MakeFix(const struct FxConst *constdef) {
double ret_di, ret_df, value_abs;
long long ret_ii, ret_if, ret_val;
if (constdef->value == 0) {
return 0LL;
}
value_abs = constdef->value < 0 ? -constdef->value : constdef->value;
ret_di = floor(value_abs);
ret_df = value_abs - ret_di;
ret_ii = (long long)value_abs * (1LL << constdef->fxtype->fracpart);
ret_if = (long long)(ret_df * (double)(1LL << constdef->fxtype->fracpart) + 0.5);
ret_ii &= ~((1LL << constdef->fxtype->fracpart) - 1);
ret_if &= (1LL << constdef->fxtype->fracpart) - 1;
ret_val = ret_ii + ret_if;
if (constdef->value < 0) {
ret_val = -ret_val;
}
return ret_val;
}
int GetFxWidth(const struct FxSpec *fxtype) {
return fxtype->fracpart + fxtype->intpart + 1;
}

View File

@ -1,27 +0,0 @@
#ifndef GUARD_GLOBAL_H
#define GUARD_GLOBAL_H
#include <stdio.h>
#include <stdnoreturn.h>
#include <stdarg.h>
#include <stdlib.h>
#define len(a) ((sizeof(a))/(sizeof(*(a))))
static inline noreturn __attribute__((format(printf, 1, 2))) void fatal_error(const char *fmt, ...) {
va_list va_args;
va_start(va_args, fmt);
vfprintf(stderr, fmt, va_args);
va_end(va_args);
fputc('\n', stderr);
exit(1);
}
#ifndef __clang__
#undef strlcat
#define strlcat(d,s,n) strncat(d,s,(n)-strlen(d)-1)
#undef strlcpy
#define strlcpy(d,s,n) strncpy(d,s,(n)-1)
#endif //__clang__
#endif //GUARD_GLOBAL_H

View File

@ -1,86 +0,0 @@
#include <string.h>
#include <ctype.h>
#include "fx.h"
#include "global.h"
#define NAMEBUF_SIZ 32
static inline void usage(FILE *dest) {
fprintf(dest, "USAGE: gen_fx_consts FILENAME\n\n"
"FILENAME Path to write C header. Guard will be generated\n"
" automatically from the path.\n");
}
int main(int argc, char ** argv) {
int i;
char namebuf[NAMEBUF_SIZ] = "";
char *header_guard;
FILE *outfile;
FxConstTableInit();
if (argc < 2) {
outfile = stdout;
header_guard = "NITRO_FX_FX_CONST_H_";
} else {
outfile = fopen(argv[1], "w");
if (outfile == NULL) {
fatal_error("Unable to open file '%s' for writing", argv[1]);
}
header_guard = strdup(argv[1]);
if (header_guard == NULL) {
fclose(outfile);
fatal_error("Unable to allocate temp buffer for header guard");
}
for (i = 0; header_guard[i]; i++) {
switch (header_guard[i]) {
case '.':
case '/':
header_guard[i] = '_';
break;
default:
header_guard[i] = toupper(header_guard[i]);
break;
}
}
}
fprintf(outfile, "#ifndef %s_\n"
"#define %s_\n\n", header_guard, header_guard);
for (i = 0; i < gNFxConstTable; i++) {
long long value;
int nbyte;
char *suffix;
char *fmtstr;
int j;
value = MakeFix(&gFxConstTable[i]);
nbyte = GetFxWidth(gFxConstTable[i].fxtype) / 8;
switch (nbyte) {
case 2:
suffix = "";
fmtstr = "#define %-32s ((%s) 0x%04hx%s) // %.12f\n";
value &= 0xFFFFLL;
break;
case 4:
suffix = "L";
fmtstr = "#define %-32s ((%s) 0x%08lx%s) // %.12f\n";
value &= 0xFFFFFFFFLL;
break;
case 8:
suffix = "LL";
fmtstr = "#define %-32s ((%s) 0x%016llx%s) // %.12f\n";
break;
default:
fatal_error("invalid integer width: %d", nbyte);
}
snprintf(namebuf, NAMEBUF_SIZ, "%s_%s", gFxConstTable[i].fxtype->name, gFxConstTable[i].name);
for (j = 0; j < NAMEBUF_SIZ && namebuf[j]; j++) {
namebuf[j] = toupper(namebuf[j]);
}
fprintf(outfile, fmtstr, namebuf, gFxConstTable[i].fxtype->name, value, suffix, gFxConstTable[i].value);
}
fprintf(outfile, "\n#endif //%s_\n", header_guard);
if (argc >= 2) {
fclose(outfile);
free(header_guard);
}
return 0;
}