1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
import firrtl._
import firrtl.annotations.{Annotation, SingleTargetAnnotation}
import firrtl.annotations.{CircuitTarget, ModuleTarget, InstanceTarget, ReferenceTarget, Target}
import chisel3._
import chisel3.experimental.{annotate, ChiselAnnotation, RunFirrtlTransform}
import chisel3.internal.InstanceId
case class InfoAnnotation(target: Target, info: String) extends SingleTargetAnnotation[Target] {
def duplicate(newTarget: Target) = this.copy(target = newTarget)
}
object InfoAnnotator {
def info(component: InstanceId, info: String): Unit = {
annotate(new ChiselAnnotation with RunFirrtlTransform {
def toFirrtl: Annotation = InfoAnnotation(component.toTarget, info)
def transformClass = classOf[InfoTransform]
})
}
}
/** A transform that reads InfoAnnotations and prints information about them */
class InfoTransform() extends Transform with DependencyAPIMigration {
override def prerequisites = firrtl.stage.Forms.HighForm
override def execute(state: CircuitState): CircuitState = {
println("Starting transform 'IdentityTransform'")
// Add infoanno - a single format for all object types
val annotationsx = state.annotations.flatMap{
case InfoAnnotation(a: CircuitTarget, info) | InfoAnnotation(a: ModuleTarget, info) | InfoAnnotation(a: InstanceTarget, info) | InfoAnnotation(a: ReferenceTarget, info) =>
println(s"PROOF_MARKER {${a.serialize}, '$info'}")
None
case a =>
Some(a)
}
state.copy(annotations = annotationsx)
}
}
class RegisterFile() extends Module {
val io = IO(new Bundle {
val readreg1 = Input(UInt(5.W))
val readreg2 = Input(UInt(5.W))
val writereg = Input(UInt(5.W))
val writedata = Input(UInt(32.W))
val wen = Input(Bool())
val readdata1 = Output(UInt(32.W))
val readdata2 = Output(UInt(32.W))
})
// Required so the compiler doesn't optimize things away when testing
// incomplete designs.
dontTouch(io)
val regs = Reg(Vec(32, UInt(32.W)))
for (i <- 0 to regs.length-1) {
InfoAnnotator.info(regs(i), s"x$i")
}
// When the write enable is high, write the data
when (io.wen) {
regs(io.writereg) := io.writedata
}
// *Always* read the data. This is required for the single cycle CPU since in a single cycle it
// might both read and write the registers (e.g., an add)
io.readdata1 := regs(io.readreg1)
io.readdata2 := regs(io.readreg2)
}
class ALU() extends Module {
val io = IO(new Bundle {
val op = Input(UInt(4.W))
val in1 = Input(UInt(32.W))
val in2 = Input(UInt(32.W))
val out = Output(UInt(32.W))
val output_valid = Output(Bool())
})
io.out := 0.U
io.output_valid := false.B
when(io.op === 0.U) {
io.out := io.in1 & io.in2;
io.output_valid := true.B
}.elsewhen(io.op === 1.U) {
io.out := io.in1 | io.in2;
io.output_valid := true.B
}.elsewhen(io.op === 2.U) {
io.out := io.in1 + io.in2;
io.output_valid := true.B
}.elsewhen(io.op === 6.U) {
io.out := io.in1 - io.in2
io.output_valid := true.B
}.otherwise {
io.output_valid := false.B
}
}
println(getVerilog(new ALU))
// ChiselStage.emitChirrtl(new RegisterFile())
import chisel3.stage.{ChiselStage, ChiselGeneratorAnnotation}
// TODO fix type error here
(new ChiselStage).execute(Array.empty, Seq(ChiselGeneratorAnnotation(() => new RegisterFile())))
|