Files
libbsdl/tools/bsdl2json.c
François 6b56ab5c42 libbsdl: scaffold + working BSDL parser (struct + JSON, C ABI)
Standalone LGPL-2.1 parser for BSDL (IEEE 1149.1), shared by essim and
bs_explorer. The parser is ported from the Viveris JTAG Core loader,
decoupled from jtag_core, and extended with two extractions the original
lacks:
  - PIN_MAP_STRING -> per-port physical package pin, scalar and vector;
  - TAP_SCAN_*     -> TAP signal roles (TDI/TDO/TMS/TCK/TRST).

Exposes a stable C ABI (bsdl_parse_file/buffer -> bsdl_t, bsdl_to_json)
with a dependency-free JSON serializer and a bsdl2json CLI. CMake builds a
versioned shared library with install/export rules for find_package(bsdl).

Verified against m2gl010t, xcku040 and xcku15p (100% pin mapping, correct
IDCODEs and TAP roles); api and parse regression tests pass, clean build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 10:27:13 +02:00

78 lines
1.8 KiB
C

/*
* bsdl2json - parse a BSDL file and print the model as JSON on stdout.
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* Thin frontend over libbsdl. essim invokes this out-of-process; bs_explorer
* links the library directly and uses the struct instead.
*/
#include <stdio.h>
#include <string.h>
#include "bsdl/bsdl.h"
static void log_cb(bsdl_log_level_t level, const char* msg, void* user)
{
static const char* const names[] = { "ERROR", "WARN", "INFO", "DEBUG" };
(void)user;
fprintf(stderr, "[bsdl:%s] %s\n", names[level], msg);
}
static void usage(const char* argv0)
{
fprintf(stderr,
"libbsdl %s\n"
"usage: %s [--quiet] <file.bsd>\n"
" prints the parsed BSDL model as JSON on stdout\n",
bsdl_version(), argv0);
}
int main(int argc, char** argv)
{
bsdl_opts_t opts;
const char* path = NULL;
int quiet = 0;
int i;
bsdl_t* model;
char* json;
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "--quiet") || !strcmp(argv[i], "-q")) {
quiet = 1;
} else if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) {
usage(argv[0]);
return 0;
} else if (argv[i][0] == '-') {
fprintf(stderr, "unknown option: %s\n", argv[i]);
usage(argv[0]);
return 2;
} else {
path = argv[i];
}
}
if (!path) {
usage(argv[0]);
return 2;
}
bsdl_opts_default(&opts);
if (!quiet)
opts.log = log_cb;
model = bsdl_parse_file(path, &opts);
if (!model) {
fprintf(stderr, "error: failed to parse %s\n", path);
return 1;
}
json = bsdl_to_json(model);
if (json) {
fputs(json, stdout);
fputc('\n', stdout);
bsdl_string_free(json);
}
bsdl_free(model);
return 0;
}