Compare commits
	
		
			3 Commits
		
	
	
		
			1e6c6cfc43
			...
			6174baf650
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 6174baf650 | |||
| 6d6c357534 | |||
| c9155a0b99 | 
							
								
								
									
										
											BIN
										
									
								
								gallery/test.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								gallery/test.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										300
									
								
								gallery/test.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								gallery/test.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,300 @@ | |||||||
|  | #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") | ||||||
|  | }) | ||||||
							
								
								
									
										6
									
								
								src/circuit.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/circuit.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | #import "@preview/cetz:0.2.2": canvas | ||||||
|  |  | ||||||
|  | #let circuit(body, length: 2em) = { | ||||||
|  |   set text(font: "Source Sans 3") | ||||||
|  |   canvas(length: length, body) | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								src/element.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/element.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | #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 | ||||||
							
								
								
									
										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 | ||||||
|  |       ) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										6
									
								
								src/lib.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/lib.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | #let version = version((0,0,1)) | ||||||
|  |  | ||||||
|  | #import "circuit.typ": circuit | ||||||
|  | #import "element.typ" | ||||||
|  | #import "util.typ" | ||||||
|  | #import "wire.typ" | ||||||
							
								
								
									
										40
									
								
								src/util.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/util.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | #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
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								src/wire.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,230 @@ | |||||||
|  | #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
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								typst.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | [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/*" ] | ||||||
		Reference in New Issue
	
	Block a user