Skip to content

Instantly share code, notes, and snippets.

@lihaoyi
Created April 13, 2017 08:52
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lihaoyi/7895ee1bb0850d6a64e1d18b3f61a986 to your computer and use it in GitHub Desktop.
Save lihaoyi/7895ee1bb0850d6a64e1d18b3f61a986 to your computer and use it in GitHub Desktop.
package hello
import java.io.ByteArrayOutputStream
import chisel3._
import chisel3.iotesters.{Driver, PeekPokeTester}
sealed trait Op
object Op{
case class GotoIfZero(dest: Byte, valueAddr: Byte) extends Op
case class Set(dest: Byte, value: Byte) extends Op
case class Add(src1: Byte, src2: Byte, dest: Byte) extends Op
case class Sub(src1: Byte, src2: Byte, dest: Byte) extends Op
case class Mul(src1: Byte, src2: Byte, dest: Byte) extends Op
case class Div(src1: Byte, src2: Byte, dest: Byte) extends Op
case class Mod(src1: Byte, src2: Byte, dest: Byte) extends Op
case class Ret(valueAddr: Byte) extends Op
def serialize(instructions: Seq[Op]) = {
val output = new ByteArrayOutputStream()
def write(out: Byte*) = {
out.foreach(output.write(_))
}
instructions.foreach{
case GotoIfZero(dest, valueAddr) => write(0, dest, valueAddr, 0)
case Set(dest, value: Byte) => write(1, dest, value, 0)
case Add(src1, src2, dest) => write(2, src1, src2, dest)
case Sub(src1, src2, dest) => write(3, src1, src2, dest)
case Mul(src1, src2, dest) => write(4, src1, src2, dest)
case Div(src1, src2, dest) => write(5, src1, src2, dest)
case Mod(src1, src2, dest) => write(6, src1, src2, dest)
case Ret(valueAddr) => write(7, valueAddr, 0, 0)
}
output.toByteArray
}
}
class CPU extends Module {
val io = IO(new Bundle {
val out = Output(UInt(8.W))
val done = Output(Bool())
val mode = Input(Bool())
val in = Input(UInt(8.W))
// val instructionCounter = Output(UInt(8.W))
// val instructions = Output(Vec(Seq.fill(64) { 0.U(8.W) }))
// val memory = Output(Vec(Seq.fill(8) { 0.U(8.W) }))
// val dbg = Output(UInt(8.W))
})
val instrs = Reg(init = Vec(Seq.fill(64) { 0.U(8.W) }))
val memory = Reg(init = Vec(Seq.fill(8) { 0.U(8.W) }))
val PC = RegInit(UInt(8.W), 0.U)
val previousMode = RegInit(Bool(), 0.U)
val done = RegInit(Bool(), 0.U)
val result = RegInit(UInt(8.W), 0.U)
// io.instructionCounter := PC
// io.memory:= memory
io.out := result
// io.instructions := instrs
io.done := done
// io.dbg := instrs(PC + 1.U)
when(previousMode =/= io.mode){
PC := 0.U
previousMode := io.mode
}.otherwise{
previousMode := io.mode
when(io.mode === 0.U) {
instrs(PC) := io.in
PC := PC + 1.U
}.otherwise{
PC := PC + 4.U
when (instrs(PC) === 0.U){
when(memory(instrs(PC + 2.U)) === 0.U) {
PC := instrs(PC + 1.U) * 4.U
}
}.elsewhen(instrs(PC) === 1.U){
memory(instrs(PC + 1.U)) := instrs(PC + 2.U)
}.elsewhen(instrs(PC) === 2.U){
memory(instrs(PC + 3.U)) := memory(instrs(PC + 1.U)) + memory(instrs(PC + 2.U))
}.elsewhen(instrs(PC) === 3.U){
memory(instrs(PC + 3.U)) := memory(instrs(PC + 1.U)) - memory(instrs(PC + 2.U))
}.elsewhen(instrs(PC) === 4.U){
memory(instrs(PC + 3.U)) := memory(instrs(PC + 1.U)) * memory(instrs(PC + 2.U))
}.elsewhen(instrs(PC) === 5.U){
memory(instrs(PC + 3.U)) := memory(instrs(PC + 1.U)) / memory(instrs(PC + 2.U))
}.elsewhen(instrs(PC) === 6.U){
memory(instrs(PC + 3.U)) := memory(instrs(PC + 1.U)) % memory(instrs(PC + 2.U))
}.elsewhen(instrs(PC) === 7.U){
done := 1.U
result := memory(instrs(PC+1.U))
}
}
}
}
class CPUTests(c: CPU
) extends PeekPokeTester(c) {
import c.io._
poke(mode, 0)
val instructions = Seq(
/* 0 */ Op.Set(0, 0),
/* 1 */ Op.Set(1, 1),
/* 2 */ Op.Set(2, 23), // number i want to test if prime
/* 3 */ Op.Set(3, 1), // Counter at RAM index 3
/* 4 */ Op.Add(1, 3, 3),
/* 5 */ Op.Sub(2, 3, 4),
/* 6 */ Op.GotoIfZero(11, 4), // prime
/* 7 */ Op.Mod(2, 3, 4),
/* 8 */ Op.GotoIfZero(10, 4), // non-prime
/* 9 */ Op.GotoIfZero(4, 0), // loop around
/* 10 */ Op.Ret(0),
/* 11 */ Op.Ret(1)
)
val bytes = Op.serialize(instructions)
for(byte <- bytes){
poke(in, byte)
step(1)
}
// expect(instructionCounter, instructions.length * 4)
// peek(c.io.instructions).grouped(4).foreach(x => println(x.toString))
poke(mode, 1)
var count = 0
while(peek(done) != 1 && count < 1000){
count += 1
println(count.toString)
step(1)
// println()
// println("PC " + peek(instructionCounter) / 4)
// println("Memory " + peek(memory))
// println("Done " + peek(done))
// println("Instr " + peek(c.io.instructions).drop(peek(instructionCounter).toInt).take(4))
}
println("is prime " + peek(out))
}
object CPU {
def main(args: Array[String]): Unit = {
if (!Driver(() => new CPU(), backendType = "verilator")(c =>
new CPUTests(c))) System.exit(1
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment