Files
libbsdl/tests/test_api.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

91 lines
2.8 KiB
C

/*
* libbsdl - API test: exercises the lifecycle + JSON layer.
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bsdl/bsdl.h"
static int failures = 0;
#define CHECK(cond) do { \
if (!(cond)) { \
fprintf(stderr, "FAIL %s:%d: %s\n", __FILE__, __LINE__, #cond); \
failures++; \
} \
} while (0)
int main(void)
{
bsdl_opts_t opts;
bsdl_t model;
char* json;
/* version is reported and matches the compiled-in macro */
CHECK(bsdl_version() != NULL);
CHECK(strcmp(bsdl_version(), BSDL_VERSION_STRING) == 0);
/* defaults are sane */
bsdl_opts_default(&opts);
CHECK(opts.sort_pins_by_name == 0);
CHECK(opts.log == NULL);
CHECK(opts.log_user == NULL);
/* defined behaviour on bad input */
CHECK(bsdl_parse_file(NULL, &opts) == NULL);
CHECK(bsdl_parse_file("/nonexistent/does-not-exist.bsd", NULL) == NULL);
CHECK(bsdl_to_json(NULL) == NULL);
bsdl_free(NULL); /* must be NULL-safe */
bsdl_string_free(NULL); /* must be NULL-safe */
/* JSON layer over a hand-built model (independent of the parser) */
{
static bsdl_pin_t pins[1];
static bsdl_instr_t instrs[1];
memset(&model, 0, sizeof(model));
memset(pins, 0, sizeof(pins));
memset(instrs, 0, sizeof(instrs));
pins[0].name = "TCK";
pins[0].dir = BSDL_DIR_IN;
pins[0].physical_pin = "W20";
pins[0].tap_role = BSDL_TAP_TCK;
pins[0].in_bit = -1;
pins[0].out_bit = -1;
pins[0].ctrl_bit = -1;
instrs[0].name = "IDCODE";
instrs[0].opcode = "001001";
model.entity = "DEMO";
model.src_filename = "demo.bsd";
model.idcode = 0x12345678UL;
model.idcode_mask = 0xFFFFFFFFUL;
model.instruction_length = 6;
model.pins = pins;
model.pin_count = 1;
model.instructions = instrs;
model.instruction_count = 1;
json = bsdl_to_json(&model);
CHECK(json != NULL);
if (json) {
CHECK(strstr(json, "\"entity\":\"DEMO\"") != NULL);
CHECK(strstr(json, "\"physical_pin\":\"W20\"") != NULL);
CHECK(strstr(json, "\"tap_role\":\"tck\"") != NULL);
CHECK(strstr(json, "\"idcode\":\"0x12345678\"") != NULL);
CHECK(strstr(json, "\"name\":\"IDCODE\"") != NULL);
bsdl_string_free(json);
}
}
if (failures) {
fprintf(stderr, "%d check(s) failed\n", failures);
return 1;
}
printf("all API checks passed\n");
return 0;
}