From 89ac7eb5b4d61f8abce0aff99fe0a0efc2c5550a Mon Sep 17 00:00:00 2001 From: TolaMironcenko Date: Mon, 9 Feb 2026 16:47:11 +0700 Subject: [PATCH] initial commit --- .clang-format | 6 ++ .gitea/workflows/actions.yaml | 40 ++++++++ .gitignore | 4 + CMakeLists.txt | 12 +++ Makefile | 20 ++++ meson.build | 3 + src/main.c | 175 ++++++++++++++++++++++++++++++++++ 7 files changed, 260 insertions(+) create mode 100644 .clang-format create mode 100644 .gitea/workflows/actions.yaml create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 Makefile create mode 100644 meson.build create mode 100644 src/main.c diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..24fab55 --- /dev/null +++ b/.clang-format @@ -0,0 +1,6 @@ +BasedOnStyle: Google +AllowShortFunctionsOnASingleLine: false +SpaceAfterCStyleCast: true +PointerBindsToType: false +DerivePointerBinding: false +IncludeBlocks: Preserve diff --git a/.gitea/workflows/actions.yaml b/.gitea/workflows/actions.yaml new file mode 100644 index 0000000..ff5a098 --- /dev/null +++ b/.gitea/workflows/actions.yaml @@ -0,0 +1,40 @@ +name: Prepare Build and Testing executable binary +run-name: ${{ gitea.actor }} +on: [push] + +jobs: + Prepare-Build-Testing-With-Make: + runs-on: ubuntu-latest + steps: + - name: Check out repository code + uses: actions/checkout@v3 + - name: Building binary with make + run: make -j$(nproc) + + Prepare-Build-Testing-With-CMake: + runs-on: ubuntu-latest + steps: + - name: prepare-container + run: | + apt install -y cmake + - name: Check out repository code + uses: actions/checkout@v3 + - name: Building binary with CMake + run: | + mkdir build && \ + cd build && \ + cmake .. && \ + make -j$(nproc) + + Prepare-Build-Testing-With-Meson: + runs-on: ubuntu-latest + steps: + - name: prepare-container + run: | + apt install -y meson + - name: Check out repository code + uses: actions/checkout@v3 + - name: Building binary with meson + run: | + meson setup build && \ + ninja -C build diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fa68f3d --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.cache +*.o +swpb +build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b11dfb9 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required (VERSION 3.6) +project(swpb LANGUAGES C) + +set(CMAKE_C_STANDARD 23) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +FILE(GLOB_RECURSE SOURCES src/*.c) + +add_executable( + swpb + ${SOURCES} +) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a1e0dca --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +CC = gcc +CFLAGS = -Wall -g -std=gnu2x +LDFLAGS = +LIBS = +INCLUDES = +SRCS = $(wildcard src/*.c) +OBJS = $(SRCS:.c=.o) +TARGET = swpb +CROSS_COMPILE = + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CROSS_COMPILE)$(CC) $(LDFLAGS) $^ -o $@ $(LIBS) + +%.o: %.c + $(CROSS_COMPILE)$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + +clean: + rm -f $(OBJS) $(TARGET) diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..54b3d85 --- /dev/null +++ b/meson.build @@ -0,0 +1,3 @@ +project('swpb', 'c', default_options: ['cpp_std=c20']) +include_dirs = include_directories('src') +executable('swpb', 'src/main.c', include_directories: include_dirs, install: true) diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..845afdb --- /dev/null +++ b/src/main.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The Xilinx .bit format is pretty simple. It uses keys and lengths to + * divide the file. + * + * Parser source code: + * https://gist.github.com/warmonkey/49dd574fda39f88b5eed5edc92707cf2 + * + * Here is an example. Below is a hex dump from the beginning of a .bit file: + * + * 00000000: 00 09 0f f0 0f f0 0f f0 0f f0 00 00 01 61 00 0a .............a.. + * 00000010: 78 66 6f 72 6d 2e 6e 63 64 00 62 00 0c 76 31 30 xform.ncd.b..v10 + * 00000020: 30 30 65 66 67 38 36 30 00 63 00 0b 32 30 30 31 00efg860.c..2001 + * 00000030: 2f 30 38 2f 31 30 00 64 00 09 30 36 3a 35 35 3a /08/10.d..06:55: + * 00000040: 30 34 00 65 00 0c 28 18 ff ff ff ff aa 99 55 66 04.e..(.......Uf + * + * Field 1 + * 2 bytes length 0x0009 (big endian) + * 9 bytes some sort of header 0f f0 0f f0 0f f0 0f f0 00 + * + * Field 2 + * 2 bytes length 0x0001 (key-length-value below) + * + * Field 3 + * 1 byte key 0x61 (The letter "a") + * 2 bytes length 0x000a (value depends on file name length) + * 10 bytes string design name "xform.ncd" end with \0 + * + * Field 4 + * 1 byte key 0x62 (The letter "b") + * 2 bytes length 0x000c (value depends on part name length) + * 12 bytes string part name "v1000efg860" end with \0 + * + * Field 5 + * 1 byte key 0x63 (The letter "c") + * 2 bytes length 0x000b + * 11 bytes string date "2001/08/10" end with \0 + * + * Field 6 + * 1 byte key 0x64 (The letter "d") + * 2 bytes length 0x0009 + * 9 bytes string time "06:55:04" end with \0 + * + * Field 7 + * 1 byte key 0x65 (The letter "e") + * 4 bytes length 0x000c2818 (configuration length) + * + * 796696 bytes raw bitstream starting with ffff ffff aa99 5566 sync word + */ + +#define _NL "\n" + +#define _HEADBUF_SIZE 512 +static char headbuf[_HEADBUF_SIZE]; + +static void usage(char *pname) { + fprintf(stderr, "Usage: %s " _NL, pname); + fprintf(stderr, _NL); + fprintf(stderr, + "Read from bit-file (or standard input in case of \"-\") " + "\"bit\" data." _NL); + fprintf(stderr, + "Write to bin-file (or standard output in case of \"-\") " + "swapped \"bin\" data" _NL); + fprintf(stderr, _NL); +} + +/* + * Swap bytes in 32-bit word + */ +uint32_t swapb(uint32_t b) { + return (((b >> 24) & 0x000000FF) | ((b >> 8) & 0x0000FF00) | + ((b << 8) & 0x00FF0000) | ((b << 24) & 0xFF000000)); +} + +/* + * + */ +int main(int argc, char **argv) { + int ifd; + int ofd; + int rd; + int wr; + uint32_t clength; /* configuration length */ + int nopt = 0; + + if (argc < 3) { + usage(argv[0]); + return -1; + } + + ifd = 0; + ofd = 1; + +#define _INPUT_FILE (argv[nopt + 1]) +#define _OUTPUT_FILE (argv[nopt + 2]) + if (strcmp(_INPUT_FILE, "-") != 0) { + fprintf(stderr, "Input file: \"%s\"" _NL, _INPUT_FILE); + ifd = open(_INPUT_FILE, O_RDONLY); + if (ifd < 0) { + fprintf(stderr, "\"%s\" open failed" _NL, _INPUT_FILE); + goto error; + } + } + + if (strcmp(_OUTPUT_FILE, "-") != 0) { + fprintf(stderr, "Output file: \"%s\"" _NL, _OUTPUT_FILE); + ofd = open(_OUTPUT_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (ofd < 0) { + fprintf(stderr, "\"%s\" open failed" _NL, _OUTPUT_FILE); + goto error; + } + } + + clength = (uint32_t) (-1); + + { + while (clength) { + size_t n; + + n = clength; + if (n > sizeof(headbuf)) n = sizeof(headbuf); + + rd = read(ifd, headbuf, n); + if (rd < 0) { + fprintf(stderr, "RD %d" _NL, rd); + goto error; + } + + if (rd == 0) { + if (clength == (uint32_t) (-1)) goto error; + break; + } + + /* XXX 4-byte size align not checked */ + uint32_t *src, *dst; + size_t nswap; + + nswap = rd / 4; + src = (uint32_t *) headbuf; + dst = (uint32_t *) headbuf; + while (nswap--) { + *dst = swapb(*src); + + dst++; + src++; + } + + wr = write(ofd, headbuf, rd); + if (wr != rd) goto error; + + clength -= rd; + } + } + + fprintf(stderr, "Convert SUCCESS" _NL); + return 0; +error: + if (errno) + fprintf(stderr, "Failed %s" _NL, strerror(errno)); + else + fprintf(stderr, "Failed" _NL); + + if (ifd >= 0) close(ifd); + if (ofd >= 0) close(ofd); + return 1; +}