{
	"components": {
		"PC":         {"type": "PC", "x": 40, "y": 250, "in": "NewPC", "out": "PC"},
		"ForkPC":     {"type": "Fork", "x": 80, "y": 265, "size": 32, "in": "In", "out": ["Out1", "Out2"]},
		"PCAdder":    {"type": "Add", "latency": 50, "x": 110, "y": 158, "in1": "In1", "in2": "In2", "out": "PC+4", "desc": {"default": "Calculates the address of the next sequential instruction.", "pt": "Calcula o endereço da instrução sequencial seguinte."}},
		"Const4":     {"type": "Constant", "x": 85, "y": 173, "out": "Out", "val": 4, "size": 32},
		"ForkPCAdder":{"type": "Fork", "x": 155, "y": 175, "size": 32, "in": "In", "out": ["Out1", "Out2"]},
		"MuxPC":      {"type": "Multiplexer", "latency": 15, "x": 15, "y": 248, "size": 32, "sel": "PCSrc", "in": ["0", "1"], "out": "Out", "desc": {"default": "Selects PC+4 or the branch address as the new PC.", "pt": "Selecciona o PC+4 ou o endereço de branch como novo PC."}},
		"InstMem":    {"type": "InstructionMemory", "latency": 300, "x": 90, "y": 215, "in": "Address", "out": "Instruction"},
		
		"IF/ID":      {"type": "PipelineRegister", "x": 180, "y": 110, "regs": {"NewPC": 32, "Instruction": 32}, "desc": {"default": "Register that separates two pipeline stages.\nThe values that transition to the next stage are stored here temporarily.", "pt": "Registo que separa duas etapas do pipeline.\nOs valores que transitam para a próxima etapa são armazenados aqui temporariamente."}},
		
		"DistInst":   {"type": "Distributor", "x": 200, "y": 250, "in": {"id": "Instruction", "size": 32}, "out": [{"msb": 31, "lsb": 26}, {"msb": 25, "lsb": 21}, {"msb": 20, "lsb": 16},   {"msb": 15, "lsb": 11}, {"msb": 15, "lsb": 0}]},
		"ForkRt":     {"type": "Fork", "x": 220, "y": 265, "size": 5, "in": "In", "out": ["Out1", "Out2"]},
		"RegBank":    {"type": "RegBank", "latency": 100, "x": 260, "y": 215, "num_regs": 32, "read_reg1": "ReadReg1", "read_reg2": "ReadReg2", "read_data1": "ReadData1", "read_data2": "ReadData2", "write_reg": "WriteReg", "write_data": "WriteData", "reg_write": "RegWrite", "const_regs": [{"reg": 0, "val": 0}]},
		"Control":    {"type": "ControlUnit", "latency": 50, "x": 230, "y": 70, "in": "Opcode"},
		"ExtendImm":  {"type": "SignExtend", "x": 280, "y": 330, "in": {"id": "In", "size": 16}, "out": {"id": "Out", "size": 32}, "desc": {"default": "Extends the instruction's immediate value from 16 to 32 bits, in the case it is an I-type instruction.", "pt": "Estende o valor imediato da instrução de 16 para 32 bits, no caso de ser uma instrução do tipo I."}},
		
		"ID/EX":      {"type": "PipelineRegister", "x": 390, "y": 110, "regs": {"ReadData1": 32, "ReadData2": 32, "NewPC": 32, "Imm": 32, "Rt": 5, "Rd": 5, "RegDst": 1, "ALUOp": 2, "ALUSrc": 1, "Branch": 1, "MemRead": 1, "MemWrite": 1, "MemToReg": 1, "RegWrite": 1}, "desc": {"default": "Register that separates two pipeline stages.\nThe values that transition to the next stage are stored here temporarily.", "pt": "Registo que separa duas etapas do pipeline.\nOs valores que transitam para a próxima etapa são armazenados aqui temporariamente."}},
		
		"ForkReg":    {"type": "Fork", "x": 410, "y": 281, "size": 32, "in": "In", "out": ["Out1", "Out2"]},
		"MuxReg":     {"type": "Multiplexer", "latency": 15, "x": 425, "y": 270, "size": 32, "sel": "ALUSrc", "out": "Out", "in": ["0", "1"], "desc": {"default": "Selects the value of the 2nd read register or the instruction's immediate value as the ALU's second operand.", "pt": "Selecciona o valor do 2º registo lido ou o valor imediato da instrução como segundo operando da ALU."}},
		"DistImm":    {"type": "Distributor", "x": 413, "y": 330, "in": {"id": "In", "size": 32}, "out": [{"msb": 31, "lsb": 0}, {"msb": 5, "lsb": 0}]},
		"ALUControl": {"type": "ALUControl", "latency": 50, "x": 426, "y": 330, "aluop": "ALUOp", "func": "func"},
		"ALU":        {"type": "ALU", "latency": 100, "x": 450, "y": 237, "in1": "In1", "in2": "In2", "control": "Operation", "out": "Result", "zero": "Zero"},
		"MuxDst":     {"type": "Multiplexer", "latency": 15, "x": 413, "y": 370, "size": 5, "sel": "RegDst", "in": ["0", "1"], "out": "Out", "desc": {"default": "Selects the instruction's rt or rd field as the destination register (WriteReg).", "pt": "Selecciona o campo rt ou rd da instrução como registo de destino (WriteReg)."}},
		"ShiftImm":   {"type": "ShiftLeft", "x": 450, "y": 190, "in": {"id": "In", "size": 32}, "out": {"id": "Out", "size": 32}, "amount": 2, "desc": {"default": "The 2 less significant bits of the addresses of the instructions are always 00 (the addresses are multiples of 4). As such, these bits are not included in the instruction's immediate value (offset).\nThis component restores those bits by shifting the value 2 bits to the left (or multiplying by 4), in case it is a branch instruction.", "pt": "Os 2 bits menos significativos dos endereços das instruções são sempre 00 (os endereços são múltiplos de 4). Como tal, estes bits não são incluídos no valor imediato da instrução (offset).\nEste componente restaura esses bits deslocando o valor 2 bits para a esquerda (ou multiplicando por 4), no caso de ser uma instrução de branch."}},
		"AddBranch":  {"type": "Add", "latency": 50, "x": 505, "y": 164, "in1": "In1", "in2": "In2", "out": "Out", "desc": {"default": "Adds the branch offset to the PC+4 to obtain the destination branch address, in case it is a branch instruction.", "pt": "Soma o offset do branch ao PC+4 para obter o endereço de destino do branch, no caso de ser uma instrução de branch."}},
		"ForkImm":    {"type": "Fork", "x": 415, "y": 292, "size": 32, "in": "In", "out": ["Out1", "Out2"]},
		
		"EX/MEM":     {"type": "PipelineRegister", "x": 550, "y": 110, "regs": {"Result": 32, "ReadData2": 32, "Zero": 1, "RegBankDst": 5, "Target": 32, "Branch": 1, "MemRead": 1, "MemWrite": 1, "MemToReg": 1, "RegWrite": 1}, "desc": {"default": "Register that separates two pipeline stages.\nThe values that transition to the next stage are stored here temporarily.", "pt": "Registo que separa duas etapas do pipeline.\nOs valores que transitam para a próxima etapa são armazenados aqui temporariamente."}},
		
		"ForkMem":    {"type": "Fork", "x": 572, "y": 275, "size": 32, "in": "In", "out": ["Out1", "Out2"]},
		"DataMem":    {"type": "DataMemory", "latency": 400, "x": 580, "y": 242, "size": 100, "address": "Address", "write_data": "WriteData", "out": "ReadData", "mem_read": "MemRead", "mem_write": "MemWrite"},
		"AndBranch":  {"type": "And", "x": 600, "y": 180, "in1": "Branch", "in2": "Zero", "out": "Branch", "desc": {"default": "Determines if a branch should occur.", "pt": "Determina se um branch será efectuado."}},
		
		"MEM/WB":     {"type": "PipelineRegister", "x": 680, "y": 110, "regs": {"Result": 32, "ReadData": 32, "RegBankDst": 5, "MemToReg": 1, "RegWrite": 1}, "desc": {"default": "Register that separates two pipeline stages.\nThe values that transition to the next stage are stored here temporarily.", "pt": "Registo que separa duas etapas do pipeline.\nOs valores que transitam para a próxima etapa são armazenados aqui temporariamente."}},
		
		"MuxMem":     {"type": "Multiplexer", "latency": 15, "x": 710, "y": 270, "size": 32, "sel": "MemToReg", "in": ["0", "1"], "out": "Out", "desc": {"default": "Selects the result of the ALU or the value read from memory to write to the destination register (WriteData).", "pt": "Selecciona o resultado da ALU ou o valor lido da memória para escrever no registo de destino (WriteData)."}}
	},
	"wires": [
		{"from": "PC", "out": "PC", "to": "ForkPC", "in": "In"},
		{"from": "ForkPC", "out": "Out1", "to": "InstMem", "in": "Address"},
		{"from": "ForkPC", "out": "Out2", "to": "PCAdder", "in": "In1", "points": [{"x": 80, "y": 169}]},
		{"from": "Const4", "out": "Out", "to": "PCAdder", "in": "In2"},
		{"from": "PCAdder", "out": "PC+4", "to": "ForkPCAdder", "in": "In"},
		{"from": "ForkPCAdder", "out": "Out1", "to": "MuxPC", "in": "0", "points": [{"x": 155, "y": 150}, {"x": 10, "y": 150}, {"x": 10, "y": 259}]},
		{"from": "MuxPC", "out": "Out", "to": "PC", "in": "NewPC"},
		{"from": "ForkPCAdder", "out": "Out2", "to": "IF/ID", "in": "NewPC", "end": {"x": 180, "y": 175}},
		{"from": "InstMem", "out": "Instruction", "to": "IF/ID", "in": "Instruction", "end": {"x": 180, "y": 265}},
		
		{"from": "IF/ID", "out": "NewPC", "to": "ID/EX", "in": "NewPC", "start": {"x": 195, "y": 175}, "end": {"x": 390, "y": 175}},
		{"from": "IF/ID", "out": "Instruction", "to": "DistInst", "in": "Instruction", "start": {"x": 195, "y": 265}},
		{"from": "DistInst", "out": "31-26", "to": "Control", "in": "Opcode", "start": {"x": 205, "y": 255}, "points": [{"x": 210, "y": 255}, {"x": 210, "y": 120}]},
		{"from": "DistInst", "out": "25-21", "to": "RegBank", "in": "ReadReg1", "start": {"x": 205, "y": 260}, "points": [{"x": 215, "y": 260}, {"x": 215, "y": 235}]},
		{"from": "DistInst", "out": "20-16", "to": "ForkRt", "in": "In", "start": {"x": 205, "y": 265}},
		{"from": "ForkRt", "out": "Out1", "to": "RegBank", "in": "ReadReg2", "points": [{"x": 220, "y": 255}]},
		{"from": "ForkRt", "out": "Out2", "to": "ID/EX", "in": "Rt", "points": [{"x": 220, "y": 381}], "end": {"x": 390, "y": 381}},
		{"from": "DistInst", "out": "15-0", "to": "ExtendImm", "in": "In", "start": {"x": 205, "y": 270}, "points": [{"x": 225, "y": 270}, {"x": 225, "y": 350}]},
		{"from": "DistInst", "out": "15-11", "to": "ID/EX", "in": "Rd", "start": {"x": 205, "y": 275}, "points": [{"x": 215, "y": 275}, {"x": 215, "y": 392}], "end": {"x": 390, "y": 392}},
		{"from": "RegBank", "out": "ReadData1", "to": "ID/EX", "in": "ReadData1", "end": {"x": 390, "y": 248}},
		{"from": "RegBank", "out": "ReadData2", "to": "ID/EX", "in": "ReadData2", "end": {"x": 390, "y": 281}},
		{"from": "ExtendImm", "out": "Out", "to": "ID/EX", "in": "Imm", "end": {"x": 390, "y": 350}},
		{"from": "Control", "out": "RegDst", "to": "ID/EX", "in": "RegDst", "start": {"x": 290, "y": 160}, "end": {"x": 390, "y": 160}},
		{"from": "Control", "out": "ALUSrc", "to": "ID/EX", "in": "ALUSrc", "start": {"x": 290, "y": 155}, "end": {"x": 390, "y": 155}},
		{"from": "Control", "out": "ALUOp", "to": "ID/EX", "in": "ALUOp", "start": {"x": 290, "y": 150}, "end": {"x": 390, "y": 150}},
		{"from": "Control", "out": "Branch", "to": "ID/EX", "in": "Branch", "start": {"x": 290, "y": 145}, "end": {"x": 390, "y": 145}},
		{"from": "Control", "out": "MemRead", "to": "ID/EX", "in": "MemRead", "start": {"x": 290, "y": 140}, "end": {"x": 390, "y": 140}},
		{"from": "Control", "out": "MemWrite", "to": "ID/EX", "in": "MemWrite", "start": {"x": 290, "y": 135}, "end": {"x": 390, "y": 135}},
		{"from": "Control", "out": "MemToReg", "to": "ID/EX", "in": "MemToReg", "start": {"x": 290, "y": 130}, "end": {"x": 390, "y": 130}},
		{"from": "Control", "out": "RegWrite", "to": "ID/EX", "in": "RegWrite", "start": {"x": 290, "y": 125}, "end": {"x": 390, "y": 125}},
		
		{"from": "ID/EX", "out": "ReadData1", "to": "ALU", "in": "In1", "start": {"x": 405, "y": 248}, "end": {"x": 450, "y": 248}},
		{"from": "ID/EX", "out": "ReadData2", "to": "ForkReg", "in": "In", "start": {"x": 405, "y": 281}},
		{"from": "ForkReg", "out": "Out1", "to": "MuxReg", "in": "0"},
		{"from": "ForkReg", "out": "Out2", "to": "EX/MEM", "in": "ReadData2", "points": [{"x": 410, "y": 308}], "end": {"x": 550, "y": 308}},
		{"from": "MuxReg", "out": "Out", "to": "ALU", "in": "In2", "end": {"x": 450, "y": 287}},
		{"from": "ID/EX", "out": "ALUSrc", "to": "MuxReg", "in": "ALUSrc", "start": {"x": 405, "y": 155}, "points": [{"x": 432, "y": 155}]},
		{"from": "ID/EX", "out": "Imm", "to": "DistImm", "in": "In", "start": {"x": 405, "y": 350}, "end": {"x": 413, "y": 350}},
		{"from": "ALUControl", "out": "Operation", "to": "ALU", "in": "Operation", "points": [{"x": 480, "y": 350}]},
		{"from": "DistImm", "out": "5-0", "to": "ALUControl", "in": "func", "start": {"x": 413, "y": 350}},
		{"from": "ID/EX", "out": "ALUOp", "to": "ALUControl", "in": "ALUOp", "start": {"x": 405, "y": 150}, "points": [{"x": 446, "y": 150}]},
		{"from": "ALU", "out": "Zero", "to": "EX/MEM", "in": "Zero", "start": {"x": 510, "y": 255}, "end": {"x": 550, "y": 255}},
		{"from": "ALU", "out": "Result", "to": "EX/MEM", "in": "Result", "start": {"x": 510, "y": 275}, "end": {"x": 550, "y": 275}},
		{"from": "ID/EX", "out": "Rt", "to": "MuxDst", "in": "0", "start": {"x": 405, "y": 381}},
		{"from": "ID/EX", "out": "Rd", "to": "MuxDst", "in": "1", "start": {"x": 405, "y": 392}},
		{"from": "ID/EX", "out": "RegDst", "to": "MuxDst", "in": "RegDst", "start": {"x": 405, "y": 160}, "points": [{"x": 420, "y": 160}]},
		{"from": "MuxDst", "out": "Out", "to": "EX/MEM", "in": "RegBankDst", "end": {"x": 550, "y": 387}},
		{"from": "ID/EX", "out": "NewPC", "to": "AddBranch", "in": "In1", "start": {"x": 405, "y": 175}},
		{"from": "DistImm", "out": "31-0", "to": "ForkImm", "in": "In", "start": {"x": 415, "y": 330}},
		{"from": "ForkImm", "out": "Out1", "to": "MuxReg", "in": "1"},
		{"from": "ForkImm", "out": "Out2", "to": "ShiftImm", "in": "In", "points": [{"x": 415, "y": 210}]},
		{"from": "ShiftImm", "out": "Out", "to": "AddBranch", "in": "In2", "points": [{"x": 497, "y": 210}, {"x": 497, "y": 186}]},
		{"from": "AddBranch", "out": "Out", "to": "EX/MEM", "in": "Target", "end": {"x": 550, "y": 181}},
		{"from": "ID/EX", "out": "Branch", "to": "EX/MEM", "in": "Branch", "start": {"x": 405, "y": 145}, "end": {"x": 550, "y": 145}},
		{"from": "ID/EX", "out": "MemRead", "to": "EX/MEM", "in": "MemRead", "start": {"x": 405, "y": 140}, "end": {"x": 550, "y": 140}},
		{"from": "ID/EX", "out": "MemWrite", "to": "EX/MEM", "in": "MemWrite", "start": {"x": 405, "y": 135}, "end": {"x": 550, "y": 135}},
		{"from": "ID/EX", "out": "MemToReg", "to": "EX/MEM", "in": "MemToReg", "start": {"x": 405, "y": 130}, "end": {"x": 550, "y": 130}},
		{"from": "ID/EX", "out": "RegWrite", "to": "EX/MEM", "in": "RegWrite", "start": {"x": 405, "y": 125}, "end": {"x": 550, "y": 125}},
		
		{"from": "EX/MEM", "out": "RegBankDst", "to": "MEM/WB", "in": "RegBankDst", "start": {"x": 565, "y": 387}, "end": {"x": 680, "y": 387}},
		{"from": "EX/MEM", "out": "Result", "to": "ForkMem", "in": "In", "start": {"x": 565, "y": 275}},
		{"from": "ForkMem", "out": "Out1", "to": "DataMem", "in": "Address"},
		{"from": "ForkMem", "out": "Out2", "to": "MEM/WB", "in": "Result", "points": [{"x": 572, "y": 360}], "end": {"x": 680, "y": 360}},
		{"from": "EX/MEM", "out": "ReadData2", "to": "DataMem", "in": "WriteData", "start": {"x": 565, "y": 308}},
		{"from": "DataMem", "out": "ReadData", "to": "MEM/WB", "in": "ReadData", "end": {"x": 680, "y": 292}},
		{"from": "EX/MEM", "out": "Target", "to": "MuxPC", "in": "1", "start": {"x": 565, "y": 181}, "points": [{"x": 575, "y": 181}, {"x": 575, "y": 50}, {"x": 5, "y": 50}, {"x": 5, "y": 270}]},
		{"from": "EX/MEM", "out": "Zero", "to": "AndBranch", "in": "Zero", "start": {"x": 565, "y": 255}, "points": [{"x": 572, "y": 255}, {"x": 572, "y": 200}]},
		{"from": "EX/MEM", "out": "Branch", "to": "AndBranch", "in": "Branch", "start": {"x": 565, "y": 145}, "points": [{"x": 580, "y": 145}, {"x": 580, "y": 190}]},
		{"from": "AndBranch", "out": "Branch", "to": "MuxPC", "in": "PCSrc", "points": [{"x": 640, "y": 195}, {"x": 640, "y": 30}, {"x": 22, "y": 30}]},
		{"from": "EX/MEM", "out": "MemRead", "to": "DataMem", "in": "MemRead", "start": {"x": 565, "y": 140}, "points": [{"x": 590, "y": 140}], "end": {"x": 590, "y": 242}},
		{"from": "EX/MEM", "out": "MemWrite", "to": "DataMem", "in": "MemWrite", "start": {"x": 565, "y": 135}, "points": [{"x": 650, "y": 135}], "end": {"x": 650, "y": 242}},
		{"from": "EX/MEM", "out": "MemToReg", "to": "MEM/WB", "in": "MemToReg", "start": {"x": 565, "y": 130}, "end": {"x": 680, "y": 130}},
		{"from": "EX/MEM", "out": "RegWrite", "to": "MEM/WB", "in": "RegWrite", "start": {"x": 565, "y": 125}, "end": {"x": 680, "y": 125}},
		
		{"from": "MEM/WB", "out": "ReadData", "to": "MuxMem", "in": "1", "start": {"x": 695, "y": 292}},
		{"from": "MEM/WB", "out": "Result", "to": "MuxMem", "in": "0", "start": {"x": 695, "y": 360}, "points": [{"x": 702, "y": 360}, {"x": 702, "y": 281}]},
		{"from": "MEM/WB", "out": "MemToReg", "to": "MuxMem", "in": "MemToReg", "start": {"x": 695, "y": 130}, "points": [{"x": 717, "y": 130}]},
		{"from": "MEM/WB", "out": "RegBankDst", "to": "RegBank", "in": "WriteReg", "start": {"x": 695, "y": 387}, "points": [{"x": 705, "y": 387}, {"x": 705, "y": 420}, {"x": 250, "y": 420}, {"x": 250, "y": 275}], "end": {"x": 260, "y": 275}},
		{"from": "MuxMem", "out": "Out", "to": "RegBank", "in": "WriteData", "points": [{"x": 730, "y": 287}, {"x": 730, "y": 430}, {"x": 240, "y": 430}, {"x": 240, "y": 295}], "end": {"x": 260, "y": 295}},
		{"from": "MEM/WB", "out": "RegWrite", "to": "RegBank", "in": "RegWrite", "start": {"x": 695, "y": 125}, "points": [{"x": 705, "y": 125}, {"x": 705, "y": 100}, {"x": 300, "y": 100}]}
	],
	"reg_names": ["zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"],
	"instructions": "default-no-jump.set"
}
