From f9ac81d68ea0eaaab856792d87be4c847e4a8df5 Mon Sep 17 00:00:00 2001 From: Gustavo Martin Date: Sun, 14 Dec 2025 19:48:34 +0100 Subject: [PATCH] Squashed commit --- src/colibri/documenter/diagram.ts | 15 +- src/colibri/documenter/doxygen_parser.ts | 41 +++- src/colibri/parser/common.ts | 1 + test_keepports_diagram.ts | 54 ++++++ tests/documenter/complete/entity.vhdlSource | 27 ++- .../entity_vhdlSource_html/output.html | 178 +++++++++++++++++- .../output.markdown | 66 +++++-- 7 files changed, 344 insertions(+), 38 deletions(-) create mode 100644 test_keepports_diagram.ts diff --git a/src/colibri/documenter/diagram.ts b/src/colibri/documenter/diagram.ts index 4d3e99eb..e0510d03 100644 --- a/src/colibri/documenter/diagram.ts +++ b/src/colibri/documenter/diagram.ts @@ -164,8 +164,21 @@ function get_ports(hdl_element: common_hdl.Hdl_element) { const port_list = hdl_element.get_port_array(); const port_list_vbus = doxygen.get_virtual_bus(port_list); let complete_list: any[] = []; + + // Add normal ports (not part of virtual buses) complete_list = complete_list.concat(port_list_vbus.port_list); - complete_list = complete_list.concat(port_list_vbus.v_port_list); + + // Process virtual buses + for (const virtual_bus of port_list_vbus.v_port_list) { + if (virtual_bus.keepports) { + // If @keepports is enabled, expand virtual bus to show individual ports + complete_list = complete_list.concat(virtual_bus.port_list); + } else { + // If @keepports is not enabled, show virtual bus as single entity + complete_list.push(virtual_bus); + } + } + return complete_list; } diff --git a/src/colibri/documenter/doxygen_parser.ts b/src/colibri/documenter/doxygen_parser.ts index 478beb06..e4ff5fce 100644 --- a/src/colibri/documenter/doxygen_parser.ts +++ b/src/colibri/documenter/doxygen_parser.ts @@ -67,6 +67,7 @@ export function parse_virtualbus_init(description: string) { name: '', direction: 'in', notable: false, + keepports: false, description: '', to_delete: '' }; @@ -83,6 +84,7 @@ export function parse_virtualbus_init(description: string) { result.notable = true; corpus = notable_element.text; } + //Port name const virtual_port_element = parse_element('virtualbus', corpus); if (virtual_port_element.element_list.length === 0) { @@ -96,14 +98,21 @@ export function parse_virtualbus_init(description: string) { // Direction const direction_port_element = parse_element('dir', corpus); - if (direction_port_element.element_list.length === 0) { - result.description = corpus.trim(); - return result; + if (direction_port_element.element_list.length !== 0) { + corpus = direction_port_element.element_list[0].description.trim(); + element_0 = get_first_element(corpus); + result.direction = element_0.name; + corpus = element_0.text.trim(); + } + + // Keep ports + const keepports_element = is_keepports(corpus); + if (keepports_element.is_in === true) { + result.keepports = true; + corpus = keepports_element.text; } - corpus = direction_port_element.element_list[0].description.trim(); - element_0 = get_first_element(corpus); - result.direction = element_0.name; - result.description = element_0.text.trim(); + + result.description = corpus.trim(); if (result.is_in === true) { return result; } @@ -125,6 +134,20 @@ function is_notable(text: string) { return result; } +function is_keepports(text: string) { + const regex = /@keepports/gms; + const element_parser = text.match(regex); + const result = { + text: text, + is_in: false + }; + if (element_parser !== null) { + result.is_in = true; + result.text = text.replace(regex, '').trim(); + } + return result; +} + function get_first_element(text: string) { let corpus_split = text.split(' '); const name = corpus_split[0]; @@ -188,6 +211,7 @@ export function get_virtual_bus(port_list: common_hdl.Port_hdl[]) { }, direction: virtual_port.direction, notable: virtual_port.notable, + keepports: virtual_port.keepports, port_list: [], type: "virtual_bus" }; @@ -196,7 +220,7 @@ export function get_virtual_bus(port_list: common_hdl.Port_hdl[]) { info: { position: port_i.info.position, name: port_i.info.name, - description: port_description.replace(virtual_port.to_delete, '') + description: port_i.inline_comment.trim() }, inline_comment: "", over_comment: "", @@ -279,6 +303,7 @@ export function get_virtual_bus(port_list: common_hdl.Port_hdl[]) { }, direction: virtual_port.direction, notable: virtual_port.notable, + keepports: virtual_port.keepports, port_list: [], type: "virtual_bus" }; diff --git a/src/colibri/parser/common.ts b/src/colibri/parser/common.ts index 9787dcb8..22c329b0 100644 --- a/src/colibri/parser/common.ts +++ b/src/colibri/parser/common.ts @@ -114,6 +114,7 @@ export type Virtual_bus_hdl = { info: Common_info; direction: string; notable: boolean; + keepports: boolean; port_list: Port_hdl[]; type: string; }; diff --git a/test_keepports_diagram.ts b/test_keepports_diagram.ts new file mode 100644 index 00000000..cb52239c --- /dev/null +++ b/test_keepports_diagram.ts @@ -0,0 +1,54 @@ +import { documenter_factory } from "../src/colibri/documenter/factory"; +import { HDL_LANG } from "../src/colibri/common/general"; +import { Diagram } from "../src/colibri/documenter/diagram"; +import * as fs from "fs"; +import * as path from "path"; + +async function test_keepports_diagram() { + const test_file = path.join(__dirname, "test_keepports_diagram.vhdl"); + const vhdl_code = fs.readFileSync(test_file, "utf8"); + + console.log("Testing @keepports diagram functionality..."); + + // Create documenter + const documenter = documenter_factory(HDL_LANG.VHDL); + + // Parse the VHDL code + const result = await documenter.get_documentation(vhdl_code, { + language: HDL_LANG.VHDL, + path: test_file, + configuration: { + enable_markdown: true, + enable_comments: true + } + }); + + console.log("Parsed entities:", result.length); + + if (result.length > 0) { + const entity = result[0]; + console.log("Entity name:", entity.name); + console.log("Number of ports:", entity.port.length); + console.log("Virtual buses:", entity.virtual_bus); + + // Create diagram + const diagram = new Diagram(); + const svg_content = diagram.get_entity_as_svg(entity); + + // Save diagram to file for visual inspection + const output_file = path.join(__dirname, "keepports_diagram_test.svg"); + fs.writeFileSync(output_file, svg_content); + console.log("Diagram saved to:", output_file); + + // Check virtual bus properties + entity.virtual_bus.forEach((vbus, index) => { + console.log(`Virtual bus ${index + 1}:`); + console.log(` Name: ${vbus.name}`); + console.log(` Description: ${vbus.description}`); + console.log(` Keepports: ${vbus.keepports}`); + console.log(` Ports: ${vbus.port_list.map(p => p.name).join(", ")}`); + }); + } +} + +test_keepports_diagram().catch(console.error); \ No newline at end of file diff --git a/tests/documenter/complete/entity.vhdlSource b/tests/documenter/complete/entity.vhdlSource index 56ea8264..b6cca787 100644 --- a/tests/documenter/complete/entity.vhdlSource +++ b/tests/documenter/complete/entity.vhdlSource @@ -78,15 +78,34 @@ entity test_entity_name is --! @virtualbus v_bus_1 @keepports Description of virtual bus 1 j : in std_logic := '1'; l : out std_logic; - m : in std_logic; + m : in std_logic; --! @end --! @virtualbus v_bus_2 Description of virtual bus 2 n : in std_logic; --! Description 3 - o : out std_logic; --! @end - p : in std_logic; + o : out std_logic; + p : in std_logic; --! @end q : out std_logic; --! Inline comment r : in std_logic; --! Over comment - s : out std_logic --! Preference inline + s : out std_logic; --! Preference inline + --! @virtualbus video_in_axi_stream @dir in a slave axi stream interface for video in + video_in_tdata : in std_logic_vector(23 downto 0); --! axis data bus + video_in_tlast : in std_logic; --! axis last + video_in_tuser : in std_logic_vector(0 downto 0); --! axis user + video_in_tvalid : in std_logic; --! axis valid handshake signal + video_in_tready : out std_logic; --! axis ready handshake signal + --! @end + --! @virtualbus video_out_axi_stream @dir out @keepports a master axi stream interface for video out + video_out_tdata : out std_logic_vector(23 downto 0); --! axis data bus video_out + video_out_tlast : out std_logic; --! axis last + video_out_tuser : out std_logic_vector(0 downto 0); --! axis user + video_out_tvalid : out std_logic; --! axis valid handshake signal + video_out_tready : in std_logic; --! axis ready handshake signal + --! @end + --! @virtualbus SPI @dir out description of SPI + cs : OUT std_logic; --! Chip select + clk_out: OUT std_logic; --! SPI clock + miso: OUT std_logic; --! Master in slave out + mosi: OUT std_logic --! Master out slave in @end ); end test_entity_name; diff --git a/tests/documenter/complete/expected/entity_vhdlSource_html/output.html b/tests/documenter/complete/expected/entity_vhdlSource_html/output.html index 51425f34..33917a5f 100644 --- a/tests/documenter/complete/expected/entity_vhdlSource_html/output.html +++ b/tests/documenter/complete/expected/entity_vhdlSource_html/output.html @@ -1100,7 +1100,7 @@

Entity: test_entity_name

Diagram

integer a std_logic b std_logic_vector(1 downto 0) c std_logic_vector(1 downto 0) d std_logic e std_logic ee std_logic_vector(31 downto 0) h std_logic_vector(31 downto 0) i std_logic p std_logic r virtual_bus v_bus_1 std_logic q std_logic s virtual_bus v_bus_0 +

Diagram

integer a std_logic b std_logic_vector(1 downto 0) c std_logic_vector(1 downto 0) d std_logic e std_logic ee std_logic_vector(31 downto 0) h std_logic_vector(31 downto 0) i std_logic r std_logic j std_logic m virtual_bus v_bus_2 virtual_bus video_in_axi_stream std_logic video_out_tready std_logic q std_logic s std_logic f std_logic ff std_logic g std_logic l std_logic_vector(23 downto 0) video_out_tdata std_logic video_out_tlast std_logic_vector(0 downto 0) video_out_tuser std_logic video_out_tvalid virtual_bus SPI

Description

This is an entity description 5 multiline.

Example of multiline code snipet:

int* versions = 0x0080000000 ;
int* major = 0x0090000000 ;
int* minor = 0x00A0000000 ;
int* patch = 0x00B0000000 ;
print_version();

Example of multiline code snipet:

function sum(a : integer := 0; b : integer := 0)
return integer is
variable result : integer;
begin
result <= a + b;
return result;
end function;

Example of description beakline

Example of Wavedrom

image:


pclkPclknclkNclkclk0clk1clk2clk3clk4

Example of bitfield:


06711121415192031opcoderdfunc3rs1imm[11:0]OP-IMMdestADDISLTISLTIUANDIORIXORIsrcI-immediate[11:0]

Generics

@@ -1174,12 +1174,6 @@

Ports

- - - - - - @@ -1201,13 +1195,37 @@

Ports

- + - + + + + + + + + + + + + + + + + + + + + + + + + +
pinstd_logic
q out std_logic v_bus_0 out Virtual bus@keepports Description of virtual bus 0Description of virtual bus 0
v_bus_1 in Virtual bus@keepports Description of virtual bus 1Description of virtual bus 1
v_bus_2inVirtual busDescription of virtual bus 2
video_in_axi_streaminVirtual busa slave axi stream interface for video in
video_out_axi_streamoutVirtual busa master axi stream interface for video out
SPIoutVirtual busdescription of SPI
@@ -1272,6 +1290,19 @@

v_bus_1

std_logic + + +

v_bus_2

+ + + + + + + + + + @@ -1284,6 +1315,135 @@

v_bus_1

+ + + + + + + +
Port nameDirectionTypeDescription
n in std_logic
pinstd_logic
+

video_in_axi_stream

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Port nameDirectionTypeDescription
video_in_tdatainstd_logic_vector(23 downto 0)axis data bus
video_in_tlastinstd_logicaxis last
video_in_tuserinstd_logic_vector(0 downto 0)axis user
video_in_tvalidinstd_logicaxis valid handshake signal
video_in_treadyoutstd_logicaxis ready handshake signal
+

video_out_axi_stream

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Port nameDirectionTypeDescription
video_out_tdataoutstd_logic_vector(23 downto 0)axis data bus video_out
video_out_tlastoutstd_logicaxis last
video_out_tuseroutstd_logic_vector(0 downto 0)axis user
video_out_tvalidoutstd_logicaxis valid handshake signal
video_out_treadyinstd_logicaxis ready handshake signal
+

SPI

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Port nameDirectionTypeDescription
csoutstd_logicChip select
clk_outoutstd_logicSPI clock
misooutstd_logicMaster in slave out
mosioutstd_logicMaster out slave in

Signals

diff --git a/tests/documenter/complete/expected/entity_vhdlSource_markdown/output.markdown b/tests/documenter/complete/expected/entity_vhdlSource_markdown/output.markdown index 4bd0e0f7..cd7ec117 100644 --- a/tests/documenter/complete/expected/entity_vhdlSource_markdown/output.markdown +++ b/tests/documenter/complete/expected/entity_vhdlSource_markdown/output.markdown @@ -44,7 +44,7 @@ image: -![alt text](wavedrom_yTaI0.svg "title") +![alt text](wavedrom_6Vtl0.svg "title") @@ -52,7 +52,7 @@ Example of bitfield: -![alt text](wavedrom_xpwo1.svg "title") +![alt text](wavedrom_wHVW1.svg "title") @@ -69,17 +69,20 @@ Example of bitfield: ## Ports -| Port name | Direction | Type | Description | -| --------- | --------- | ----------------------------- | ---------------------------------------- | -| ee | in | std_logic | Over comment in ```port``` | -| h | in | std_logic_vector(31 downto 0) | | -| i | in | std_logic_vector(31 downto 0) | | -| p | in | std_logic | | -| q | out | std_logic | Inline comment | -| r | in | std_logic | | -| s | out | std_logic | Preference inline | -| v_bus_0 | out | Virtual bus | @keepports Description of virtual bus 0 | -| v_bus_1 | in | Virtual bus | @keepports Description of virtual bus 1 | +| Port name | Direction | Type | Description | +| -------------------- | --------- | ----------------------------- | ------------------------------------------- | +| ee | in | std_logic | Over comment in ```port``` | +| h | in | std_logic_vector(31 downto 0) | | +| i | in | std_logic_vector(31 downto 0) | | +| q | out | std_logic | Inline comment | +| r | in | std_logic | | +| s | out | std_logic | Preference inline | +| v_bus_0 | out | Virtual bus | Description of virtual bus 0 | +| v_bus_1 | in | Virtual bus | Description of virtual bus 1 | +| v_bus_2 | in | Virtual bus | Description of virtual bus 2 | +| video_in_axi_stream | in | Virtual bus | a slave axi stream interface for video in | +| video_out_axi_stream | out | Virtual bus | a master axi stream interface for video out | +| SPI | out | Virtual bus | description of SPI | ### Virtual Buses @@ -92,13 +95,44 @@ Example of bitfield: | g | inout | std_logic | | #### v_bus_1 +| Port name | Direction | Type | Description | +| --------- | --------- | --------- | ----------- | +| j | in | std_logic | | +| l | out | std_logic | | +| m | in | std_logic | | +#### v_bus_2 + | Port name | Direction | Type | Description | | --------- | --------- | --------- | ------------- | -| j | in | std_logic | | -| l | out | std_logic | | -| m | in | std_logic | | | n | in | std_logic | Description 3 | | o | out | std_logic | | +| p | in | std_logic | | +#### video_in_axi_stream + +| Port name | Direction | Type | Description | +| --------------- | --------- | ----------------------------- | --------------------------- | +| video_in_tdata | in | std_logic_vector(23 downto 0) | axis data bus | +| video_in_tlast | in | std_logic | axis last | +| video_in_tuser | in | std_logic_vector(0 downto 0) | axis user | +| video_in_tvalid | in | std_logic | axis valid handshake signal | +| video_in_tready | out | std_logic | axis ready handshake signal | +#### video_out_axi_stream + +| Port name | Direction | Type | Description | +| ---------------- | --------- | ----------------------------- | --------------------------- | +| video_out_tdata | out | std_logic_vector(23 downto 0) | axis data bus video_out | +| video_out_tlast | out | std_logic | axis last | +| video_out_tuser | out | std_logic_vector(0 downto 0) | axis user | +| video_out_tvalid | out | std_logic | axis valid handshake signal | +| video_out_tready | in | std_logic | axis ready handshake signal | +#### SPI + +| Port name | Direction | Type | Description | +| --------- | --------- | --------- | ------------------- | +| cs | out | std_logic | Chip select | +| clk_out | out | std_logic | SPI clock | +| miso | out | std_logic | Master in slave out | +| mosi | out | std_logic | Master out slave in | ## Signals