435 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Typst
		
	
	
	
	
	
			
		
		
	
	
			435 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Typst
		
	
	
	
	
	
| #import "@preview/cetz:0.2.2": draw
 | |
| #import "../src/lib.typ": *
 | |
| 
 | |
| #set page(flipped: true, paper: "a3")
 | |
| 
 | |
| #circuit({
 | |
|   element.multiplexer(
 | |
|     x: 0, y: 0, w: .5, h: 1.5, id: "PCMux",
 | |
|     entries: 2,
 | |
|     fill: util.colors.blue,
 | |
|     h-ratio: 80%
 | |
|   )
 | |
|   element.block(
 | |
|     x: (rel: 2, to: "PCMux.east"),
 | |
|     y: (from: "PCMux-port-out", to: "in"),
 | |
|     w: 1, h: 1.5, id: "PCBuf",
 | |
|     ports: (
 | |
|       north: ((id: "clk", clock: true),),
 | |
|       west: ((id: "in"),),
 | |
|       east: ((id: "out"),)
 | |
|     ),
 | |
|     fill: util.colors.green
 | |
|   )
 | |
| 
 | |
|   element.block(
 | |
|     x: (rel: 2, to: "PCBuf.east"),
 | |
|     y: (from: "PCBuf-port-out", to: "A"),
 | |
|     w: 3, h: 4, id: "IMem",
 | |
|     ports: (
 | |
|       west: (
 | |
|         (id: "A", name: "A"),
 | |
|       ),
 | |
|       east: (
 | |
|         (id: "RD", name: "RD"),
 | |
|       )
 | |
|     ),
 | |
|     ports-margins: (
 | |
|       west: (0%, 50%),
 | |
|       east: (0%, 50%)
 | |
|     ),
 | |
|     fill: util.colors.green,
 | |
|     name: "Instruction\nMemory"
 | |
|   )
 | |
|   element.block(
 | |
|     x: (rel: 3, to: "IMem.east"),
 | |
|     y: (from: "IMem-port-RD", to: "A1"),
 | |
|     w: 4.5, h: 4, id: "RegFile",
 | |
|     ports: (
 | |
|       north: (
 | |
|         (id: "clk", clock: true, small: true),
 | |
|         (id: "WE3", name: "WE3"),
 | |
|         (id: "dummy1")
 | |
|       ),
 | |
|       west: (
 | |
|         (id: "dummy2"),
 | |
|         (id: "A1", name: "A1"),
 | |
|         (id: "dummy3"),
 | |
|         (id: "A2", name: "A2"),
 | |
|         (id: "A3", name: "A3"),
 | |
|         (id: "dummy4"),
 | |
|         (id: "WD3", name: "WD3"),
 | |
|       ),
 | |
|       east: (
 | |
|         (id: "RD1", name: "RD1"),
 | |
|         (id: "RD2", name: "RD2"),
 | |
|       )
 | |
|     ),
 | |
|     ports-margins: (
 | |
|       north: (-20%, -20%),
 | |
|       east: (0%, 10%)
 | |
|     ),
 | |
|     fill: util.colors.green,
 | |
|     name: "Register\nFile"
 | |
|   )
 | |
| 
 | |
|   element.alu(
 | |
|     x: (rel: -.7, to: "IMem.center"),
 | |
|     y: -7,
 | |
|     w: 1.4, h: 2.8, id: "PCAdd",
 | |
|     name: text("+", size: 1.5em),
 | |
|     name-anchor: "name",
 | |
|     fill: util.colors.pink
 | |
|   )
 | |
|   element.extender(
 | |
|     x: (rel: 0, to: "RegFile.west"),
 | |
|     y: (from: "PCAdd-port-out", to: "in"),
 | |
|     w: 4, h: 1.5, id: "Ext",
 | |
|     h-ratio: 50%,
 | |
|     name: "Extend",
 | |
|     name-anchor: "south",
 | |
|     align-out: false,
 | |
|     fill: util.colors.green
 | |
|   )
 | |
| 
 | |
|   element.multiplexer(
 | |
|     x: (rel: 3, to: "RegFile.east"),
 | |
|     y: (from: "RegFile-port-RD2", to: "in0"),
 | |
|     w: .5, h: 1.5, id: "SrcBMux",
 | |
|     fill: util.colors.blue,
 | |
|     h-ratio: 80%
 | |
|   )
 | |
| 
 | |
|   element.alu(
 | |
|     x: (rel: 2, to: "SrcBMux.east"),
 | |
|     y: (from: "SrcBMux-port-out", to: "in2"),
 | |
|     w: 1.4, h: 2.8, id: "ALU",
 | |
|     name: rotate("ALU", -90deg),
 | |
|     name-anchor: "name",
 | |
|     fill: util.colors.pink
 | |
|   )
 | |
|   element.alu(
 | |
|     x: (rel: 2, to: "SrcBMux.east"),
 | |
|     y: (from: "Ext-port-out", to: "in2"),
 | |
|     w: 1.4, h: 2.8, id: "JumpAdd",
 | |
|     name: text("+", size: 1.5em),
 | |
|     name-anchor: "name",
 | |
|     fill: util.colors.pink
 | |
|   )
 | |
| 
 | |
|   element.block(
 | |
|     x: (rel: 4, to: "ALU.east"),
 | |
|     y: (from: "ALU-port-out", to: "A"),
 | |
|     w: 3, h: 4, id: "DMem",
 | |
|     name: "Data\nMemory",
 | |
|     ports: (
 | |
|       north: (
 | |
|         (id: "clk", clock: true, small: true),
 | |
|         (id: "dummy1"),
 | |
|         (id: "WE", name: "WE")
 | |
|       ),
 | |
|       west: (
 | |
|         (id: "A", name: "A"),
 | |
|         (id: "WD", name: "WD")
 | |
|       ),
 | |
|       east: (
 | |
|         (id: "RD", name: "RD"),
 | |
|         (id: "dummy2")
 | |
|       )
 | |
|     ),
 | |
|     ports-margins: (
 | |
|       north: (-10%, -10%),
 | |
|       west: (-20%, -30%),
 | |
|       east: (-10%, -20%)
 | |
|     ),
 | |
|     fill: util.colors.green
 | |
|   )
 | |
| 
 | |
|   element.multiplexer(
 | |
|     x: (rel: 3, to: "DMem.east"),
 | |
|     y: (from: "DMem-port-RD", to: "in1"),
 | |
|     w: .5, h: 1.5, id: "ResMux",
 | |
|     entries: 2,
 | |
|     fill: util.colors.blue,
 | |
|     h-ratio: 80%
 | |
|   )
 | |
| 
 | |
|   element.block(
 | |
|     x: (rel: 0, to: "RegFile.west"),
 | |
|     y: 3.5, w: 2.5, h: 5, id: "Ctrl",
 | |
|     name: "Control\nUnit",
 | |
|     name-anchor: "north",
 | |
|     ports: (
 | |
|       west: (
 | |
|         (id: "op", name: "op"),
 | |
|         (id: "funct3", name: "funct3"),
 | |
|         (id: "funct7", name: [funct7#sub("[5]")]),
 | |
|         (id: "zero", name: "Zero"),
 | |
|       ),
 | |
|       east: (
 | |
|         (id: "PCSrc"),
 | |
|         (id: "ResSrc"),
 | |
|         (id: "MemWrite"),
 | |
|         (id: "ALUCtrl"),
 | |
|         (id: "ALUSrc"),
 | |
|         (id: "ImmSrc"),
 | |
|         (id: "RegWrite"),
 | |
|       )
 | |
|     ),
 | |
|     ports-margins: (
 | |
|       west: (40%, 0%)
 | |
|     ),
 | |
|     fill: util.colors.orange
 | |
|   )
 | |
| 
 | |
|   // Wires
 | |
|   wire.wire(
 | |
|     "wPCNext", ("PCMux-port-out", "PCBuf-port-in"),
 | |
|     name: "PCNext"
 | |
|   )
 | |
|   wire.stub("PCBuf-port-clk", "north", name: "clk", length: 0.25)
 | |
|   wire.wire(
 | |
|     "wPC1", ("PCBuf-port-out", "IMem-port-A"),
 | |
|     name: "PC"
 | |
|   )
 | |
|   wire.wire(
 | |
|     "wPC2", ("PCBuf-port-out", "JumpAdd-port-in1"),
 | |
|     style: "zigzag",
 | |
|     zigzag-ratio: 1
 | |
|   )
 | |
|   wire.wire(
 | |
|     "wPC3", ("PCBuf-port-out", "PCAdd-port-in1"),
 | |
|     style: "zigzag",
 | |
|     zigzag-ratio: 1
 | |
|   )
 | |
|   wire.intersection("wPC2.zig", radius: 2pt)
 | |
|   wire.intersection("wPC2.zag", radius: 2pt)
 | |
|   wire.stub("PCAdd-port-in2", "west", name: "4", length: 1.5)
 | |
|   wire.wire(
 | |
|     "wPC+4", ("PCAdd-port-out", "PCMux-port-in0"),
 | |
|     style: "dodge",
 | |
|     dodge-sides: ("east", "west"),
 | |
|     dodge-y: -7.5,
 | |
|     dodge-margins: (1.2, .5),
 | |
|     name: "PC+4",
 | |
|     name-pos: "start"
 | |
|   )
 | |
|   
 | |
|   let mid = ("IMem-port-RD", 50%, "RegFile-port-A1")
 | |
|   wire.wire(
 | |
|     "wInstr", ("IMem-port-RD", mid),
 | |
|     bus: true,
 | |
|     name: "Instr",
 | |
|     name-pos: "start"
 | |
|   )
 | |
|   draw.hide({
 | |
|     draw.line(name: "bus-top",
 | |
|       mid,
 | |
|       (horizontal: (), vertical: "Ctrl-port-op")
 | |
|     )
 | |
|     draw.line(name: "bus-bot",
 | |
|       mid,
 | |
|       (horizontal: (), vertical: "Ext-port-in")
 | |
|     )
 | |
|   })
 | |
|   wire.wire(
 | |
|     "wInstrBus", ("bus-top.end", "bus-bot.end"),
 | |
|     bus: true
 | |
|   )
 | |
|   wire.wire(
 | |
|     "wOp", ("Ctrl-port-op", (horizontal: mid, vertical: ())),
 | |
|     bus: true,
 | |
|     reverse: true,
 | |
|     slice: (6, 0)
 | |
|   )
 | |
|   wire.wire(
 | |
|     "wF3", ("Ctrl-port-funct3", (horizontal: mid, vertical: ())),
 | |
|     bus: true,
 | |
|     reverse: true,
 | |
|     slice: (14, 12)
 | |
|   )
 | |
|   wire.wire(
 | |
|     "wF7", ("Ctrl-port-funct7", (horizontal: mid, vertical: ())),
 | |
|     bus: true,
 | |
|     reverse: true,
 | |
|     slice: (30,)
 | |
|   )
 | |
|   wire.wire(
 | |
|     "wA1", ("RegFile-port-A1", (horizontal: mid, vertical: ())),
 | |
|     bus: true,
 | |
|     reverse: true,
 | |
|     slice: (19, 15)
 | |
|   )
 | |
|   wire.wire(
 | |
|     "wA2", ("RegFile-port-A2", (horizontal: mid, vertical: ())),
 | |
|     bus: true,
 | |
|     reverse: true,
 | |
|     slice: (24, 20)
 | |
|   )
 | |
|   wire.wire(
 | |
|     "wA3", ("RegFile-port-A3", (horizontal: mid, vertical: ())),
 | |
|     bus: true,
 | |
|     reverse: true,
 | |
|     slice: (11, 7)
 | |
|   )
 | |
|   wire.wire(
 | |
|     "wExt", ("Ext-port-in", (horizontal: mid, vertical: ())),
 | |
|     bus: true,
 | |
|     reverse: true,
 | |
|     slice: (31, 7)
 | |
|   )
 | |
|   wire.intersection("wF3.end", radius: 2pt)
 | |
|   wire.intersection("wF7.end", radius: 2pt)
 | |
|   wire.intersection("wA1.end", radius: 2pt)
 | |
|   wire.intersection("wA2.end", radius: 2pt)
 | |
|   wire.intersection("wA3.end", radius: 2pt)
 | |
| 
 | |
|   wire.stub("RegFile-port-clk", "north", name: "clk", length: 0.25)
 | |
|   wire.wire("wRD2", ("RegFile-port-RD2", "SrcBMux-port-in0"))
 | |
|   wire.wire(
 | |
|     "wWD", ("RegFile-port-RD2", "DMem-port-WD"),
 | |
|     style: "zigzag",
 | |
|     zigzag-ratio: 1.5,
 | |
|     name: "WriteData",
 | |
|     name-pos: "end"
 | |
|   )
 | |
|   wire.intersection("wWD.zig", radius: 2pt)
 | |
| 
 | |
|   wire.wire(
 | |
|     "wImmALU", ("Ext-port-out", "SrcBMux-port-in1"),
 | |
|     style: "zigzag",
 | |
|     zigzag-ratio: 2.5,
 | |
|     name: "ImmExt",
 | |
|     name-pos: "start"
 | |
|   )
 | |
|   wire.wire(
 | |
|     "wImmJump", ("Ext-port-out", "JumpAdd-port-in2")
 | |
|   )
 | |
|   wire.intersection("wImmALU.zig", radius: 2pt)
 | |
|   wire.wire(
 | |
|     "wJumpPC", ("JumpAdd-port-out", "PCMux-port-in1"),
 | |
|     style: "dodge",
 | |
|     dodge-sides: ("east", "west"),
 | |
|     dodge-y: -8,
 | |
|     dodge-margins: (1, 1),
 | |
|     name: "PCTarget",
 | |
|     name-pos: "start"
 | |
|   )
 | |
| 
 | |
|   wire.wire(
 | |
|     "wSrcA", ("RegFile-port-RD1", "ALU-port-in1"),
 | |
|     name: "SrcA",
 | |
|     name-pos: "end"
 | |
|   )
 | |
|   wire.wire(
 | |
|     "wSrcB", ("SrcBMux-port-out", "ALU-port-in2"),
 | |
|     name: "SrcB",
 | |
|     name-pos: "end"
 | |
|   )
 | |
| 
 | |
|   wire.wire(
 | |
|     "wZero", (
 | |
|       ("ALU.north-east", 50%, "ALU-port-out"),
 | |
|       "Ctrl-port-zero"
 | |
|     ),
 | |
|     style: "dodge",
 | |
|     dodge-sides: ("east", "west"),
 | |
|     dodge-y: 3,
 | |
|     dodge-margins: (1.5, 1),
 | |
|     name: "Zero",
 | |
|     name-pos: "start"
 | |
|   )
 | |
|   wire.wire(
 | |
|     "wALURes1", ("ALU-port-out", "DMem-port-A"),
 | |
|     name: "ALUResult",
 | |
|     name-pos: "start"
 | |
|   )
 | |
|   wire.wire(
 | |
|     "wALURes2", ("ALU-port-out", "ResMux-port-in0"),
 | |
|     style: "dodge",
 | |
|     dodge-sides: ("east", "west"),
 | |
|     dodge-y: 2,
 | |
|     dodge-margins: (3, 2)
 | |
|   )
 | |
|   wire.intersection("wALURes2.start2", radius: 2pt)
 | |
| 
 | |
|   wire.stub("DMem-port-clk", "north", name: "clk", length: 0.25)
 | |
|   wire.wire(
 | |
|     "wRD", ("DMem-port-RD", "ResMux-port-in1"),
 | |
|     name: "ReadData",
 | |
|     name-pos: "start"
 | |
|   )
 | |
| 
 | |
|   wire.wire(
 | |
|     "wRes", ("ResMux-port-out", "RegFile-port-WD3"),
 | |
|     style: "dodge",
 | |
|     dodge-sides: ("east", "west"),
 | |
|     dodge-y: -7.5,
 | |
|     dodge-margins: (1, 2)
 | |
|   )
 | |
|   draw.content(
 | |
|     "wRes.dodge-start",
 | |
|     "Result",
 | |
|     anchor: "south-east",
 | |
|     padding: 5pt
 | |
|   )
 | |
| 
 | |
|   // Other wires
 | |
|   draw.group({
 | |
|     draw.stroke(util.colors.blue)
 | |
|     draw.line(name: "wPCSrc", 
 | |
|       "Ctrl-port-PCSrc",
 | |
|       (horizontal: "RegFile.east", vertical: ()),
 | |
|       (horizontal: (), vertical: (rel: (0, 0.5), to: "Ctrl.north")),
 | |
|       (horizontal: "PCMux.north", vertical: ()),
 | |
|       "PCMux.north"
 | |
|     )
 | |
|     draw.line(name: "wResSrc",
 | |
|       "Ctrl-port-ResSrc",
 | |
|       (horizontal: "ResMux.north", vertical: ()),
 | |
|       "ResMux.north"
 | |
|     )
 | |
|     draw.line(name: "wMemWrite",
 | |
|       "Ctrl-port-MemWrite",
 | |
|       (horizontal: "DMem-port-WE", vertical: ()),
 | |
|       "DMem-port-WE"
 | |
|     )
 | |
|     draw.line(name: "wALUCtrl",
 | |
|       "Ctrl-port-ALUCtrl",
 | |
|       (horizontal: "ALU.north", vertical: ()),
 | |
|       "ALU.north"
 | |
|     )
 | |
|     draw.line(name: "wALUSrc",
 | |
|       "Ctrl-port-ALUSrc",
 | |
|       (horizontal: "SrcBMux.north", vertical: ()),
 | |
|       "SrcBMux.north"
 | |
|     )
 | |
|     draw.line(name: "wImmSrc",
 | |
|       "Ctrl-port-ImmSrc",
 | |
|       (rel: (1, 0), to: (horizontal: "RegFile.east", vertical: ())),
 | |
|       (horizontal: (), vertical: (rel: (0, -.5), to: "RegFile.south")),
 | |
|       (horizontal: "Ext.north", vertical: ()),
 | |
|       "Ext.north"
 | |
|     )
 | |
|     draw.line(name: "wRegWrite",
 | |
|       "Ctrl-port-RegWrite",
 | |
|       (rel: (.5, 0), to: (horizontal: "RegFile.east", vertical: ())),
 | |
|       (horizontal: (), vertical: ("Ctrl.south", 50%, "RegFile.north")),
 | |
|       (horizontal: "RegFile-port-WE3", vertical: ()),
 | |
|       "RegFile-port-WE3"
 | |
|     )
 | |
| 
 | |
|     let names = (
 | |
|       "PCSrc": "PCSrc",
 | |
|       "ResSrc": "ResultSrc",
 | |
|       "MemWrite": "MemWrite",
 | |
|       "ALUCtrl": [ALUControl#sub("[2:0]")],
 | |
|       "ALUSrc": "ALUSrc",
 | |
|       "ImmSrc": [ImmSrc#sub("[1:0]")],
 | |
|       "RegWrite": "RegWrite"
 | |
|     )
 | |
|     for (port, name) in names {
 | |
|       draw.content("Ctrl-port-"+port, name, anchor: "south-west", padding: 3pt)
 | |
|     }
 | |
|   })
 | |
| }) |