Compare commits
2 Commits
26231b2f48
...
3e9272255c
Author | SHA1 | Date | |
---|---|---|---|
3e9272255c | |||
4930b53c84 |
Binary file not shown.
@ -1,5 +1,8 @@
|
|||||||
#import "../src/lib.typ": *
|
#import "../src/lib.typ": *
|
||||||
#import "@preview/cetz:0.3.4": draw
|
#import "@preview/cetz:0.3.4": draw
|
||||||
|
|
||||||
|
#set text(font: "Source Sans 3")
|
||||||
|
|
||||||
#circuit({
|
#circuit({
|
||||||
element.block(
|
element.block(
|
||||||
size: (1.5, 2.2),
|
size: (1.5, 2.2),
|
||||||
@ -10,14 +13,12 @@
|
|||||||
north: (id: "CLK", clock: true),
|
north: (id: "CLK", clock: true),
|
||||||
east: "PC",
|
east: "PC",
|
||||||
south: (("EN", "EN"),)
|
south: (("EN", "EN"),)
|
||||||
),
|
)
|
||||||
debug: (ports: true)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
wire.stub("PCBuf.CLK", name: "CLK")
|
wire.stub("PCBuf.CLK", name: "CLK")
|
||||||
wire.stub("PCBuf.EN", name: "PCWrite")
|
wire.stub("PCBuf.EN", name: "PCWrite")
|
||||||
|
|
||||||
/*
|
|
||||||
element.multiplexer(
|
element.multiplexer(
|
||||||
pos: (
|
pos: (
|
||||||
3, (align: "in0", with: "PCBuf.PC")
|
3, (align: "in0", with: "PCBuf.PC")
|
||||||
@ -34,8 +35,9 @@
|
|||||||
name: "PC",
|
name: "PC",
|
||||||
bus: true
|
bus: true
|
||||||
)
|
)
|
||||||
wire.stub("AdrSrc-MP.north", name: "AdrSrc")
|
wire.stub("AdrSrc-MP.north", side: "north", name: "AdrSrc")
|
||||||
|
|
||||||
|
/*
|
||||||
element.block(
|
element.block(
|
||||||
pos: (
|
pos: (
|
||||||
6, (align: "A", with: "AdrSrc-MP.out")
|
6, (align: "A", with: "AdrSrc-MP.out")
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#let block(
|
#let block(
|
||||||
..args
|
..args
|
||||||
) = element.elmt(
|
) = element.elmt(
|
||||||
|
cls: "block",
|
||||||
draw-shape: draw-shape,
|
draw-shape: draw-shape,
|
||||||
..args
|
..args
|
||||||
)
|
)
|
@ -1,5 +1,5 @@
|
|||||||
#import "@preview/cetz:0.3.2": draw, coordinate, matrix, vector
|
#import "@preview/cetz:0.3.2": draw, coordinate, matrix, vector
|
||||||
#import "ports.typ": add-ports, add-port
|
#import "ports.typ": add-ports, add-port, get-port-pos, get-port-idx
|
||||||
#import "../util.typ"
|
#import "../util.typ"
|
||||||
|
|
||||||
#let find-port(ports, id) = {
|
#let find-port(ports, id) = {
|
||||||
@ -10,7 +10,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("Could not find port with id " + str(id))
|
panic("Could not find port with id '" + str(id) + "'")
|
||||||
}
|
}
|
||||||
|
|
||||||
#let local-to-global(origin, u, v, points) = {
|
#let local-to-global(origin, u, v, points) = {
|
||||||
@ -42,7 +42,7 @@
|
|||||||
return pos.at(axis)
|
return pos.at(axis)
|
||||||
}
|
}
|
||||||
|
|
||||||
#let resolve-align(ctx, elmt, align, with, axis) = {
|
#let resolve-align(ctx, elmt, bounds, align, with, axis) = {
|
||||||
let (align-side, i) = find-port(elmt.ports, align)
|
let (align-side, i) = find-port(elmt.ports, align)
|
||||||
let margins = (0%, 0%)
|
let margins = (0%, 0%)
|
||||||
if align-side in elmt.ports-margins {
|
if align-side in elmt.ports-margins {
|
||||||
@ -67,12 +67,12 @@
|
|||||||
let used-len = len * used-pct / 100%
|
let used-len = len * used-pct / 100%
|
||||||
start-margin = len * margins.at(0) / 100%
|
start-margin = len * margins.at(0) / 100%
|
||||||
|
|
||||||
dl = used-len * (i + 1) / (elmt.ports.at(align-side).len() + 1)
|
//dl = used-len * (i + 1) / (elmt.ports.at(align-side).len() + 1)
|
||||||
|
dl = get-port-pos(elmt, bounds, align-side, align, get-port-idx(elmt, align, side: align-side))
|
||||||
if not elmt.auto-ports {
|
/*if not elmt.auto-ports {
|
||||||
start-margin = 0
|
start-margin = 0
|
||||||
dl = elmt.ports-pos.at(with)(len)
|
dl = elmt.ports-pos.at(align)(len)
|
||||||
}
|
}*/
|
||||||
} else if align-side == ortho-sides.first() {
|
} else if align-side == ortho-sides.first() {
|
||||||
dl = 0
|
dl = 0
|
||||||
start-margin = 0
|
start-margin = 0
|
||||||
@ -89,7 +89,7 @@
|
|||||||
return with-pos.at(axis) - dl + start-margin
|
return with-pos.at(axis) - dl + start-margin
|
||||||
}
|
}
|
||||||
|
|
||||||
#let resolve-coordinate(ctx, elmt, coord, axis) = {
|
#let resolve-coordinate(ctx, elmt, bounds, coord, axis) = {
|
||||||
if type(coord) == dictionary {
|
if type(coord) == dictionary {
|
||||||
let offset = coord.at("offset", default: none)
|
let offset = coord.at("offset", default: none)
|
||||||
let from = coord.at("from", default: none)
|
let from = coord.at("from", default: none)
|
||||||
@ -105,7 +105,7 @@
|
|||||||
return resolve-offset(ctx, offset, from, axis)
|
return resolve-offset(ctx, offset, from, axis)
|
||||||
|
|
||||||
} else if none not in (align, with) {
|
} else if none not in (align, with) {
|
||||||
return resolve-align(ctx, elmt, align, with, axis)
|
return resolve-align(ctx, elmt, bounds, align, with, axis)
|
||||||
} else {
|
} else {
|
||||||
panic("Dictionnary must either provide both 'offset' and 'from', or 'align' and 'with'")
|
panic("Dictionnary must either provide both 'offset' and 'from', or 'align' and 'with'")
|
||||||
}
|
}
|
||||||
@ -116,21 +116,68 @@
|
|||||||
return coord
|
return coord
|
||||||
}
|
}
|
||||||
|
|
||||||
#let make-bounds(x, y, w, h) = {
|
#let complete-bounds(elmt, bounds) = {
|
||||||
|
let b = bounds
|
||||||
|
bounds += (
|
||||||
|
center: (
|
||||||
|
(b.br.at(0) + b.tl.at(0))/2,
|
||||||
|
(b.br.at(1) + b.tl.at(1))/2
|
||||||
|
),
|
||||||
|
b: (
|
||||||
|
(b.br.at(0) + b.bl.at(0))/2,
|
||||||
|
(b.br.at(1) + b.bl.at(1))/2
|
||||||
|
),
|
||||||
|
t: (
|
||||||
|
(b.tr.at(0) + b.tl.at(0))/2,
|
||||||
|
(b.tr.at(1) + b.tl.at(1))/2
|
||||||
|
),
|
||||||
|
l: (
|
||||||
|
(b.bl.at(0) + b.tl.at(0))/2,
|
||||||
|
(b.bl.at(1) + b.tl.at(1))/2
|
||||||
|
),
|
||||||
|
r: (
|
||||||
|
(b.br.at(0) + b.tr.at(0))/2,
|
||||||
|
(b.br.at(1) + b.tr.at(1))/2
|
||||||
|
),
|
||||||
|
sides: (
|
||||||
|
north: (bounds.tl, bounds.tr),
|
||||||
|
south: (bounds.bl, bounds.br),
|
||||||
|
west: (bounds.tl, bounds.bl),
|
||||||
|
east: (bounds.tr, bounds.br),
|
||||||
|
),
|
||||||
|
lengths: (
|
||||||
|
north: (bounds.tr.at(0) - bounds.tl.at(0)),
|
||||||
|
south: (bounds.br.at(0) - bounds.bl.at(0)),
|
||||||
|
west: (bounds.tl.at(1) - bounds.bl.at(1)),
|
||||||
|
east: (bounds.tr.at(1) - bounds.br.at(1)),
|
||||||
|
),
|
||||||
|
ports: (:)
|
||||||
|
)
|
||||||
|
for (side, props) in bounds.sides.pairs() {
|
||||||
|
let props2 = props
|
||||||
|
if side in elmt.ports-margins {
|
||||||
|
let (pt0, pt1) = props
|
||||||
|
let margins = ports-margins.at(side)
|
||||||
|
a = (pt0, margins.at(0), pt1)
|
||||||
|
b = (pt0, 100% - margins.at(1), pt1)
|
||||||
|
props2 = (a, b)
|
||||||
|
}
|
||||||
|
bounds.ports.insert(side, props2)
|
||||||
|
}
|
||||||
|
return bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
#let make-bounds(elmt, x, y, w, h) = {
|
||||||
let w2 = w / 2
|
let w2 = w / 2
|
||||||
let h2 = h / 2
|
let h2 = h / 2
|
||||||
|
|
||||||
return (
|
let bounds = (
|
||||||
bl: (x, y),
|
bl: (x, y),
|
||||||
tl: (x, y + h),
|
tl: (x, y + h),
|
||||||
tr: (x + w, y + h),
|
tr: (x + w, y + h),
|
||||||
br: (x + w, y),
|
br: (x + w, y),
|
||||||
center: (x + w2, y + h2),
|
|
||||||
b: (x + w2, y),
|
|
||||||
t: (x + w2, y + h),
|
|
||||||
l: (x, y + h2),
|
|
||||||
r: (x + w, y + h2),
|
|
||||||
)
|
)
|
||||||
|
return complete-bounds(elmt, bounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
#let render(draw-shape, elmt) = draw.group(name: elmt.id, ctx => {
|
#let render(draw-shape, elmt) = draw.group(name: elmt.id, ctx => {
|
||||||
@ -140,10 +187,10 @@
|
|||||||
let x = elmt.pos.first()
|
let x = elmt.pos.first()
|
||||||
let y = elmt.pos.last()
|
let y = elmt.pos.last()
|
||||||
|
|
||||||
x = resolve-coordinate(ctx, elmt, x, 0)
|
let bounds = make-bounds(elmt, 0, 0, width, height)
|
||||||
y = resolve-coordinate(ctx, elmt, y, 1)
|
x = resolve-coordinate(ctx, elmt, bounds, x, 0)
|
||||||
|
y = resolve-coordinate(ctx, elmt, bounds, y, 1)
|
||||||
let bounds = make-bounds(x, y, width, height)
|
bounds = make-bounds(elmt, x, y, width, height)
|
||||||
|
|
||||||
// Workaround because CeTZ needs to have all draw functions in the body
|
// Workaround because CeTZ needs to have all draw functions in the body
|
||||||
let func = {}
|
let func = {}
|
||||||
@ -171,15 +218,7 @@
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if elmt.auto-ports {
|
add-ports(elmt, bounds)
|
||||||
add-ports(
|
|
||||||
elmt.id,
|
|
||||||
bounds,
|
|
||||||
elmt.ports,
|
|
||||||
elmt.ports-margins,
|
|
||||||
debug: elmt.debug.ports
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/// Draws an element
|
/// Draws an element
|
||||||
@ -210,6 +249,7 @@
|
|||||||
/// Supported fields include:
|
/// Supported fields include:
|
||||||
/// - `ports`: if true, shows dots on all ports of the element
|
/// - `ports`: if true, shows dots on all ports of the element
|
||||||
#let elmt(
|
#let elmt(
|
||||||
|
cls: "element",
|
||||||
draw-shape: default-draw-shape,
|
draw-shape: default-draw-shape,
|
||||||
pre-process: default-pre-process,
|
pre-process: default-pre-process,
|
||||||
pos: (0, 0),
|
pos: (0, 0),
|
||||||
@ -221,11 +261,11 @@
|
|||||||
fill: none,
|
fill: none,
|
||||||
stroke: black + 1pt,
|
stroke: black + 1pt,
|
||||||
id: auto,
|
id: auto,
|
||||||
auto-ports: true,
|
ports-pos: auto,
|
||||||
ports-y: (:),
|
|
||||||
debug: (
|
debug: (
|
||||||
ports: false
|
ports: false
|
||||||
)
|
),
|
||||||
|
extra: (:)
|
||||||
) = {
|
) = {
|
||||||
for (key, side-ports) in ports.pairs() {
|
for (key, side-ports) in ports.pairs() {
|
||||||
if type(side-ports) == str {
|
if type(side-ports) == str {
|
||||||
@ -249,6 +289,7 @@
|
|||||||
|
|
||||||
|
|
||||||
return ((
|
return ((
|
||||||
|
cls: cls,
|
||||||
id: id,
|
id: id,
|
||||||
draw: render.with(draw-shape),
|
draw: render.with(draw-shape),
|
||||||
pre-process: pre-process,
|
pre-process: pre-process,
|
||||||
@ -260,8 +301,7 @@
|
|||||||
ports-margins: ports-margins,
|
ports-margins: ports-margins,
|
||||||
fill: fill,
|
fill: fill,
|
||||||
stroke: stroke,
|
stroke: stroke,
|
||||||
auto-ports: auto-ports,
|
ports-pos: ports-pos,
|
||||||
ports-y: ports-y,
|
|
||||||
debug: debug
|
debug: debug
|
||||||
),)
|
) + extra,)
|
||||||
}
|
}
|
||||||
|
@ -3,29 +3,35 @@
|
|||||||
#import "element.typ"
|
#import "element.typ"
|
||||||
#import "ports.typ": add-port
|
#import "ports.typ": add-port
|
||||||
|
|
||||||
#let draw-shape(id, tl, tr, br, bl, fill, stroke, h-ratio: 60%) = {
|
#let draw-shape(elmt, bounds) = {
|
||||||
let margin = (100% - h-ratio) / 2
|
let margin = (100% - elmt.l-ratio) / 2
|
||||||
let tr2 = (tr, margin, br)
|
let tr2 = util.lerp(bounds.tr, margin, bounds.br)
|
||||||
let br2 = (br, margin, tr)
|
let br2 = util.lerp(bounds.br, margin, bounds.tr)
|
||||||
let f = draw.group(name: id, {
|
let bounds2 = element.complete-bounds(elmt, (
|
||||||
|
tl: bounds.tl,
|
||||||
|
bl: bounds.bl,
|
||||||
|
tr: tr2,
|
||||||
|
br: br2,
|
||||||
|
))
|
||||||
|
let f = {
|
||||||
draw.merge-path(
|
draw.merge-path(
|
||||||
inset: 0.5em,
|
inset: 0.5em,
|
||||||
fill: fill,
|
fill: elmt.fill,
|
||||||
stroke: stroke,
|
stroke: elmt.stroke,
|
||||||
close: true,
|
close: true,
|
||||||
draw.line(tl, tr2, br2, bl)
|
draw.line(bounds2.tl, bounds2.tr, bounds2.br, bounds2.bl)
|
||||||
)
|
)
|
||||||
draw.anchor("north", (tl, 50%, tr2))
|
draw.anchor("north", bounds2.t)
|
||||||
draw.anchor("south", (bl, 50%, br2))
|
draw.anchor("south", bounds2.b)
|
||||||
draw.anchor("west", (tl, 50%, bl))
|
draw.anchor("west", bounds2.l)
|
||||||
draw.anchor("east", (tr2, 50%, br2))
|
draw.anchor("east", bounds2.r)
|
||||||
draw.anchor("north-west", tl)
|
draw.anchor("north-west", bounds2.tl)
|
||||||
draw.anchor("north-east", tr2)
|
draw.anchor("north-east", bounds2.tr)
|
||||||
draw.anchor("south-east", br2)
|
draw.anchor("south-east", bounds2.br)
|
||||||
draw.anchor("south-west", bl)
|
draw.anchor("south-west", bounds2.bl)
|
||||||
})
|
}
|
||||||
|
|
||||||
return (f, tl, tr, br, bl)
|
return (f, bounds2)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draws a multiplexer
|
/// Draws a multiplexer
|
||||||
@ -35,64 +41,44 @@
|
|||||||
/// - entries (int, array): If it is an integer, it defines the number of input ports (automatically named with their binary index). If it is an array of strings, it defines the name of each input.
|
/// - entries (int, array): If it is an integer, it defines the number of input ports (automatically named with their binary index). If it is an array of strings, it defines the name of each input.
|
||||||
/// - h-ratio (ratio): The height ratio of the right side relative to the full height
|
/// - h-ratio (ratio): The height ratio of the right side relative to the full height
|
||||||
#let multiplexer(
|
#let multiplexer(
|
||||||
x: none,
|
|
||||||
y: none,
|
|
||||||
w: none,
|
|
||||||
h: none,
|
|
||||||
name: none,
|
|
||||||
name-anchor: "center",
|
|
||||||
entries: 2,
|
entries: 2,
|
||||||
h-ratio: 60%,
|
l-ratio: 60%,
|
||||||
fill: none,
|
..args
|
||||||
stroke: black + 1pt,
|
|
||||||
id: "",
|
|
||||||
debug: (
|
|
||||||
ports: false
|
|
||||||
)
|
|
||||||
) = {
|
) = {
|
||||||
let ports = ()
|
let in-ports = ()
|
||||||
let ports-y = (
|
let ports-pos = (
|
||||||
out: (h) => {h * 0.5}
|
"east": auto,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (type(entries) == int) {
|
if (type(entries) == int) {
|
||||||
let nbits = calc.ceil(calc.log(entries, base: 2))
|
let nbits = calc.ceil(calc.log(entries, base: 2))
|
||||||
for i in range(entries) {
|
for i in range(entries) {
|
||||||
let bits = util.lpad(str(i, base: 2), nbits)
|
let bits = util.lpad(str(i, base: 2), nbits)
|
||||||
ports.push((id: "in" + str(i), name: bits))
|
in-ports.push((id: "in" + str(i), name: bits))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i, port) in entries.enumerate() {
|
for (i, port) in entries.enumerate() {
|
||||||
ports.push((id: "in" + str(i), name: port))
|
in-ports.push((id: "in" + str(i), name: port))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let space = 100% / ports.len()
|
let n = in-ports.len()
|
||||||
let l = ports.len()
|
ports-pos.insert("west", (l, i) => {l * (i + 0.5) / n})
|
||||||
for (i, port) in ports.enumerate() {
|
|
||||||
ports-y.insert(port.id, (h) => {h * (i + 0.5) / l})
|
|
||||||
}
|
|
||||||
|
|
||||||
element.elmt(
|
element.elmt(
|
||||||
draw-shape: draw-shape.with(h-ratio: h-ratio),
|
cls: "multiplexer",
|
||||||
x: x,
|
draw-shape: draw-shape,
|
||||||
y: y,
|
ports: (west: in-ports, east: ((id: "out"),)),
|
||||||
w: w,
|
ports-pos: ports-pos,
|
||||||
h: h,
|
extra: (l-ratio: l-ratio),
|
||||||
name: name,
|
..args
|
||||||
name-anchor: name-anchor,
|
|
||||||
ports: (west: ports, east: ((id: "out"),)),
|
|
||||||
fill: fill,
|
|
||||||
stroke: stroke,
|
|
||||||
id: id,
|
|
||||||
ports-y: ports-y,
|
|
||||||
auto-ports: false,
|
|
||||||
debug: debug
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
for (i, port) in ports.enumerate() {
|
for (i, port) in ports.enumerate() {
|
||||||
let pct = (i + 0.5) * space
|
let pct = (i + 0.5) * space
|
||||||
add-port(id, "west", port, (id+".north-west", pct, id+".south-west"))
|
add-port(id, "west", port, (id+".north-west", pct, id+".south-west"))
|
||||||
}
|
}
|
||||||
add-port(id, "east", (id: "out"), (id+".north-east", 50%, id+".south-east"))
|
add-port(id, "east", (id: "out"), (id+".north-east", 50%, id+".south-east"))
|
||||||
|
*/
|
||||||
}
|
}
|
@ -1,6 +1,74 @@
|
|||||||
#import "@preview/cetz:0.3.2": draw
|
#import "@preview/cetz:0.3.2": draw
|
||||||
#import "../util.typ": rotate-anchor
|
#import "../util.typ": rotate-anchor
|
||||||
|
|
||||||
|
#let get-port-side(elmt, port) = {
|
||||||
|
for (side, ports) in elmt.ports {
|
||||||
|
for p in ports {
|
||||||
|
if p.id == port {
|
||||||
|
return side
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("Unknown port " + port + " on element " + elmt.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let get-port-idx(elmt, port, side: auto) = {
|
||||||
|
if side == auto {
|
||||||
|
side = get-port-side(elmt, port)
|
||||||
|
}
|
||||||
|
assert(
|
||||||
|
side in elmt.ports,
|
||||||
|
message: "No ports on side '" + side + "' of element '" + elmt.id + "'"
|
||||||
|
)
|
||||||
|
let i = elmt.ports.at(side).position(p => p.id == port)
|
||||||
|
assert(
|
||||||
|
i != none,
|
||||||
|
message: "Could not find port '" + port + "' on side '" + side + "' of element '" + elmt.id + "'"
|
||||||
|
)
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
#let get-port-pos(elmt, bounds, side, port, port-i) = {
|
||||||
|
let (pt0, pt1) = bounds.ports.at(side)
|
||||||
|
let side-len = if side in ("north", "south") {
|
||||||
|
pt1.at(0) - pt0.at(0)
|
||||||
|
} else {
|
||||||
|
pt0.at(1) - pt1.at(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
let offset = if (
|
||||||
|
elmt.ports-pos == auto or
|
||||||
|
elmt.ports-pos.at(side, default: auto) == auto
|
||||||
|
) {
|
||||||
|
let space = 100% / (elmt.ports.at(side, default: ()).len() + 1)
|
||||||
|
(port-i + 1) * space
|
||||||
|
} else {
|
||||||
|
assert(
|
||||||
|
side in elmt.ports-pos,
|
||||||
|
message: "Could not reliably compute port position (missing side)"
|
||||||
|
)
|
||||||
|
let side-pos = elmt.ports-pos.at(side)
|
||||||
|
if type(side-pos) == function {
|
||||||
|
(side-pos)(side-len, port-i)
|
||||||
|
} else if type(side-pos) == array {
|
||||||
|
(side-pos.at(i))(side-len)
|
||||||
|
} else if type(side-pos) == dictionary {
|
||||||
|
assert(
|
||||||
|
port in side-pos,
|
||||||
|
message: "Could not reliably compute port position (missing port)"
|
||||||
|
)
|
||||||
|
(side-pos.at(port))(side-len)
|
||||||
|
} else {
|
||||||
|
panic("Could not reliably compute port position (invalid type)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if type(offset) == ratio {
|
||||||
|
offset = offset * side-len / 100%
|
||||||
|
}
|
||||||
|
return offset
|
||||||
|
}
|
||||||
|
|
||||||
#let add-port(
|
#let add-port(
|
||||||
elmt-id, side, port, pos,
|
elmt-id, side, port, pos,
|
||||||
prev: none,
|
prev: none,
|
||||||
@ -54,46 +122,41 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#let add-ports(
|
#let add-ports(
|
||||||
elmt-id,
|
elmt,
|
||||||
bounds,
|
bounds
|
||||||
ports,
|
|
||||||
ports-margins,
|
|
||||||
debug: false
|
|
||||||
) = {
|
) = {
|
||||||
let sides = (
|
let debug = elmt.debug.ports
|
||||||
"north": (bounds.tl, bounds.tr),
|
|
||||||
"east": (bounds.tr, bounds.br),
|
|
||||||
"south": (bounds.bl, bounds.br),
|
|
||||||
"west": (bounds.tl, bounds.bl)
|
|
||||||
)
|
|
||||||
|
|
||||||
if type(ports) != dictionary {
|
if type(elmt.ports) != dictionary {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for (side, props) in sides {
|
for (side, props) in bounds.ports {
|
||||||
let side-ports = ports.at(side, default: ())
|
let side-ports = elmt.ports.at(side, default: ())
|
||||||
let space = 100% / (side-ports.len() + 1)
|
let space = 100% / (side-ports.len() + 1)
|
||||||
|
|
||||||
|
let (pt0, pt1) = props
|
||||||
|
let side-len = if side in ("north", "south") {
|
||||||
|
pt1.at(0) - pt0.at(0)
|
||||||
|
} else {
|
||||||
|
pt0.at(1) - pt1.at(1)
|
||||||
|
}
|
||||||
for (i, port) in side-ports.enumerate() {
|
for (i, port) in side-ports.enumerate() {
|
||||||
let pct = (i + 1) * space
|
let offset = get-port-pos(elmt, bounds, side, port, i)
|
||||||
let pt0 = props.at(0)
|
|
||||||
let pt1 = props.at(1)
|
|
||||||
|
|
||||||
if side in ports-margins {
|
let pos = (pt0, offset, pt1)
|
||||||
let (a, b) = (pt0, pt1)
|
let offset-prev = if type(offset) == ratio {
|
||||||
let margins = ports-margins.at(side)
|
offset - space / 2
|
||||||
a = (pt0, margins.at(0), pt1)
|
} else {
|
||||||
b = (pt0, 100% - margins.at(1), pt1)
|
offset - space * side-len / 200%
|
||||||
pt0 = a
|
|
||||||
pt1 = b
|
|
||||||
}
|
}
|
||||||
|
let offset-next = if type(offset) == ratio {
|
||||||
let pos = (pt0, pct, pt1)
|
offset + space / 2
|
||||||
let pct-prev = (i + 0.5) * space
|
} else {
|
||||||
let pct-next = (i + 1.5) * space
|
offset + space * side-len / 200%
|
||||||
let pos-prev = (pt0, pct-prev, pt1)
|
}
|
||||||
let pos-next = (pt0, pct-next, pt1)
|
let pos-prev = (pt0, offset-prev, pt1)
|
||||||
|
let pos-next = (pt0, offset-next, pt1)
|
||||||
|
|
||||||
if port.at("small", default: false) {
|
if port.at("small", default: false) {
|
||||||
pos-prev = (pos, 4pt, pt0)
|
pos-prev = (pos, 4pt, pt0)
|
||||||
@ -101,7 +164,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
add-port(
|
add-port(
|
||||||
elmt-id,
|
elmt.id,
|
||||||
side,
|
side,
|
||||||
port,
|
port,
|
||||||
pos,
|
pos,
|
||||||
|
14
src/util.typ
14
src/util.typ
@ -75,13 +75,9 @@
|
|||||||
"north-east", "north-west", "south-east", "south-west"
|
"north-east", "north-west", "south-east", "south-west"
|
||||||
)
|
)
|
||||||
|
|
||||||
#let get-port-side(element, port) = {
|
#let lerp(pt0, ratio, pt1) = {
|
||||||
for (side, ports) in element.ports {
|
return (
|
||||||
for p in ports {
|
(pt1.at(0) - pt0.at(0)) * ratio / 100% + pt0.at(0),
|
||||||
if p.id == port {
|
(pt1.at(1) - pt0.at(1)) * ratio / 100% + pt0.at(1)
|
||||||
return side
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic("Unknown port " + port + " on element " + element.id)
|
|
||||||
}
|
}
|
33
src/wire.typ
33
src/wire.typ
@ -1,5 +1,6 @@
|
|||||||
#import "@preview/cetz:0.3.2": draw, coordinate
|
#import "@preview/cetz:0.3.2": draw, coordinate
|
||||||
#import "util.typ": opposite-anchor, get-port-side
|
#import "util.typ": opposite-anchor
|
||||||
|
#import "elements/ports.typ": get-port-side
|
||||||
#import "elements/element.typ"
|
#import "elements/element.typ"
|
||||||
|
|
||||||
/// List of valid wire styles
|
/// List of valid wire styles
|
||||||
@ -129,10 +130,11 @@
|
|||||||
/// - dodge-sides (array): The start and end sides (going out of the connected element) of the wire (only with style "dodge")
|
/// - dodge-sides (array): The start and end sides (going out of the connected element) of the wire (only with style "dodge")
|
||||||
/// - dodge-margins (array): The start and end margins (i.e. space before dodging) of the wire (only with style "dodge")
|
/// - dodge-margins (array): The start and end margins (i.e. space before dodging) of the wire (only with style "dodge")
|
||||||
#let wire(
|
#let wire(
|
||||||
id, pts,
|
pt0,
|
||||||
|
pt1,
|
||||||
|
id: none,
|
||||||
bus: false,
|
bus: false,
|
||||||
name: none,
|
name: none,
|
||||||
name-pos: "middle",
|
|
||||||
slice: none,
|
slice: none,
|
||||||
color: black,
|
color: black,
|
||||||
dashed: false,
|
dashed: false,
|
||||||
@ -144,15 +146,14 @@
|
|||||||
zigzag-dir: "vertical",
|
zigzag-dir: "vertical",
|
||||||
dodge-y: 0,
|
dodge-y: 0,
|
||||||
dodge-sides: ("east", "west"),
|
dodge-sides: ("east", "west"),
|
||||||
dodge-margins: (5%, 5%)
|
dodge-margins: (5%, 5%),
|
||||||
|
..args
|
||||||
) = draw.get-ctx(ctx => {
|
) = draw.get-ctx(ctx => {
|
||||||
if not style in wire-styles {
|
if not style in wire-styles {
|
||||||
panic("Invalid wire style '" + style + "'")
|
panic("Invalid wire style '" + style + "'")
|
||||||
}
|
}
|
||||||
|
|
||||||
if pts.len() != 2 {
|
let pts = (pt0, pt1)
|
||||||
panic("Wrong number of points (got " + str(pts.len()) + " instead of 2)")
|
|
||||||
}
|
|
||||||
|
|
||||||
let stroke = (
|
let stroke = (
|
||||||
paint: color,
|
paint: color,
|
||||||
@ -217,7 +218,7 @@
|
|||||||
let names = ()
|
let names = ()
|
||||||
|
|
||||||
if type(name) == str {
|
if type(name) == str {
|
||||||
names = ((name, name-pos),)
|
names = ((name, "middle"),)
|
||||||
|
|
||||||
} else if type(name) == array {
|
} else if type(name) == array {
|
||||||
names = (
|
names = (
|
||||||
@ -227,6 +228,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (name, pos) in names {
|
for (name, pos) in names {
|
||||||
|
if name == none {
|
||||||
|
continue
|
||||||
|
}
|
||||||
let point
|
let point
|
||||||
let anchor
|
let anchor
|
||||||
|
|
||||||
@ -268,7 +272,7 @@
|
|||||||
/// - vertical (bool): Whether the name should be displayed vertically
|
/// - vertical (bool): Whether the name should be displayed vertically
|
||||||
/// - length (number): The length of the stub
|
/// - length (number): The length of the stub
|
||||||
/// - name-offset (number): The name offset, perpendicular to the stub
|
/// - name-offset (number): The name offset, perpendicular to the stub
|
||||||
#let stub(anchor, name: none, vertical: false, length: 1em, name-offset: 0) = {
|
#let stub(anchor, side: auto, name: none, vertical: false, length: 1em, name-offset: 0) = {
|
||||||
if "." not in anchor {
|
if "." not in anchor {
|
||||||
panic("`anchor` must be a valid anchor of an element")
|
panic("`anchor` must be a valid anchor of an element")
|
||||||
}
|
}
|
||||||
@ -279,11 +283,14 @@
|
|||||||
let pre-process = (elements, elmt) => {
|
let pre-process = (elements, elmt) => {
|
||||||
let eid = elmt.id
|
let eid = elmt.id
|
||||||
|
|
||||||
if port-elmt-id not in elements {
|
let side = side
|
||||||
panic("Unknown element " + port-elmt-id)
|
if side == auto {
|
||||||
|
if port-elmt-id not in elements {
|
||||||
|
panic("Unknown element " + port-elmt-id)
|
||||||
|
}
|
||||||
|
let port-elmt = elements.at(port-elmt-id)
|
||||||
|
side = get-port-side(port-elmt, port-id)
|
||||||
}
|
}
|
||||||
let port-elmt = elements.at(port-elmt-id)
|
|
||||||
let side = get-port-side(port-elmt, port-id)
|
|
||||||
elements.at(eid).insert("side", side)
|
elements.at(eid).insert("side", side)
|
||||||
return elements
|
return elements
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user