Files
circuiteria/src/elements/ports.typ
T
purpl3F0x 55ea5cdef6 Add Verilog parsing and rendering support
- Introduced `verilog.typ` for parsing Verilog/SystemVerilog source code, supporting both ANSI and non-ANSI port styles.
- Implemented functions to analyze modules, infer AXI4, AXI4-Lite, and AXI4-Stream buses, as well as clock and reset signals.
- Added rendering capabilities for Verilog modules, allowing for visual representation of ports and buses.
- Created a new `gallery/verilog.typ` file to facilitate the drawing of Verilog blocks in diagrams.

Signed-off-by: Stavros Avramidis <stavros9899@gmail.com>
2026-09-10 12:00:25 +01:00

131 lines
2.9 KiB
Typst

#import "/src/cetz.typ": draw
#import "../util.typ": rotate-anchor
#let add-port(
elmt-id, side, port, pos,
prev: none,
next: none,
debug: false
) = {
let name = port.at("name", default: "")
let name-rotate = port.at("vertical", default: false)
if (port.at("clock", default: false)) {
if prev == none or next == none {
panic("Clock port must have previous and next positions")
}
let size = if port.at("small", default: false) {8pt} else {1em}
let offset
if (side == "north") { offset = ( 0, -size) }
else if (side == "east") { offset = (-size, 0) }
else if (side == "south") { offset = ( 0, size) }
else if (side == "west") { offset = ( size, 0) }
let pos1 = (rel: offset, to: pos)
// TODO: use context or vectors to have the height relative to the width
draw.line(prev, pos1, next)
}
if (port.at("invert", default: false)) {
let r = 0.1
let offset
if (side == "north") { offset = ( 0, r) }
else if (side == "east") { offset = ( r, 0) }
else if (side == "south") { offset = ( 0, -r) }
else if (side == "west") { offset = ( -r, 0) }
draw.circle(
(rel: offset, to: pos),
radius: r,
fill: white,
stroke: black + 1pt
)
}
draw.content(
pos,
anchor: if name-rotate {rotate-anchor(side)} else {side},
padding: 2pt,
angle: if name-rotate {90deg} else {0deg},
name
)
let id = elmt-id + "-port-" + port.at("id")
if debug {
draw.circle(
pos,
name: id,
radius: .1,
stroke: none,
fill: red
)
} else {
draw.hide(draw.circle(
pos,
radius: 0,
stroke: none,
name: id
))
}
}
#let add-ports(
elmt-id,
tl, tr, br, bl,
ports,
ports-margins,
debug: false
) = {
let sides = (
"north": (tl, tr),
"east": (tr, br),
"south": (bl, br),
"west": (tl, bl)
)
if type(ports) != dictionary {
return
}
for (side, props) in sides {
let side-ports = ports.at(side, default: ())
let space = 100% / (side-ports.len() + 1)
for (i, port) in side-ports.enumerate() {
let pct = (i + 1) * space
let pt0 = props.at(0)
let pt1 = props.at(1)
if side in ports-margins {
let (a, b) = (pt0, pt1)
let margins = ports-margins.at(side)
a = (pt0, margins.at(0), pt1)
b = (pt0, 100% - margins.at(1), pt1)
pt0 = a
pt1 = b
}
let pos = (pt0, pct, pt1)
let pct-prev = (i + 0.5) * space
let pct-next = (i + 1.5) * space
let pos-prev = (pt0, pct-prev, pt1)
let pos-next = (pt0, pct-next, pt1)
if port.at("small", default: false) {
pos-prev = (pos, 4pt, pt0)
pos-next = (pos, 4pt, pt1)
}
add-port(
elmt-id,
side,
port,
pos,
prev: pos-prev,
next: pos-next,
debug: debug
)
}
}
}