Compare commits
	
		
			2 Commits
		
	
	
		
			66ac91af7b
			...
			86d9122740
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 86d9122740 | |||
| 5bd3dd8111 | 
| @@ -114,3 +114,30 @@ gates.gate-xor(x: 3, y: 0, w: 1.5, h: 1.5, inverted: "all") | ||||
| gates.gate-xnor(x: 0, y: 0, w: 1.5, h: 1.5) | ||||
| gates.gate-xnor(x: 3, y: 0, w: 1.5, h: 1.5, inverted: "all") | ||||
| ```, vertical: true) | ||||
|  | ||||
| #let group = example(``` | ||||
| element.group( | ||||
|   id: "g1", name: "Group 1", stroke: (dash: "dashed"), | ||||
|   { | ||||
|     element.block(id: "b1", w: 2, h: 2, | ||||
|       x: 0, y: 1.5, | ||||
|       ports: (east: ((id: "out"),)), | ||||
|       fill: util.colors.green | ||||
|     ) | ||||
|     element.block(id: "b2", w: 2, h: 1, | ||||
|       x: 0, y: 0, | ||||
|       ports: (east: ((id: "out"),)), | ||||
|       fill: util.colors.orange | ||||
|     ) | ||||
|   } | ||||
| ) | ||||
| element.block(id: "b3", w: 2, h: 3, | ||||
|   x: (rel: 1, to: "g1.east"), | ||||
|   y: (from: "b1-port-out", to: "in1"), | ||||
|   ports: (west: ((id: "in1"), (id: "in2"))), | ||||
|   fill: util.colors.blue | ||||
| ) | ||||
| wire.wire("w1", ("b1-port-out", "b3-port-in1")) | ||||
| wire.wire("w2", ("b2-port-out", "b3-port-in2"), | ||||
|           style: "zigzag") | ||||
| ```) | ||||
							
								
								
									
										
											BIN
										
									
								
								gallery/test.pdf
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								gallery/test.pdf
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								gallery/test4.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								gallery/test4.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										217
									
								
								gallery/test4.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								gallery/test4.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,217 @@ | ||||
| #import "@preview/cetz:0.2.2": draw | ||||
| #import "../src/lib.typ": * | ||||
|  | ||||
| #set page(flipped: true) | ||||
|  | ||||
| #circuit({ | ||||
|   element.group(id: "toplvl", name: "Toplevel", { | ||||
|     element.group( | ||||
|       id: "proc", | ||||
|       name: "Processor", | ||||
|       padding: 1.5em, | ||||
|       stroke: (dash: "dashed"), | ||||
|       { | ||||
|       element.block( | ||||
|         x: 0, y: 0, w: 8, h: 4, | ||||
|         id: "dp", | ||||
|         fill: util.colors.pink, | ||||
|         name: "Datapath", | ||||
|         ports: ( | ||||
|           north: ( | ||||
|             (id: "clk", clock: true), | ||||
|             (id: "Zero"), | ||||
|             (id: "Regsrc"), | ||||
|             (id: "PCSrc"), | ||||
|             (id: "ResultSrc"), | ||||
|             (id: "ALUControl"), | ||||
|             (id: "ImmSrc"), | ||||
|             (id: "RegWrite"), | ||||
|             (id: "dummy") | ||||
|           ), | ||||
|           east: ( | ||||
|             (id: "PC", name: "PC"), | ||||
|             (id: "Instr", name: "Instr"), | ||||
|             (id: "ALUResult", name: "ALUResult"), | ||||
|             (id: "dummy"), | ||||
|             (id: "WriteData", name: "WriteData"), | ||||
|             (id: "ReadData", name: "ReadData"), | ||||
|           ), | ||||
|           west: ( | ||||
|             (id: "rst"), | ||||
|           ) | ||||
|         ), | ||||
|         ports-margins: ( | ||||
|           north: (0%, 0%), | ||||
|           west: (0%, 70%) | ||||
|         ) | ||||
|       ) | ||||
|        | ||||
|       element.block( | ||||
|         x: 0, y: 7, w: 8, h: 3, | ||||
|         id: "ctrl", | ||||
|         fill: util.colors.orange, | ||||
|         name: "Controller", | ||||
|         ports: ( | ||||
|           east: ( | ||||
|             (id: "Instr", name: "Instr"), | ||||
|           ), | ||||
|           south: ( | ||||
|             (id: "dummy"), | ||||
|             (id: "Zero"), | ||||
|             (id: "Regsrc"), | ||||
|             (id: "PCSrc"), | ||||
|             (id: "ResultSrc"), | ||||
|             (id: "ALUControl"), | ||||
|             (id: "ImmSrc"), | ||||
|             (id: "RegWrite"), | ||||
|             (id: "MemWrite") | ||||
|           ) | ||||
|         ), | ||||
|         ports-margins: ( | ||||
|           south: (0%, 0%) | ||||
|         ) | ||||
|       ) | ||||
|       wire.wire( | ||||
|         "w-Zero", | ||||
|         ("dp-port-Zero", "ctrl-port-Zero"), | ||||
|         name: "Zero", | ||||
|         name-pos: "start", | ||||
|         directed: true | ||||
|       ) | ||||
|       for p in ("Regsrc", "PCSrc", "ResultSrc", "ALUControl", "ImmSrc", "RegWrite") { | ||||
|         wire.wire( | ||||
|           "w-" + p, | ||||
|           ("ctrl-port-"+p, "dp-port-"+p), | ||||
|           name: p, | ||||
|           name-pos: "start", | ||||
|           directed: true | ||||
|         ) | ||||
|       } | ||||
|  | ||||
|       draw.content( | ||||
|         (rel: (0, 1em), to: "ctrl.north"), | ||||
|         [*RISCV single*], | ||||
|         anchor: "south" | ||||
|       ) | ||||
|     }) | ||||
|      | ||||
|     element.block( | ||||
|       x: (rel: 3.5, to: "dp.east"), | ||||
|       y: (from: "dp-port-ReadData", to: "RD"), | ||||
|       w: 3, h: 4, | ||||
|       id: "dmem", | ||||
|       fill: util.colors.green, | ||||
|       name: "Data\n Memory", | ||||
|       ports: ( | ||||
|         north: ( | ||||
|           (id: "clk", clock: true), | ||||
|           (id: "WE", name: "WE") | ||||
|         ), | ||||
|         west: ( | ||||
|           (id: "dummy"), | ||||
|           (id: "dummy"), | ||||
|           (id: "A", name: "A"), | ||||
|           (id: "dummy"), | ||||
|           (id: "WD", name: "WD"), | ||||
|           (id: "RD", name: "RD"), | ||||
|         ) | ||||
|       ), | ||||
|       ports-margins: ( | ||||
|         north: (0%, 10%) | ||||
|       ) | ||||
|     ) | ||||
|     wire.wire( | ||||
|       "w-DataAddr", | ||||
|       ("dp-port-ALUResult", "dmem-port-A"), | ||||
|       name: "DataAddr", | ||||
|       name-pos: "end", | ||||
|       directed: true | ||||
|     ) | ||||
|     wire.wire( | ||||
|       "w-WriteData", | ||||
|       ("dp-port-WriteData", "dmem-port-WD"), | ||||
|       name: "WriteData", | ||||
|       name-pos: "end", | ||||
|       directed: true | ||||
|     ) | ||||
|     wire.wire( | ||||
|       "w-ReadData", | ||||
|       ("dmem-port-RD", "dp-port-ReadData"), | ||||
|       name: "ReadData", | ||||
|       name-pos: "end", | ||||
|       reverse: true, | ||||
|       directed: true | ||||
|     ) | ||||
|     wire.wire( | ||||
|       "w-MemWrite", | ||||
|       ("ctrl-port-MemWrite", "dmem-port-WE"), | ||||
|       style: "zigzag", | ||||
|       name: "MemWrite", | ||||
|       name-pos: "start", | ||||
|       zigzag-dir: "horizontal", | ||||
|       zigzag-ratio: 80%, | ||||
|       directed: true | ||||
|     ) | ||||
|     wire.stub( | ||||
|       "dmem-port-clk", "north", | ||||
|       name: "clk", length: 3pt | ||||
|     ) | ||||
|  | ||||
|     element.block( | ||||
|       x: (rel: 3.5, to: "dp.east"), | ||||
|       y: (from: "ctrl-port-Instr", to: "dummy"), | ||||
|       w: 3, h: 4, | ||||
|       id: "imem", | ||||
|       fill: util.colors.green, | ||||
|       name: "Instruction\n Memory", | ||||
|       ports: ( | ||||
|         west: ( | ||||
|           (id: "A", name: "A"), | ||||
|           (id: "dummy"), | ||||
|           (id: "dummy2"), | ||||
|           (id: "RD", name: "RD"), | ||||
|         ) | ||||
|       ) | ||||
|     ) | ||||
|     wire.wire( | ||||
|       "w-PC", | ||||
|       ("dp-port-PC", "imem-port-A"), | ||||
|       style: "zigzag", | ||||
|       directed: true | ||||
|     ) | ||||
|     wire.wire( | ||||
|       "w-Instr1", | ||||
|       ("imem-port-RD", "dp-port-Instr"), | ||||
|       style: "zigzag", | ||||
|       zigzag-ratio: 30%, | ||||
|       directed: true | ||||
|     ) | ||||
|     wire.wire( | ||||
|       "w-Instr2", | ||||
|       ("imem-port-RD", "ctrl-port-Instr"), | ||||
|       style: "zigzag", | ||||
|       zigzag-ratio: 30%, | ||||
|       directed: true | ||||
|     ) | ||||
|     wire.intersection("w-Instr1.zig", radius: 2pt) | ||||
|     draw.content("w-Instr1.zig", "Instr", anchor: "south", padding: 4pt) | ||||
|     draw.content("w-PC.zig", "PC", anchor: "south-east", padding: 2pt) | ||||
|  | ||||
|     draw.content("dmem.south-west", [*External Memories*], anchor: "north", padding: 10pt) | ||||
|   }) | ||||
|  | ||||
|   wire.wire( | ||||
|     "w-dp-clk", | ||||
|     ("dp-port-clk", (-1, 4.2)), | ||||
|     style: "zigzag", | ||||
|     zigzag-dir: "horizontal", | ||||
|     zigzag-ratio: 100% | ||||
|   ) | ||||
|   draw.content("w-dp-clk.end", "clk", anchor: "east", padding: 3pt) | ||||
|    | ||||
|   wire.wire( | ||||
|     "w-dp-rst", | ||||
|     ("dp-port-rst", (horizontal: (-1, 0), vertical: ())) | ||||
|   ) | ||||
|   draw.content("w-dp-rst.end", "rst", anchor: "east", padding: 3pt) | ||||
| }) | ||||
							
								
								
									
										
											BIN
										
									
								
								manual.pdf
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								manual.pdf
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -158,7 +158,8 @@ Simply import #link("src/lib.typ") and call the `circuit` function: | ||||
|   read("src/elements/alu.typ") + "\n" + | ||||
|   read("src/elements/block.typ") + "\n" + | ||||
|   read("src/elements/extender.typ") + "\n" + | ||||
|   read("src/elements/multiplexer.typ"), | ||||
|   read("src/elements/multiplexer.typ") + "\n" + | ||||
|   read("src/elements/group.typ"), | ||||
|   name: "element", | ||||
|   scope: ( | ||||
|     element: element, | ||||
|   | ||||
| @@ -11,3 +11,5 @@ | ||||
| #import "elements/logic/or.typ": gate-or, gate-nor | ||||
| #import "elements/logic/xor.typ": gate-xor, gate-xnor | ||||
| #import "elements/logic/buf.typ": gate-buf, gate-not | ||||
|  | ||||
| #import "elements/group.typ": group | ||||
| @@ -33,7 +33,7 @@ | ||||
| ///   - `name` (`str`): Optional name displayed *in* the block | ||||
| ///   - `clock` (`bool`): Whether it is a clock port (triangle symbol) | ||||
| ///   - `vertical` (`bool`): Whether the name should be drawn vertically | ||||
| /// - ports-margins (dictionary): Dictionary of ports margins (used with automatic port placement). They keys are cardinal directions ("north", "east", "south", "west"). The values are tuples of (<start>, <end>) margins (numbers) | ||||
| /// - ports-margins (dictionary): Dictionary of ports margins (used with automatic port placement). They keys are cardinal directions ("north", "east", "south", "west"). The values are tuples of (`<start>`, `<end>`) margins (numbers) | ||||
| /// - fill (none, color): Fill color | ||||
| /// - stroke (stroke): Border stroke | ||||
| /// - id (str): The block id (for future reference) | ||||
|   | ||||
							
								
								
									
										80
									
								
								src/elements/group.typ
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/elements/group.typ
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| #import "@preview/cetz:0.2.2": draw, coordinate | ||||
| #import "../util.typ" | ||||
|  | ||||
| /// Draws a group of elements | ||||
| /// | ||||
| /// #examples.group | ||||
| /// - body (elements, function): Elements to group | ||||
| /// - id (str): see #doc-ref("element.elmt") | ||||
| /// - name (str): The group's name | ||||
| /// - name-anchor (str): The anchor for the name. \ | ||||
| ///     Note: the name will be placed on the *outside* of the group | ||||
| /// - fill (color): see #doc-ref("element.elmt") | ||||
| /// - stroke (stroke): see #doc-ref("element.elmt") | ||||
| /// - padding (float,length,array,dictionary): The inside padding: | ||||
| ///    - float / length: same for all sides | ||||
| ///    - array: either (`<all>`,), (`<vertical>`, `<horizontal>`) or (`<top>`, `<right>`, `<bottom>`, `<left>`) | ||||
| ///    - dictionary: valid keys are "top", "right", "bottom" and "left" | ||||
| /// - radius (number): The corner radius | ||||
| #let group( | ||||
|   body, | ||||
|   id: "", | ||||
|   name: none, | ||||
|   name-anchor: "south", | ||||
|   fill: none, | ||||
|   stroke: black + 1pt, | ||||
|   padding: 0.5em, | ||||
|   radius: 0.5em | ||||
| ) = { | ||||
|   let min-x = none | ||||
|   let max-x = none | ||||
|   let min-y = none | ||||
|   let max-y = none | ||||
|  | ||||
|   let pad-top = padding | ||||
|   let pad-bottom = padding | ||||
|   let pad-left = padding | ||||
|   let pad-right = padding | ||||
|  | ||||
|   if type(padding) == array { | ||||
|     if padding.len() == 0 { | ||||
|       panic("Padding array must contain at least one value") | ||||
|     } else if padding.len() == 1 { | ||||
|       pad-top = padding.first() | ||||
|       pad-bottom = padding.first() | ||||
|       pad-left = padding.first() | ||||
|       pad-right = padding.first() | ||||
|     } else if padding.len() == 2 { | ||||
|       pad-top = padding.first() | ||||
|       pad-bottom = padding.first() | ||||
|       pad-left = padding.last() | ||||
|       pad-right = padding.last() | ||||
|     } else if padding.len() == 4 { | ||||
|       (pad-top, pad-right, pad-bottom, pad-left) = padding | ||||
|     } | ||||
|   } else if type(padding) == dictionary { | ||||
|     pad-top = padding.at("top", default: 0.5em) | ||||
|     pad-right = padding.at("right", default: 0.5em) | ||||
|     pad-bottom = padding.at("bottom", default: 0.5em) | ||||
|     pad-left = padding.at("left", default: 0.5em) | ||||
|   } | ||||
|  | ||||
|   draw.hide(draw.group(name: id+"-inner", body)) | ||||
|   draw.rect( | ||||
|     (rel: (-pad-left, -pad-bottom), to: id+"-inner.south-west"), | ||||
|     (rel: (pad-right, pad-top), to: id+"-inner.north-east"), | ||||
|     name: id, | ||||
|     radius: radius, | ||||
|     stroke: stroke, | ||||
|     fill: fill | ||||
|   ) | ||||
|   if name != none { | ||||
|     draw.content( | ||||
|       id + "." + name-anchor, | ||||
|       anchor: util.opposite-anchor(name-anchor), | ||||
|       padding: 5pt, | ||||
|       [*#name*] | ||||
|     ) | ||||
|   } | ||||
|   body | ||||
| } | ||||
							
								
								
									
										45
									
								
								src/wire.typ
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								src/wire.typ
									
									
									
									
									
								
							| @@ -7,8 +7,8 @@ | ||||
| #let signal-width = 1pt | ||||
| #let bus-width = 1.5pt | ||||
|  | ||||
| #let intersection(pt) = { | ||||
|   draw.circle(pt, radius: .2, stroke: none, fill: black) | ||||
| #let intersection(pt, radius: .2, fill: black) = { | ||||
|   draw.circle(pt, radius: radius, stroke: none, fill: fill) | ||||
| } | ||||
|  | ||||
| #let get-direct-wire(pts) = { | ||||
| @@ -19,17 +19,26 @@ | ||||
|   return (pts, anchors) | ||||
| } | ||||
|  | ||||
| #let get-zigzag-wire(pts, ratio) = { | ||||
| #let get-zigzag-wire(pts, ratio, dir) = { | ||||
|   let start = pts.first() | ||||
|   let end = pts.last() | ||||
|   let mid = (start, ratio, end) | ||||
|  | ||||
|   let points = ( | ||||
|   let points = if dir == "vertical" { | ||||
|     ( | ||||
|       start, | ||||
|       (horizontal: mid, vertical: ()), | ||||
|       (horizontal: (), vertical: end), | ||||
|       end | ||||
|     ) | ||||
|   } else { | ||||
|     ( | ||||
|       start, | ||||
|       (horizontal: (), vertical: mid), | ||||
|       (horizontal: end, vertical: ()), | ||||
|       end | ||||
|     ) | ||||
|   } | ||||
|   let anchors = ( | ||||
|     "start": start, | ||||
|     "zig": points.at(1), | ||||
| @@ -102,7 +111,10 @@ | ||||
| /// - dashed (bool): Whether the stroke is dashed or not | ||||
| /// - style (str): The wire's style (see #doc-ref("wire.wire-styles", var: true) for possible values) | ||||
| /// - reverse (bool): If true, the start and end points will be swapped (useful in cases where the start point depends on the end point, for example with perpendiculars) | ||||
| /// - directed (bool): If true, the wire will be directed, meaning an arrow will be drawn at the endpoint | ||||
| /// - rotate-name (bool): If true, the name will be rotated according to the wire's slope | ||||
| /// - zigzag-ratio (ratio): Position of the zigzag vertical relative to the horizontal span (only with style "zigzag") | ||||
| /// - zigzag-dir (str): The zigzag's direction. As either "vertical" or "horizontal" (only with dstyle "zigzag") | ||||
| /// - dodge-y (number): Y position to dodge the wire to (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") | ||||
| @@ -116,7 +128,10 @@ | ||||
|   dashed: false, | ||||
|   style: "direct", | ||||
|   reverse: false, | ||||
|   directed: false, | ||||
|   rotate-name: true, | ||||
|   zigzag-ratio: 50%, | ||||
|   zigzag-dir: "vertical", | ||||
|   dodge-y: 0, | ||||
|   dodge-sides: ("east", "west"), | ||||
|   dodge-margins: (5%, 5%) | ||||
| @@ -144,7 +159,7 @@ | ||||
|     (points, anchors) = get-direct-wire(pts) | ||||
|      | ||||
|   } else if style == "zigzag" { | ||||
|     (points, anchors) = get-zigzag-wire(pts, zigzag-ratio) | ||||
|     (points, anchors) = get-zigzag-wire(pts, zigzag-ratio, zigzag-dir) | ||||
|      | ||||
|   } else if style == "dodge" { | ||||
|     (points, anchors) = get-dodge-wire( | ||||
| @@ -156,8 +171,12 @@ | ||||
|     ) | ||||
|   } | ||||
|  | ||||
|   let mark = (fill: color) | ||||
|   if directed { | ||||
|     mark = (end: ">", fill: color) | ||||
|   } | ||||
|   draw.group(name: id, { | ||||
|     draw.line(..points, stroke: stroke) | ||||
|     draw.line(..points, stroke: stroke, mark: mark) | ||||
|     for (anchor-name, anchor-pos) in anchors { | ||||
|       draw.anchor(anchor-name, anchor-pos) | ||||
|     } | ||||
| @@ -165,8 +184,20 @@ | ||||
|  | ||||
|   let first-pt = id + ".start" | ||||
|   let last-pt = id + ".end" | ||||
|   let first-pos = points.first() | ||||
|   let second-pos = points.at(1) | ||||
|   if reverse { | ||||
|     (first-pt, last-pt) = (last-pt, first-pt) | ||||
|     (first-pos, second-pos) = (second-pos, first-pos) | ||||
|   } | ||||
|    | ||||
|   let angle = 0deg | ||||
|   if rotate-name { | ||||
|     (ctx, first-pos) = coordinate.resolve(ctx, first-pos) | ||||
|     (ctx, second-pos) = coordinate.resolve(ctx, second-pos) | ||||
|     let (x1, y1, _) = first-pos | ||||
|     let (x2, y2, _) = second-pos | ||||
|     angle = calc.atan2(x2 - x1, y2 - y1) | ||||
|   } | ||||
|    | ||||
|   if name != none { | ||||
| @@ -199,7 +230,7 @@ | ||||
|         anchor = "south-east" | ||||
|       } | ||||
|  | ||||
|       draw.content(point, anchor: anchor, padding: 3pt, name) | ||||
|       draw.content(point, anchor: anchor, padding: 3pt, angle: angle, name) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user