main.scala (4835B)
1 //> using repository https://central.sonatype.com/repository/maven-snapshots 2 //> using scala 2.13.17 3 //> using dep org.chipsalliance::chisel:7.3.0 4 //> using plugin org.chipsalliance:::chisel-plugin:7.3.0 5 //> using options -unchecked -deprecation -language:reflectiveCalls -feature -Xcheckinit 6 //> using options -Xfatal-warnings -Ywarn-dead-code -Ywarn-unused -Ymacro-annotations 7 8 package com.rinthyAi.perilus.main 9 10 import chisel3._ 11 import chisel3.util._ 12 import _root_.circt.stage.ChiselStage 13 import scala.collection.mutable.ArrayBuffer 14 import scala.io.Source 15 16 import com.rinthyAi.perilus.alu._ 17 import com.rinthyAi.perilus.extendUnit._ 18 import com.rinthyAi.perilus.memory._ 19 import com.rinthyAi.perilus.registerFile._ 20 import com.rinthyAi.perilus.controlUnit._ 21 22 class Perilus( 23 initRegs: String = "", 24 initMem: String = "", 25 withDebug: Boolean = false 26 ) extends Module { 27 val width = 32.W 28 val memorySizeWords = if (initMem.nonEmpty) { 29 Source.fromFile(initMem).getLines().size 30 } else { 1048576 } 31 32 val io = IO(new Bundle { 33 val memory = Module(new Memory(memorySizeWords, width, initMem, withDebug)) 34 val registerFile = Module(new RegisterFile(width, initRegs, withDebug)) 35 val pc = Output(UInt(width)) 36 val debug = 37 if (withDebug) Some(new Bundle { 38 val reg = Input(UInt(5.W)) 39 val regData = Output(UInt(width)) 40 val memAddr = Input(UInt(width)) 41 val memData = Output(Vec(width.get / 8, UInt(8.W))) 42 val state = Output(ControlUnitState()) 43 }) 44 else None 45 }) 46 47 val alu = Module(new Alu()) 48 val controlUnit = Module(new ControlUnit(withDebug)) 49 val extendUnit = Module(new ExtendUnit()) 50 51 io.registerFile.io.debug.foreach(r => { 52 r.reg := 0.U 53 }) 54 io.memory.io.debug.foreach(m => { 55 m.memAddr := 0.U 56 }) 57 io.debug.foreach(d => { 58 io.registerFile.io.debug.foreach(r => { 59 r.reg := d.reg 60 d.regData := r.regData 61 }) 62 io.memory.io.debug.foreach(m => { 63 m.memAddr := d.memAddr 64 d.memData := m.memData 65 }) 66 controlUnit.io.debug.foreach(c => { 67 d.state := c.state 68 }) 69 }) 70 71 val pc = RegInit(0.U(width)) 72 val pcNext = WireDefault(UInt(width), 0.U) 73 when(controlUnit.io.pcWrite) { 74 // Mask LSB 75 pc := pcNext & ~1.U(width) 76 } 77 78 io.pc := pc 79 80 val oldPc = RegInit(0.U(width)) 81 when(controlUnit.io.irWrite) { 82 oldPc := pc 83 } 84 85 val instr = RegInit(0.U(width)) 86 when(controlUnit.io.irWrite) { 87 instr := io.memory.io.readData 88 } 89 90 val readDataBuf = RegInit(0.U(width)) 91 readDataBuf := io.memory.io.readData 92 93 val rd1Buf = RegInit(0.U(width)) 94 rd1Buf := io.registerFile.io.rd1 95 val rd2Buf = RegInit(0.U(width)) 96 rd2Buf := io.registerFile.io.rd2 97 98 val aluOutBuf = RegInit(0.U(width)) 99 aluOutBuf := alu.io.aluResult 100 101 val result = WireDefault(0.U(width)) 102 pcNext := result 103 switch(controlUnit.io.resultSrc) { 104 is(ResultSrc.aluOutBuf) { 105 result := aluOutBuf 106 } 107 is(ResultSrc.readDataBuf) { 108 result := readDataBuf 109 } 110 is(ResultSrc.aluResult) { 111 result := alu.io.aluResult 112 } 113 is(ResultSrc.immExt) { 114 result := extendUnit.io.immExt 115 } 116 } 117 118 alu.io.aluControl := controlUnit.io.aluControl 119 alu.io.srcA := 0.U 120 alu.io.srcB := 0.U 121 switch(controlUnit.io.aluSrcA) { 122 is(AluSrcA.pc) { 123 alu.io.srcA := pc 124 } 125 is(AluSrcA.oldPc) { 126 alu.io.srcA := oldPc 127 } 128 is(AluSrcA.rd1) { 129 alu.io.srcA := rd1Buf 130 } 131 } 132 switch(controlUnit.io.aluSrcB) { 133 is(AluSrcB.rd2) { 134 alu.io.srcB := rd2Buf 135 } 136 is(AluSrcB.immExt) { 137 alu.io.srcB := extendUnit.io.immExt 138 } 139 is(AluSrcB.four) { 140 alu.io.srcB := 4.U 141 } 142 } 143 controlUnit.io.zero := alu.io.zero 144 controlUnit.io.lessThan := alu.io.lessThan 145 146 val (opcode, opcodeValid) = Opcode.safe(instr(6, 0)) 147 controlUnit.io.op := opcode 148 controlUnit.io.funct3 := instr(14, 12) 149 controlUnit.io.funct7_5 := instr(30) 150 151 extendUnit.io.input := instr(31, 7) 152 extendUnit.io.immSrc := controlUnit.io.immSrc 153 154 when(controlUnit.io.adrSrc) { 155 io.memory.io.address := result 156 }.otherwise { 157 io.memory.io.address := pc 158 } 159 io.memory.io.writeData := rd2Buf 160 io.memory.io.writeEnable := controlUnit.io.memWrite 161 io.memory.io.dataMask := controlUnit.io.dataMask 162 io.memory.io.signExtData := controlUnit.io.signExtData 163 164 io.registerFile.io.a1 := instr(19, 15) 165 io.registerFile.io.a2 := instr(24, 20) 166 io.registerFile.io.a3 := instr(11, 7) 167 io.registerFile.io.writeData3 := result 168 io.registerFile.io.writeEnable3 := controlUnit.io.regWrite 169 } 170 171 object Perilus extends App { 172 println( 173 ChiselStage.emitSystemVerilogFile( 174 new Perilus, 175 args = Array("--target-dir", "generated"), 176 firtoolOpts = Array( 177 "-disable-all-randomization", 178 "-strip-debug-info", 179 "-default-layer-specialization=enable" 180 ) 181 ) 182 ) 183 }