Compare commits
No commits in common. "6174baf650ce0c4fd768cf324f48cfe7b521f26d" and "1e6c6cfc4366345974257cc027a9efe90fcd135a" have entirely different histories.
6174baf650
...
1e6c6cfc43
BIN
gallery/test.pdf
BIN
gallery/test.pdf
Binary file not shown.
300
gallery/test.typ
300
gallery/test.typ
@ -1,300 +0,0 @@
|
|||||||
#import "../src/lib.typ": circuit, element, util, wire
|
|
||||||
|
|
||||||
#set page(flipped: true)
|
|
||||||
|
|
||||||
#circuit({
|
|
||||||
element.block(
|
|
||||||
x: 0, y: 0, w: 1.5, h: 2.2,
|
|
||||||
id: "PC-buf",
|
|
||||||
fill: util.colors.orange,
|
|
||||||
ports: (
|
|
||||||
west: (
|
|
||||||
(id: "PCNext"),
|
|
||||||
),
|
|
||||||
north: (
|
|
||||||
(id: "CLK", clock: true),
|
|
||||||
),
|
|
||||||
east: (
|
|
||||||
(id: "PC"),
|
|
||||||
),
|
|
||||||
south: (
|
|
||||||
(id: "EN", name: "EN"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
wire.stub("PC-buf-port-CLK", "north", name: "CLK")
|
|
||||||
wire.stub("PC-buf-port-EN", "south", name: "PCWrite")
|
|
||||||
|
|
||||||
element.multiplexer(
|
|
||||||
x: 3, y: (from: "PC-buf-port-PC", to: "in0"), w: 1, h: 2,
|
|
||||||
id: "AdrSrc-MP",
|
|
||||||
fill: util.colors.orange,
|
|
||||||
entries: 2
|
|
||||||
)
|
|
||||||
wire.wire(
|
|
||||||
"wPCBuf-InstDataMgr", (
|
|
||||||
"PC-buf-port-PC",
|
|
||||||
"AdrSrc-MP-port-in0"
|
|
||||||
),
|
|
||||||
name: "PC",
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
wire.stub("AdrSrc-MP.north", "north", name: "AdrSrc")
|
|
||||||
|
|
||||||
element.block(
|
|
||||||
x: 6, y: (from: "AdrSrc-MP-port-out", to: "A"), w: 3, h: 4,
|
|
||||||
id: "InstDataMgr",
|
|
||||||
fill: util.colors.yellow,
|
|
||||||
ports: (
|
|
||||||
west: (
|
|
||||||
(id: "A", name: "A"),
|
|
||||||
(id: "WD", name: "WD")
|
|
||||||
),
|
|
||||||
north: (
|
|
||||||
(id: "CLK", clock: true),
|
|
||||||
(id: "WE", name: "WE", vertical: true),
|
|
||||||
(id: "IRWrite", name: "IRWrite", vertical: true)
|
|
||||||
),
|
|
||||||
east: (
|
|
||||||
(id: "Instr", name: "Instr."),
|
|
||||||
(id: "RD", name: "RD")
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ports-margins: (
|
|
||||||
west: (30%, 0%),
|
|
||||||
east: (40%, 0%)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
wire.wire(
|
|
||||||
"wAdrSrcMP-InstDataMgr", (
|
|
||||||
"AdrSrc-MP-port-out",
|
|
||||||
"InstDataMgr-port-A"
|
|
||||||
),
|
|
||||||
name: "Adr",
|
|
||||||
name-pos: "end",
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
|
|
||||||
wire.stub("InstDataMgr-port-CLK", "north", name: "CLK")
|
|
||||||
wire.stub("InstDataMgr-port-WE", "north")
|
|
||||||
wire.stub("InstDataMgr-port-IRWrite", "north")
|
|
||||||
wire.stub("InstDataMgr-port-WD", "west")
|
|
||||||
|
|
||||||
element.block(
|
|
||||||
x: 15, y: (from: "InstDataMgr-port-RD", to: "WD3"), w: 3, h: 4,
|
|
||||||
id: "RegFile",
|
|
||||||
fill: util.colors.pink,
|
|
||||||
ports: (
|
|
||||||
west: (
|
|
||||||
(id: "A1", name: "A1"),
|
|
||||||
(id: "A2", name: "A2"),
|
|
||||||
(id: "A3", name: "A3"),
|
|
||||||
(id: "WD3", name: "WD3"),
|
|
||||||
),
|
|
||||||
north: (
|
|
||||||
(id: "CLK", clock: true),
|
|
||||||
(id: "WE3", name: "WE3", vertical: true)
|
|
||||||
),
|
|
||||||
east: (
|
|
||||||
(id: "RD1", name: "RD1"),
|
|
||||||
(id: "RD2", name: "RD2"),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
ports-margins: (
|
|
||||||
east: (20%, 20%)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
wire.stub("RegFile-port-CLK", "north", name: "CLK")
|
|
||||||
wire.stub("RegFile-port-WE3", "north", name: "Regwrite", vertical: true)
|
|
||||||
wire.stub("RegFile-port-A2", "west")
|
|
||||||
wire.stub("RegFile-port-RD2", "east")
|
|
||||||
|
|
||||||
element.extender(
|
|
||||||
x: 15, y: -3.5, w: 3, h: 1,
|
|
||||||
id: "Extender",
|
|
||||||
fill: util.colors.green
|
|
||||||
)
|
|
||||||
wire.wire(
|
|
||||||
"wExtender-ImmSrc", (
|
|
||||||
"Extender.north",
|
|
||||||
(18, -2)
|
|
||||||
),
|
|
||||||
style: "zigzag",
|
|
||||||
zigzag-ratio: 0%,
|
|
||||||
name: "ImmSrc",
|
|
||||||
name-pos: "end",
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
|
|
||||||
let mid = ("InstDataMgr.east", 50%, "RegFile.west")
|
|
||||||
wire.wire(
|
|
||||||
"wInstDataMgr-Bus", (
|
|
||||||
"InstDataMgr-port-Instr",
|
|
||||||
(vertical: (), horizontal: mid)
|
|
||||||
),
|
|
||||||
name: "Instr",
|
|
||||||
name-pos: "start",
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
wire.wire(
|
|
||||||
"wBus", (
|
|
||||||
(v => (v.at(0), -3.5), mid),
|
|
||||||
(horizontal: (), vertical: (0, 3.5)),
|
|
||||||
),
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
wire.wire(
|
|
||||||
"wBus-RegFile-A1", (
|
|
||||||
"RegFile-port-A1",
|
|
||||||
(horizontal: mid, vertical: ()),
|
|
||||||
),
|
|
||||||
name: "RS1",
|
|
||||||
name-pos: "end",
|
|
||||||
slice: (19, 15),
|
|
||||||
reverse: true,
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
wire.wire(
|
|
||||||
"wBus-RegFile-A3", (
|
|
||||||
"RegFile-port-A3",
|
|
||||||
(horizontal: mid, vertical: ()),
|
|
||||||
),
|
|
||||||
name: "RD",
|
|
||||||
name-pos: "end",
|
|
||||||
slice: (11, 7),
|
|
||||||
reverse: true,
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
wire.wire(
|
|
||||||
"wBus-Extender", (
|
|
||||||
"Extender-port-in",
|
|
||||||
(horizontal: mid, vertical: ()),
|
|
||||||
),
|
|
||||||
slice: (31, 7),
|
|
||||||
reverse: true,
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
|
|
||||||
element.alu(
|
|
||||||
x: 22, y: (from: "RegFile-port-RD1", to: "in1"), w: 1, h: 2,
|
|
||||||
id: "ALU",
|
|
||||||
fill: util.colors.purple
|
|
||||||
)
|
|
||||||
wire.wire(
|
|
||||||
"wRegFile-ALU", (
|
|
||||||
"RegFile-port-RD1",
|
|
||||||
"ALU-port-in1"
|
|
||||||
),
|
|
||||||
name: ("A", "SrcA"),
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
|
|
||||||
element.block(
|
|
||||||
x: 26, y: (from: "ALU-port-out", to: "in"), w: 1.5, h: 2,
|
|
||||||
id: "OutBuf",
|
|
||||||
fill: util.colors.orange,
|
|
||||||
ports: (
|
|
||||||
west: (
|
|
||||||
(id: "in"),
|
|
||||||
),
|
|
||||||
north: (
|
|
||||||
(id: "CLK", clock: true),
|
|
||||||
),
|
|
||||||
east: (
|
|
||||||
(id: "out"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
wire.stub("OutBuf-port-CLK", "north", name: "CLK")
|
|
||||||
wire.wire(
|
|
||||||
"wALU-OutBuf", (
|
|
||||||
"ALU-port-out",
|
|
||||||
"OutBuf-port-in"
|
|
||||||
),
|
|
||||||
name: "ALUResult",
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
|
|
||||||
element.multiplexer(
|
|
||||||
x: 30, y: (from: "OutBuf-port-out", to: "in0"), w: 1, h: 2.5,
|
|
||||||
id: "Res-MP",
|
|
||||||
fill: util.colors.orange,
|
|
||||||
entries: 3
|
|
||||||
)
|
|
||||||
wire.stub("Res-MP.north", "north", name: "ResultSrc")
|
|
||||||
wire.stub("Res-MP-port-in2", "west")
|
|
||||||
wire.wire(
|
|
||||||
"wOutBuf-ResMP", (
|
|
||||||
"OutBuf-port-out",
|
|
||||||
"Res-MP-port-in0"
|
|
||||||
),
|
|
||||||
name: "ALUOut",
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
|
|
||||||
wire.wire(
|
|
||||||
"wExt-ALU", (
|
|
||||||
"Extender-port-out",
|
|
||||||
"ALU-port-in2",
|
|
||||||
),
|
|
||||||
name: ("ImmExt", "SrcB"),
|
|
||||||
bus: true,
|
|
||||||
style: "zigzag",
|
|
||||||
zigzag-ratio: 60%
|
|
||||||
)
|
|
||||||
|
|
||||||
wire.wire(
|
|
||||||
"wInstDataMgr-ResMP", (
|
|
||||||
"InstDataMgr-port-RD",
|
|
||||||
"Res-MP-port-in1"
|
|
||||||
),
|
|
||||||
style: "dodge",
|
|
||||||
dodge-y: -4,
|
|
||||||
dodge-sides: ("east", "west"),
|
|
||||||
name: "Data",
|
|
||||||
name-pos: "start",
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
|
|
||||||
wire.wire(
|
|
||||||
"wResMP-AdrSrc", (
|
|
||||||
"Res-MP-port-out",
|
|
||||||
"AdrSrc-MP-port-in1"
|
|
||||||
),
|
|
||||||
style: "dodge",
|
|
||||||
dodge-y: -5,
|
|
||||||
dodge-sides: ("east", "west"),
|
|
||||||
dodge-margins: (0.5, 1),
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
|
|
||||||
wire.wire(
|
|
||||||
"wResMP-RegFile", (
|
|
||||||
"Res-MP-port-out",
|
|
||||||
"RegFile-port-WD3"
|
|
||||||
),
|
|
||||||
style: "dodge",
|
|
||||||
dodge-y: -5,
|
|
||||||
dodge-sides: ("east", "west"),
|
|
||||||
dodge-margins: (0.5, 1),
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
|
|
||||||
wire.wire(
|
|
||||||
"wResMP-PCBuf", (
|
|
||||||
"Res-MP-port-out",
|
|
||||||
"PC-buf-port-PCNext"
|
|
||||||
),
|
|
||||||
style: "dodge",
|
|
||||||
dodge-y: -5,
|
|
||||||
dodge-sides: ("east", "west"),
|
|
||||||
dodge-margins: (0.5, 1.5),
|
|
||||||
name: "PCNext",
|
|
||||||
name-pos: "end",
|
|
||||||
bus: true
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
wire.intersection("wResMP-RegFile.dodge-end")
|
|
||||||
wire.intersection("wResMP-AdrSrc.dodge-end")
|
|
||||||
})
|
|
@ -1,6 +0,0 @@
|
|||||||
#import "@preview/cetz:0.2.2": canvas
|
|
||||||
|
|
||||||
#let circuit(body, length: 2em) = {
|
|
||||||
set text(font: "Source Sans 3")
|
|
||||||
canvas(length: length, body)
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
#import "elements/ports.typ": add-ports, add-port
|
|
||||||
#import "elements/element.typ": elmt
|
|
||||||
|
|
||||||
#import "elements/alu.typ": alu
|
|
||||||
#import "elements/block.typ": block
|
|
||||||
#import "elements/extender.typ": extender
|
|
||||||
#import "elements/multiplexer.typ": multiplexer
|
|
@ -1,84 +0,0 @@
|
|||||||
#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
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
#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
|
|
||||||
)
|
|
@ -1,99 +0,0 @@
|
|||||||
#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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
@ -1,66 +0,0 @@
|
|||||||
#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
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
#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
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,106 +0,0 @@
|
|||||||
#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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
#let version = version((0,0,1))
|
|
||||||
|
|
||||||
#import "circuit.typ": circuit
|
|
||||||
#import "element.typ"
|
|
||||||
#import "util.typ"
|
|
||||||
#import "wire.typ"
|
|
40
src/util.typ
40
src/util.typ
@ -1,40 +0,0 @@
|
|||||||
#let colors = (
|
|
||||||
orange: rgb(245, 180, 147),
|
|
||||||
yellow: rgb(250, 225, 127),
|
|
||||||
green: rgb(127, 200, 172),
|
|
||||||
pink: rgb(236, 127, 178),
|
|
||||||
purple: rgb(189, 151, 255)
|
|
||||||
)
|
|
||||||
|
|
||||||
#let lpad(s, len) = {
|
|
||||||
let res = "0" * len + s
|
|
||||||
return res.slice(-len)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let opposite-anchor(anchor) = {
|
|
||||||
return (
|
|
||||||
north: "south",
|
|
||||||
east: "west",
|
|
||||||
south: "north",
|
|
||||||
west: "east",
|
|
||||||
|
|
||||||
north-west: "south-east",
|
|
||||||
north-east: "south-west",
|
|
||||||
south-east: "north-west",
|
|
||||||
south-west: "north-east"
|
|
||||||
).at(anchor)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let rotate-anchor(anchor) = {
|
|
||||||
return (
|
|
||||||
north: "east",
|
|
||||||
east: "south",
|
|
||||||
south: "west",
|
|
||||||
west: "north",
|
|
||||||
|
|
||||||
north-west: "north-east",
|
|
||||||
north-east: "south-east",
|
|
||||||
south-east: "south-west",
|
|
||||||
south-west: "north-west"
|
|
||||||
).at(anchor)
|
|
||||||
}
|
|
230
src/wire.typ
230
src/wire.typ
@ -1,230 +0,0 @@
|
|||||||
#import "@preview/cetz:0.2.2": draw, coordinate
|
|
||||||
#import "util.typ": opposite-anchor
|
|
||||||
|
|
||||||
#let wire-styles = ("direct", "zigzag", "dodge")
|
|
||||||
#let signal-width = 1pt
|
|
||||||
#let bus-width = 1.5pt
|
|
||||||
|
|
||||||
#let intersection(pt) = {
|
|
||||||
draw.circle(pt, radius: .2, stroke: none, fill: black)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let get-direct-wire(pts) = {
|
|
||||||
let anchors = (
|
|
||||||
"start": pts.first(),
|
|
||||||
"end": pts.last()
|
|
||||||
)
|
|
||||||
return (pts, anchors)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let get-zigzag-wire(pts, ratio) = {
|
|
||||||
let start = pts.first()
|
|
||||||
let end = pts.last()
|
|
||||||
let mid = (start, ratio, end)
|
|
||||||
|
|
||||||
let points = (
|
|
||||||
start,
|
|
||||||
(horizontal: mid, vertical: ()),
|
|
||||||
(horizontal: (), vertical: end),
|
|
||||||
end
|
|
||||||
)
|
|
||||||
let anchors = (
|
|
||||||
"start": start,
|
|
||||||
"zig": points.at(1),
|
|
||||||
"zag": points.at(2),
|
|
||||||
"end": end
|
|
||||||
)
|
|
||||||
return (points, anchors)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let get-dodge-wire(pts, dodge-y, margins, sides, ctx) = {
|
|
||||||
let start = pts.first()
|
|
||||||
let end = pts.last()
|
|
||||||
let (margin-start, margin-end) = margins
|
|
||||||
let (side-start, side-end) = sides
|
|
||||||
|
|
||||||
let p1 = (start, margin-start, end)
|
|
||||||
let p2 = (end, margin-end, start)
|
|
||||||
|
|
||||||
let (ctx, p0) = coordinate.resolve(ctx, start)
|
|
||||||
let (ctx, p3) = coordinate.resolve(ctx, end)
|
|
||||||
p0 = (x: p0.first(), y: p0.last())
|
|
||||||
p3 = (x: p3.first(), y: p3.last())
|
|
||||||
|
|
||||||
let dx1 = margin-start
|
|
||||||
let dx2 = margin-end
|
|
||||||
|
|
||||||
if type(margin-start) == ratio {
|
|
||||||
dx1 = calc.abs(p3.x - p0.x) * margin-start / 100%
|
|
||||||
}
|
|
||||||
if type(margin-end) == ratio {
|
|
||||||
dx2 = calc.abs(p3.x - p0.x) * margin-end / 100%
|
|
||||||
}
|
|
||||||
if side-start == "west" {
|
|
||||||
dx1 *= -1
|
|
||||||
}
|
|
||||||
if side-end == "east" {
|
|
||||||
dx2 *= -1
|
|
||||||
}
|
|
||||||
p1 = (p0.x + dx1, p0.y)
|
|
||||||
p2 = (p3.x - dx2, p0.y)
|
|
||||||
|
|
||||||
let points = (
|
|
||||||
start,
|
|
||||||
(horizontal: p1, vertical: ()),
|
|
||||||
(horizontal: (), vertical: (0, dodge-y)),
|
|
||||||
(horizontal: p2, vertical: ()),
|
|
||||||
(horizontal: (), vertical: end),
|
|
||||||
end
|
|
||||||
)
|
|
||||||
let anchors = (
|
|
||||||
"start": start,
|
|
||||||
"start2": points.at(1),
|
|
||||||
"dodge-start": points.at(2),
|
|
||||||
"dodge-end": points.at(3),
|
|
||||||
"end2": points.at(4),
|
|
||||||
"end": end
|
|
||||||
)
|
|
||||||
|
|
||||||
return (points, anchors)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let wire(
|
|
||||||
id, pts,
|
|
||||||
bus: false,
|
|
||||||
name: none,
|
|
||||||
name-pos: "middle",
|
|
||||||
slice: none,
|
|
||||||
color: black,
|
|
||||||
dashed: false,
|
|
||||||
style: "direct",
|
|
||||||
reverse: false,
|
|
||||||
zigzag-ratio: 50%,
|
|
||||||
dodge-y: 0,
|
|
||||||
dodge-sides: ("east", "west"),
|
|
||||||
dodge-margins: (5%, 5%)
|
|
||||||
) = draw.get-ctx(ctx => {
|
|
||||||
if not style in wire-styles {
|
|
||||||
panic("Invalid wire style '" + style + "'")
|
|
||||||
}
|
|
||||||
|
|
||||||
if pts.len() != 2 {
|
|
||||||
panic("Wrong number of points (got " + str(pts.len()) + " instead of 2)")
|
|
||||||
}
|
|
||||||
|
|
||||||
let stroke = (
|
|
||||||
paint: color,
|
|
||||||
thickness: if bus {bus-width} else {signal-width}
|
|
||||||
)
|
|
||||||
if dashed {
|
|
||||||
stroke.insert("dash", "dashed")
|
|
||||||
}
|
|
||||||
|
|
||||||
let points = ()
|
|
||||||
let anchors = ()
|
|
||||||
|
|
||||||
if style == "direct" {
|
|
||||||
(points, anchors) = get-direct-wire(pts)
|
|
||||||
|
|
||||||
} else if style == "zigzag" {
|
|
||||||
(points, anchors) = get-zigzag-wire(pts, zigzag-ratio)
|
|
||||||
|
|
||||||
} else if style == "dodge" {
|
|
||||||
(points, anchors) = get-dodge-wire(
|
|
||||||
pts,
|
|
||||||
dodge-y,
|
|
||||||
dodge-margins,
|
|
||||||
dodge-sides,
|
|
||||||
ctx
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
draw.group(name: id, {
|
|
||||||
draw.line(..points, stroke: stroke)
|
|
||||||
for (anchor-name, anchor-pos) in anchors {
|
|
||||||
draw.anchor(anchor-name, anchor-pos)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
let first-pt = id + ".start"
|
|
||||||
let last-pt = id + ".end"
|
|
||||||
if reverse {
|
|
||||||
(first-pt, last-pt) = (last-pt, first-pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
if name != none {
|
|
||||||
let names = ()
|
|
||||||
|
|
||||||
if type(name) == str {
|
|
||||||
names = ((name, name-pos),)
|
|
||||||
|
|
||||||
} else if type(name) == array {
|
|
||||||
names = (
|
|
||||||
(name.at(0), "start"),
|
|
||||||
(name.at(1), "end")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (name, pos) in names {
|
|
||||||
let point
|
|
||||||
let anchor
|
|
||||||
|
|
||||||
if pos == "middle" {
|
|
||||||
point = (first-pt, 50%, last-pt)
|
|
||||||
anchor = "south"
|
|
||||||
|
|
||||||
} else if pos == "start" {
|
|
||||||
point = first-pt
|
|
||||||
anchor = "south-west"
|
|
||||||
|
|
||||||
} else if pos == "end" {
|
|
||||||
point = last-pt
|
|
||||||
anchor = "south-east"
|
|
||||||
}
|
|
||||||
|
|
||||||
draw.content(point, anchor: anchor, padding: 3pt, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if slice != none {
|
|
||||||
let (start, end) = slice
|
|
||||||
let slice-txt = "[" + str(start) + ":" + str(end) + "]"
|
|
||||||
|
|
||||||
draw.content(
|
|
||||||
first-pt,
|
|
||||||
anchor: "south-west",
|
|
||||||
padding: 3pt,
|
|
||||||
text(slice-txt, size: 0.75em)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
#let stub(port-id, side, name: none, vertical: false, length: 1em) = {
|
|
||||||
let offset = (
|
|
||||||
north: (0, length),
|
|
||||||
east: (length, 0),
|
|
||||||
south: (0, -length),
|
|
||||||
west: (-length, 0)
|
|
||||||
).at(side)
|
|
||||||
draw.line(
|
|
||||||
port-id,
|
|
||||||
(rel: offset, to: port-id)
|
|
||||||
)
|
|
||||||
if name != none {
|
|
||||||
let text-anchor = if vertical {
|
|
||||||
(
|
|
||||||
"north": "west",
|
|
||||||
"south": "east",
|
|
||||||
"west": "south",
|
|
||||||
"east": "north"
|
|
||||||
).at(side)
|
|
||||||
} else { opposite-anchor(side) }
|
|
||||||
draw.content(
|
|
||||||
anchor: text-anchor,
|
|
||||||
padding: 0.2em,
|
|
||||||
angle: if vertical {90deg} else {0deg},
|
|
||||||
(rel: offset, to: port-id),
|
|
||||||
name
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
14
typst.toml
14
typst.toml
@ -1,14 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "circuiteria"
|
|
||||||
version = "0.0.1"
|
|
||||||
compiler = "0.11.0"
|
|
||||||
repository = "https://git.kb28.ch/HEL/circuiteria"
|
|
||||||
entrypoint = "src/lib.typ"
|
|
||||||
authors = [
|
|
||||||
"Louis Heredero <https://git.kb28.ch/HEL>"
|
|
||||||
]
|
|
||||||
categories = [ "visualization" ]
|
|
||||||
license = "Apache-2.0"
|
|
||||||
description = "Drawing block circuits with Typst made easy, using CeTZ"
|
|
||||||
keywords = [ "circuit", "block", "draw" ]
|
|
||||||
exclude = [ "/gallery/*" ]
|
|
Loading…
Reference in New Issue
Block a user