/* * libbsdl - Standalone BSDL (IEEE 1149.1) parser with a stable C ABI. * * Copyright (c) 2026 François * Seeded from the Viveris JTAG Core BSDL loader (Jean-François DEL NERO). * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 2.1 as * published by the Free Software Foundation. See the LICENSE file. */ /** * @file bsdl.h * @brief Public C API for libbsdl: parse a .bsd file into a struct, or to JSON. * * Design notes * ------------ * - Pure C ABI: callable as-is from C (bs_explorer) and, via `extern "C"`, * from C++ (essim). Keep this header free of C++/struct-layout churn. * - `bsdl_t` is a SUPERSET model; consumers read only the fields they need. * Extend it additively (append fields/enum values) — never reorder/remove — * so the shared .so stays ABI-stable for both projects. * - Ownership: every pointer reachable from a `bsdl_t*` is owned by the model * and released by bsdl_free(). Do not free individual members. */ #ifndef LIBBSDL_BSDL_H #define LIBBSDL_BSDL_H #include /* -------- version -------- */ #define BSDL_VERSION_MAJOR 0 #define BSDL_VERSION_MINOR 1 #define BSDL_VERSION_PATCH 0 #define BSDL_VERSION_STRING "0.1.0" /* -------- symbol visibility / export -------- */ #if defined(_WIN32) # if defined(BSDL_BUILD_SHARED) # define BSDL_API __declspec(dllexport) # elif !defined(BSDL_STATIC) # define BSDL_API __declspec(dllimport) # else # define BSDL_API # endif #else # if defined(BSDL_BUILD_SHARED) # define BSDL_API __attribute__((visibility("default"))) # else # define BSDL_API # endif #endif #ifdef __cplusplus extern "C" { #endif /* -------- enumerations (stable values; append-only) -------- */ /** Logical port direction (from the VHDL port clause). */ typedef enum bsdl_dir { BSDL_DIR_UNKNOWN = 0, BSDL_DIR_IN, BSDL_DIR_OUT, BSDL_DIR_INOUT, BSDL_DIR_BUFFER, BSDL_DIR_LINKAGE /**< power / ground / NC — Viveris folds these to UNKNOWN. */ } bsdl_dir_t; /** TAP signal role, derived from the TAP_SCAN_* attributes. */ typedef enum bsdl_tap_role { BSDL_TAP_NONE = 0, BSDL_TAP_TDI, /**< TAP_SCAN_IN */ BSDL_TAP_TDO, /**< TAP_SCAN_OUT */ BSDL_TAP_TMS, /**< TAP_SCAN_MODE */ BSDL_TAP_TCK, /**< TAP_SCAN_CLOCK */ BSDL_TAP_TRST /**< TAP_SCAN_RESET */ } bsdl_tap_role_t; /** Boundary-register cell type (BC_1 .. BC_7). */ typedef enum bsdl_cell { BSDL_CELL_UNKNOWN = 0, BSDL_CELL_BC1, BSDL_CELL_BC2, BSDL_CELL_BC3, BSDL_CELL_BC4, BSDL_CELL_BC5, BSDL_CELL_BC6, BSDL_CELL_BC7 } bsdl_cell_t; /** Boundary-register cell function. */ typedef enum bsdl_bittype { BSDL_BIT_UNKNOWN = 0, BSDL_BIT_INPUT, BSDL_BIT_OUTPUT, BSDL_BIT_TRISTATE, BSDL_BIT_INOUT, BSDL_BIT_CONTROL, BSDL_BIT_INTERNAL } bsdl_bittype_t; /** Safe / disable logic state. */ typedef enum bsdl_state { BSDL_STATE_UNKNOWN = 0, BSDL_STATE_UNDEF, /**< 'X' */ BSDL_STATE_HIGH, /**< '1' */ BSDL_STATE_LOW, /**< '0' */ BSDL_STATE_HIGHZ /**< 'Z' */ } bsdl_state_t; /* -------- model structures -------- */ /** A logical port plus its physical mapping and boundary-cell links. */ typedef struct bsdl_pin { const char* name; /**< logical port name, e.g. "TCK", "IO_A2". */ bsdl_dir_t dir; const char* physical_pin; /**< package ball/pin from PIN_MAP_STRING, e.g. "W20"; NULL if unmapped. */ bsdl_tap_role_t tap_role; /**< non-NONE if this port is a TAP signal. */ int in_bit; /**< boundary-register input bit index, or -1. */ int out_bit; /**< boundary-register output bit index, or -1. */ int ctrl_bit; /**< controlling bit index, or -1. */ } bsdl_pin_t; /** One entry of the BOUNDARY_REGISTER. */ typedef struct bsdl_cell_entry { int index; bsdl_cell_t cell; const char* port; /**< associated port name, or "*" when unnamed. */ bsdl_bittype_t type; bsdl_state_t safe; int ctrl_index; /**< controlling cell index, or -1. */ bsdl_state_t disable_state; bsdl_state_t disable_result; } bsdl_cell_entry_t; /** One INSTRUCTION_OPCODE entry. */ typedef struct bsdl_instr { const char* name; /**< e.g. "IDCODE", "EXTEST", "BYPASS", "SAMPLE". */ const char* opcode; /**< bit string, e.g. "001000". */ } bsdl_instr_t; /** The parsed device model. All pointers owned by the model (see bsdl_free). */ typedef struct bsdl { const char* entity; /**< entity name (device identifier). */ const char* src_filename; /**< basename of the source file. */ unsigned long idcode; /**< IDCODE value (X bits read as 0). */ unsigned long idcode_mask; /**< 1 where the IDCODE bit is fixed, 0 where 'X'. */ int instruction_length; bsdl_pin_t* pins; size_t pin_count; bsdl_cell_entry_t* chain; size_t chain_count; bsdl_instr_t* instructions; size_t instruction_count; } bsdl_t; /* -------- options & diagnostics -------- */ typedef enum bsdl_log_level { BSDL_LOG_ERROR = 0, BSDL_LOG_WARN, BSDL_LOG_INFO, BSDL_LOG_DEBUG } bsdl_log_level_t; /** Optional diagnostic sink. Replaces Viveris' jtag_core logging dependency. */ typedef void (*bsdl_log_fn)(bsdl_log_level_t level, const char* msg, void* user); typedef struct bsdl_opts { int sort_pins_by_name; /**< replaces the BSDL_LOADER_SORT_PINS_NAME env var. */ bsdl_log_fn log; /**< may be NULL. */ void* log_user; /**< passed back to `log`. */ } bsdl_opts_t; /** Fill `opts` with defaults (no sorting, no logging). */ BSDL_API void bsdl_opts_default(bsdl_opts_t* opts); /* -------- API -------- */ /** Parse a BSDL file. Returns NULL on error. Free with bsdl_free(). */ BSDL_API bsdl_t* bsdl_parse_file(const char* path, const bsdl_opts_t* opts); /** Parse a BSDL document held in memory. `name` is recorded as src_filename. */ BSDL_API bsdl_t* bsdl_parse_buffer(const char* text, size_t len, const char* name, const bsdl_opts_t* opts); /** Release a model returned by a bsdl_parse_* function. NULL-safe. */ BSDL_API void bsdl_free(bsdl_t* model); /** Serialize a model to a freshly allocated JSON string (compact, UTF-8). * Returns NULL on allocation failure or NULL input. Free with bsdl_string_free(). */ BSDL_API char* bsdl_to_json(const bsdl_t* model); /** Free a string returned by bsdl_to_json(). NULL-safe. */ BSDL_API void bsdl_string_free(char* s); /** Library version, e.g. "0.1.0". */ BSDL_API const char* bsdl_version(void); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* LIBBSDL_BSDL_H */