forked from HEL/circuiteria
split up sources into manageable files
This commit is contained in:
84
src/elements/alu.typ
Normal file
84
src/elements/alu.typ
Normal file
@ -0,0 +1,84 @@
|
||||
#import "@preview/cetz:0.2.2": draw
|
||||
#import "element.typ"
|
||||
#import "ports.typ": add-port
|
||||
|
||||
#let draw-shape(id, tl, tr, br, bl, fill, stroke) = {
|
||||
let p0 = tl
|
||||
let p1 = (tr, 10%, br)
|
||||
let p2 = (tr, 90%, br)
|
||||
let p3 = bl
|
||||
let p4 = (tl, 55%, bl)
|
||||
let p5 = (tl, 50%, br)
|
||||
let p6 = (tl, 45%, bl)
|
||||
|
||||
let f1 = draw.group(name: id, {
|
||||
|
||||
draw.merge-path(
|
||||
inset: 0.5em,
|
||||
fill: fill,
|
||||
stroke: stroke,
|
||||
close: true,
|
||||
draw.line(p0, p1, p2, p3, p4, p5, p6)
|
||||
)
|
||||
draw.anchor("north", (p0, 50%, p1))
|
||||
draw.anchor("south", (p2, 50%, p3))
|
||||
draw.anchor("west", (p0, 50%, p3))
|
||||
draw.anchor("east", (p1, 50%, p2))
|
||||
})
|
||||
|
||||
let f2 = add-port(id, "west", (id: "in1"), (p0, 50%, p6))
|
||||
let f3 = add-port(id, "west", (id: "in2"), (p3, 50%, p4))
|
||||
let f4 = add-port(id, "east", (id: "out"), (p1, 50%, p2))
|
||||
|
||||
let f = {
|
||||
f1; f2; f3; f4
|
||||
}
|
||||
|
||||
return (f, tl, tr, br, bl)
|
||||
}
|
||||
|
||||
#let alu(
|
||||
x: none,
|
||||
y: none,
|
||||
w: none,
|
||||
h: none,
|
||||
name: none,
|
||||
name-anchor: "center",
|
||||
fill: none,
|
||||
stroke: black + 1pt,
|
||||
id: "",
|
||||
debug: (
|
||||
grid: false,
|
||||
ports: false
|
||||
)
|
||||
) = {
|
||||
let ports = (
|
||||
west: (
|
||||
(id: "in1"),
|
||||
(id: "in2"),
|
||||
),
|
||||
east: (
|
||||
(id: "out"),
|
||||
)
|
||||
)
|
||||
|
||||
element.elmt(
|
||||
draw-shape: draw-shape,
|
||||
x: x,
|
||||
y: y,
|
||||
w: w,
|
||||
h: h,
|
||||
name: name,
|
||||
name-anchor: name-anchor,
|
||||
ports: ports,
|
||||
fill: fill,
|
||||
stroke: stroke,
|
||||
id: id,
|
||||
auto-ports: false,
|
||||
ports-y: (
|
||||
in1: (h) => {h * 0.225},
|
||||
in2: (h) => {h * 0.775},
|
||||
),
|
||||
debug: debug
|
||||
)
|
||||
}
|
46
src/elements/block.typ
Normal file
46
src/elements/block.typ
Normal file
@ -0,0 +1,46 @@
|
||||
#import "@preview/cetz:0.2.2": draw
|
||||
#import "element.typ"
|
||||
|
||||
#let draw-shape(id, tl, tr, br, bl, fill, stroke) = {
|
||||
let f = draw.rect(
|
||||
radius: 0.5em,
|
||||
inset: 0.5em,
|
||||
fill: fill,
|
||||
stroke: stroke,
|
||||
name: id,
|
||||
bl, tr
|
||||
)
|
||||
return (f, tl, tr, br, bl)
|
||||
}
|
||||
|
||||
#let block(
|
||||
x: none,
|
||||
y: none,
|
||||
w: none,
|
||||
h: none,
|
||||
name: none,
|
||||
name-anchor: "center",
|
||||
ports: (),
|
||||
ports-margins: (),
|
||||
fill: none,
|
||||
stroke: black + 1pt,
|
||||
id: "",
|
||||
debug: (
|
||||
grid: false,
|
||||
ports: false
|
||||
)
|
||||
) = element.elmt(
|
||||
draw-shape: draw-shape,
|
||||
x: x,
|
||||
y: y,
|
||||
w: w,
|
||||
h: h,
|
||||
name: name,
|
||||
name-anchor: name-anchor,
|
||||
ports: ports,
|
||||
ports-margins: ports-margins,
|
||||
fill: fill,
|
||||
stroke: stroke,
|
||||
id: id,
|
||||
debug: debug
|
||||
)
|
99
src/elements/element.typ
Normal file
99
src/elements/element.typ
Normal file
@ -0,0 +1,99 @@
|
||||
#import "@preview/cetz:0.2.2": draw, coordinate
|
||||
#import "ports.typ": add-ports, add-port
|
||||
|
||||
#let find-port(ports, id) = {
|
||||
for (side, side-ports) in ports {
|
||||
for (i, port) in side-ports.enumerate() {
|
||||
if port.id == id {
|
||||
return (side, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
panic("Could not find port with id " + str(id))
|
||||
}
|
||||
|
||||
#let default-draw-shape(id, tl, tr, br, bl, fill, stroke) = {
|
||||
return ({}, tl, tr, br, bl)
|
||||
}
|
||||
|
||||
#let elmt(
|
||||
draw-shape: default-draw-shape,
|
||||
x: none,
|
||||
y: none,
|
||||
w: none,
|
||||
h: none,
|
||||
name: none,
|
||||
name-anchor: "center",
|
||||
ports: (),
|
||||
ports-margins: (),
|
||||
fill: none,
|
||||
stroke: black + 1pt,
|
||||
id: "",
|
||||
auto-ports: true,
|
||||
ports-y: (),
|
||||
debug: (
|
||||
grid: false,
|
||||
ports: false
|
||||
)
|
||||
) = draw.get-ctx(ctx => {
|
||||
let width = w
|
||||
let height = h
|
||||
|
||||
let y = y
|
||||
if x == none { panic("Parameter x must be set") }
|
||||
if y == none { panic("Parameter y must be set") }
|
||||
if w == none { panic("Parameter w must be set") }
|
||||
if h == none { panic("Parameter h must be set") }
|
||||
|
||||
if (type(y) == dictionary) {
|
||||
let from = y.from
|
||||
let to = y.to
|
||||
let (to-side, i) = find-port(ports, to)
|
||||
let margins = (0%, 0%)
|
||||
if to-side in ports-margins {
|
||||
margins = ports-margins.at(to-side)
|
||||
}
|
||||
let used-pct = 100% - margins.at(0) - margins.at(1)
|
||||
let used-height = height * used-pct / 100%
|
||||
let top-margin = height * margins.at(0) / 100%
|
||||
|
||||
let dy = used-height * (i + 1) / (ports.at(to-side).len() + 1)
|
||||
|
||||
if not auto-ports {
|
||||
top-margin = 0
|
||||
dy = ports-y.at(to)(height)
|
||||
}
|
||||
|
||||
let (ctx, from-pos) = coordinate.resolve(ctx, from)
|
||||
y = from-pos.at(1) + dy - height + top-margin
|
||||
}
|
||||
|
||||
let tl = (x, y + height)
|
||||
let tr = (x + width, y + height)
|
||||
let br = (x + width, y)
|
||||
let bl = (x, y)
|
||||
|
||||
// Workaround because CeTZ needs to have all draw functions in the body
|
||||
let func = {}
|
||||
(func, tl, tr, br, bl) = draw-shape(id, tl, tr, br, bl, fill, stroke)
|
||||
func
|
||||
|
||||
if (name != none) {
|
||||
draw.content(
|
||||
(name: id, anchor: name-anchor),
|
||||
anchor: name-anchor,
|
||||
padding: 0.5em,
|
||||
align(center)[*#name*]
|
||||
)
|
||||
}
|
||||
|
||||
if auto-ports {
|
||||
add-ports(
|
||||
id,
|
||||
tl, tr, br, bl,
|
||||
ports,
|
||||
ports-margins,
|
||||
debug: debug.ports
|
||||
)
|
||||
}
|
||||
})
|
66
src/elements/extender.typ
Normal file
66
src/elements/extender.typ
Normal file
@ -0,0 +1,66 @@
|
||||
#import "@preview/cetz:0.2.2": draw
|
||||
#import "element.typ"
|
||||
|
||||
#let draw-shape(id, tl, tr, br, bl, fill, stroke) = {
|
||||
let (x, y) = bl
|
||||
let (width, height) = (tr.at(0) - x, tr.at(1) - y)
|
||||
|
||||
tl = (x, y + height * 0.75)
|
||||
let tr2 = (x + width, y + height * 0.75)
|
||||
let br = (x + width, y)
|
||||
(tr, tr2) = (tr2, tr)
|
||||
let f = draw.group(name: id, {
|
||||
draw.merge-path(
|
||||
inset: 0.5em,
|
||||
fill: fill,
|
||||
stroke: stroke,
|
||||
close: true,
|
||||
draw.line(tl, tr2, br, bl)
|
||||
)
|
||||
draw.anchor("north", (tl, 50%, tr2))
|
||||
draw.anchor("south", (bl, 50%, br))
|
||||
draw.anchor("west", (tl, 50%, bl))
|
||||
draw.anchor("east", (tr2, 50%, br))
|
||||
})
|
||||
return (f, tl, tr, br, bl)
|
||||
}
|
||||
|
||||
#let extender(
|
||||
x: none,
|
||||
y: none,
|
||||
w: none,
|
||||
h: none,
|
||||
name: none,
|
||||
name-anchor: "center",
|
||||
fill: none,
|
||||
stroke: black + 1pt,
|
||||
id: "",
|
||||
debug: (
|
||||
grid: false,
|
||||
ports: false
|
||||
)
|
||||
) = {
|
||||
let ports = (
|
||||
west: (
|
||||
(id: "in"),
|
||||
),
|
||||
east: (
|
||||
(id: "out"),
|
||||
)
|
||||
)
|
||||
|
||||
element.elmt(
|
||||
draw-shape: draw-shape,
|
||||
x: x,
|
||||
y: y,
|
||||
w: w,
|
||||
h: h,
|
||||
name: name,
|
||||
name-anchor: name-anchor,
|
||||
ports: ports,
|
||||
fill: fill,
|
||||
stroke: stroke,
|
||||
id: id,
|
||||
debug: debug
|
||||
)
|
||||
}
|
64
src/elements/multiplexer.typ
Normal file
64
src/elements/multiplexer.typ
Normal file
@ -0,0 +1,64 @@
|
||||
#import "@preview/cetz:0.2.2": draw
|
||||
#import "../util.typ"
|
||||
#import "element.typ"
|
||||
|
||||
#let draw-shape(id, tl, tr, br, bl, fill, stroke) = {
|
||||
let tr2 = (tr, 20%, br)
|
||||
let br2 = (tr, 80%, br)
|
||||
let f = draw.group(name: id, {
|
||||
draw.merge-path(
|
||||
inset: 0.5em,
|
||||
fill: fill,
|
||||
stroke: stroke,
|
||||
close: true,
|
||||
draw.line(tl, tr2, br2, bl)
|
||||
)
|
||||
draw.anchor("north", (tl, 50%, tr2))
|
||||
draw.anchor("south", (bl, 50%, br2))
|
||||
draw.anchor("west", (tl, 50%, bl))
|
||||
draw.anchor("east", (tr2, 50%, br2))
|
||||
})
|
||||
return (f, tl, tr, br, bl)
|
||||
}
|
||||
|
||||
#let multiplexer(
|
||||
x: none,
|
||||
y: none,
|
||||
w: none,
|
||||
h: none,
|
||||
name: none,
|
||||
name-anchor: "center",
|
||||
entries: 2,
|
||||
fill: none,
|
||||
stroke: black + 1pt,
|
||||
id: "",
|
||||
debug: (
|
||||
grid: false,
|
||||
ports: false
|
||||
)
|
||||
) = {
|
||||
let ports = ()
|
||||
|
||||
if (type(entries) == int) {
|
||||
let nbits = calc.ceil(calc.log(entries, base: 2))
|
||||
for i in range(entries) {
|
||||
let bits = util.lpad(str(i, base: 2), nbits)
|
||||
ports.push((id: "in" + str(i), name: bits))
|
||||
}
|
||||
}
|
||||
|
||||
element.elmt(
|
||||
draw-shape: draw-shape,
|
||||
x: x,
|
||||
y: y,
|
||||
w: w,
|
||||
h: h,
|
||||
name: name,
|
||||
name-anchor: name-anchor,
|
||||
ports: (west: ports, east: ((id: "out"),)),
|
||||
fill: fill,
|
||||
stroke: stroke,
|
||||
id: id,
|
||||
debug: debug
|
||||
)
|
||||
}
|
106
src/elements/ports.typ
Normal file
106
src/elements/ports.typ
Normal file
@ -0,0 +1,106 @@
|
||||
#import "@preview/cetz:0.2.2": 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 offset
|
||||
if (side == "north") { offset = ( 0, -1em) }
|
||||
else if (side == "east") { offset = (-1em, 0) }
|
||||
else if (side == "south") { offset = ( 0, 1em) }
|
||||
else if (side == "west") { offset = ( 1em, 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)
|
||||
}
|
||||
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)
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
add-port(
|
||||
elmt-id,
|
||||
side,
|
||||
port,
|
||||
pos,
|
||||
prev: pos-prev,
|
||||
next: pos-next,
|
||||
debug: debug
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user