This repository has been archived by the owner on Aug 19, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 76
/
Compiler.scala
78 lines (69 loc) · 3.35 KB
/
Compiler.scala
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
// SPDX-License-Identifier: Apache-2.0
package chiseltest.simulator
import chisel3.RawModule
import chisel3.stage._
import chisel3.stage.phases._
import firrtl.{AnnotationSeq, EmittedCircuitAnnotation}
import firrtl.annotations.{Annotation, DeletedAnnotation}
import firrtl.options.TargetDirAnnotation
import firrtl.stage.{FirrtlCircuitAnnotation, FirrtlStage}
import logger.{LogLevelAnnotation, Logger}
private[chiseltest] object Compiler {
private val elaboratePhase = new Elaborate
def elaborate[M <: RawModule](gen: () => M, annotationSeq: AnnotationSeq): (firrtl.CircuitState, M) = {
// run Builder.build(Module(gen()))
val genAnno = ChiselGeneratorAnnotation(gen)
val elaborationAnnos = Logger.makeScope(annotationSeq) { elaboratePhase.transform(genAnno +: annotationSeq) }
// extract elaborated module
val dut = elaborationAnnos.collectFirst { case DesignAnnotation(d) => d }.get
// run aspects
val aspectAnnos = maybeAspects.transform(elaborationAnnos)
// run Converter.convert(a.circuit) and toFirrtl on all annotations
val converterAnnos = converter.transform(aspectAnnos)
// annos to state
val state = annosToState(converterAnnos)
(state, dut.asInstanceOf[M])
}
def toLowFirrtl(state: firrtl.CircuitState, annos: AnnotationSeq = List()): firrtl.CircuitState = {
requireTargetDir(state.annotations)
val inAnnos = annos ++: stateToAnnos(state)
val res = firrtlStage.execute(Array("-E", "low"), inAnnos)
annosToState(res)
}
def lowFirrtlToSystemVerilog(state: firrtl.CircuitState, annos: AnnotationSeq = List()): firrtl.CircuitState = {
requireTargetDir(state.annotations)
val inAnnos = annos ++: stateToAnnos(state)
val res = firrtlStage.execute(Array("--start-from", "low", "-E", "sverilog"), inAnnos)
annosToState(res)
}
def lowFirrtlToVerilog(state: firrtl.CircuitState, annos: AnnotationSeq = List()): firrtl.CircuitState = {
requireTargetDir(state.annotations)
val inAnnos = annos ++: stateToAnnos(state)
val res = firrtlStage.execute(Array("--start-from", "low", "-E", "verilog"), inAnnos)
annosToState(res)
}
private val maybeAspects = new MaybeAspectPhase
private val converter = new Convert
private def stateToAnnos(state: firrtl.CircuitState): AnnotationSeq = {
val annosWithoutCircuit = state.annotations.filterNot(_.isInstanceOf[FirrtlCircuitAnnotation])
FirrtlCircuitAnnotation(state.circuit) +: annosWithoutCircuit
}
def annosToState(annos: AnnotationSeq): firrtl.CircuitState = {
val circuit = annos.collectFirst { case FirrtlCircuitAnnotation(c) => c }.get
val filteredAnnos = annos.filterNot(isInternalAnno)
firrtl.CircuitState(circuit, filteredAnnos)
}
private def isInternalAnno(a: Annotation): Boolean = a match {
case _: FirrtlCircuitAnnotation | _: DesignAnnotation[_] | _: ChiselCircuitAnnotation | _: DeletedAnnotation |
_: EmittedCircuitAnnotation[_] | _: LogLevelAnnotation =>
true
case _ => false
}
private def firrtlStage = new FirrtlStage
def requireTargetDir(annos: AnnotationSeq): os.Path = {
val targetDirs = annos.collect { case TargetDirAnnotation(d) => d }.toSet
require(targetDirs.nonEmpty, "Expected exactly one target directory, got none!")
require(targetDirs.size == 1, s"Expected exactly one target directory, got multiple: $targetDirs")
os.pwd / os.RelPath(targetDirs.head)
}
}