Skip to content

Commit 017ecef

Browse files
committed
[Fix tywaves] type name a annotation for innertype in memories (case of Vecs)
- Added the following tests: - Masked memories (SyncReadMem, Mem, SRAM)
1 parent ff1de98 commit 017ecef

File tree

3 files changed

+153
-30
lines changed

3 files changed

+153
-30
lines changed

core/src/main/scala/chisel3/tywaves/TywavesAnnotation.scala

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ object TywavesChiselAnnotation {
6363

6464
def generate(command: Command, typeAliases: Seq[String]): Seq[ChiselAnnotation] = {
6565
def createAnnoMem(target: HasId, binding: String, size: BigInt, innerType: Data): Seq[ChiselAnnotation] = {
66-
val name = s"$binding[${innerType.typeName}[$size]]"
66+
val name = s"$binding[${dataToTypeName(innerType)}[$size]]"
6767
// TODO: what if innerType is a Vec or a Bundle?
6868

6969
Seq(new ChiselAnnotation {
@@ -104,37 +104,40 @@ object TywavesChiselAnnotation {
104104

105105
}
106106

107+
/** Return a fancy typeName for a given input [[Data]] */
108+
private def dataToTypeName(data: Data) = data match {
109+
// case t: Bundle =>
110+
// // t.className
111+
// t.toString.split(" ").last
112+
case t: Vec[?] =>
113+
t.toString.split(" ").last
114+
// This is a workaround to pretty print anonymous bundles and other records
115+
case t: Record =>
116+
// t.prettyPrint
117+
t.topBindingOpt match {
118+
case Some(binding) =>
119+
s"${t._bindingToString(binding)}[${t.className}]" // t._bindingToString(binding) + "[" + t.className + "]"
120+
case None => t.className
121+
}
122+
// case t: Bits =>
123+
// // t.typeName
124+
// t.topBindingOpt match {
125+
// case Some(binding) =>
126+
// s"${t._bindingToString(binding)}[Bits${t.width.toString}]" // t._bindingToString(binding) + "[" + t.className + "]"
127+
// case None => s"Bits${t.width.toString}"
128+
// }
129+
case t =>
130+
// t.typeName
131+
t.toString.split(" ").last
132+
}
133+
107134
/**
108135
* Create the annotation
109136
* @param target
110137
*/
111138
private def createAnno(target: Data): Seq[ChiselAnnotation] = {
112139
// val name = target.toString
113-
val name = target match {
114-
// case t: Bundle =>
115-
// // t.className
116-
// t.toString.split(" ").last
117-
case t: Vec[?] =>
118-
t.toString.split(" ").last
119-
// This is a workaround to pretty print anonymous bundles and other records
120-
case t: Record =>
121-
// t.prettyPrint
122-
t.topBindingOpt match {
123-
case Some(binding) =>
124-
s"${t._bindingToString(binding)}[${t.className}]" // t._bindingToString(binding) + "[" + t.className + "]"
125-
case None => t.className
126-
}
127-
// case t: Bits =>
128-
// // t.typeName
129-
// t.topBindingOpt match {
130-
// case Some(binding) =>
131-
// s"${t._bindingToString(binding)}[Bits${t.width.toString}]" // t._bindingToString(binding) + "[" + t.className + "]"
132-
// case None => s"Bits${t.width.toString}"
133-
// }
134-
case t =>
135-
// t.typeName
136-
target.toString.split(" ").last
137-
}
140+
val name = dataToTypeName(target)
138141

139142
var annotations: Seq[ChiselAnnotation] = Seq.empty
140143
target match {

src/test/scala/circtTests/tywavesTests/TywavesAnnotationCircuits.scala

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package circtTests.tywavesTests
33
import chisel3._
44
import chisel3.experimental.{Analog, IntrinsicModule}
55
import chisel3.experimental.hierarchy.{instantiable, Definition, Instance}
6-
import chisel3.properties.Class
76
import chisel3.stage.ChiselGeneratorAnnotation
87
import chisel3.util.{MixedVec, SRAM, SRAMInterface}
98
import circt.stage.ChiselStage
@@ -119,7 +118,7 @@ object TywavesAnnotationCircuits {
119118

120119
// An abstract description of a CSR, represented as a Class.
121120
@instantiable
122-
class CSRDescription extends Class
121+
class CSRDescription extends chisel3.properties.Class
123122

124123
class CSRModule(csrDescDef: Definition[CSRDescription]) extends RawModule {
125124
val csrDescription = Instance(csrDescDef)
@@ -273,5 +272,30 @@ object TywavesAnnotationCircuits {
273272
extends Module {
274273
val mem = SRAM(size, gen, numReadPorts, numWritePorts, numReadwritePorts)
275274
}
275+
276+
class TopCircuitMemWithMask[T <: Data, M <: MemBase[T]](_gen: T, _mem: Class[M], maskSize: Int) extends Module {
277+
278+
val gen = Vec(maskSize, _gen)
279+
val mem = {
280+
if (classOf[SyncReadMem[T]].isAssignableFrom(_mem)) SyncReadMem(4, gen)
281+
else if (classOf[Mem[T]].isAssignableFrom(_mem)) Mem(4, gen)
282+
else throw new Exception("Unknown memory type")
283+
}
284+
285+
val mask = Wire(Vec(maskSize, Bool()))
286+
287+
val idx = IO(Input(UInt(2.W)))
288+
val in = IO(Input(gen))
289+
val out = IO(Output(gen))
290+
291+
mem.write(idx, in, mask)
292+
out := mem.read(idx)
293+
}
294+
295+
class TopCircuitSRAMWithMask[T <: Data](_gen: T) extends Module {
296+
val maskSize = 2
297+
val gen = Vec(maskSize, _gen)
298+
val mem = SRAM.masked(4, gen, 1, 1, 0)
299+
}
276300
}
277301
}

src/test/scala/circtTests/tywavesTests/memTests/TypeAnnotationMemSpec.scala

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ class TypeAnnotationMemSpec extends AnyFunSpec with Matchers with chiselTests.Ut
166166
}
167167
}
168168

169-
describe("Memory annotations with MPORT connections") {
169+
describe("Memory Annotations with MPORT connections") {
170170

171171
val targetDir = os.pwd / "test_run_dir" / "TywavesAnnotationSpec" / "Memories Annotations with MPORT connections"
172172
val args: Array[String] = Array("--target", "chirrtl", "--target-dir", targetDir.toString)
@@ -205,7 +205,7 @@ class TypeAnnotationMemSpec extends AnyFunSpec with Matchers with chiselTests.Ut
205205
}
206206
}
207207

208-
describe("Memory annotations with MPORT connections of complex types") {
208+
describe("Memory Annotations with MPORT connections of complex types") {
209209
import circtTests.tywavesTests.TywavesAnnotationCircuits.DataTypesCircuits.MyBundle
210210

211211
val targetDir =
@@ -270,4 +270,100 @@ class TypeAnnotationMemSpec extends AnyFunSpec with Matchers with chiselTests.Ut
270270
checkAnno(expectedMatches, os.read(targetDir / "TopCircuitMem.fir"))
271271
}
272272
}
273+
274+
describe("Masked Memories Annotations") {
275+
val targetDir =
276+
os.pwd / "test_run_dir" / "TywavesAnnotationSpec" / "Masked Memories Annotations"
277+
val args: Array[String] = Array("--target", "chirrtl", "--target-dir", targetDir.toString)
278+
279+
it("should annotate a SyncMem with mask") {
280+
val mSize = 100
281+
new ChiselStage(true)
282+
.execute(
283+
args,
284+
Seq(ChiselGeneratorAnnotation(() => new TopCircuitMemWithMask(SInt(7.W), classOf[SyncReadMem[SInt]], mSize)))
285+
)
286+
val expectedMatches = Seq(
287+
(
288+
createExpected(
289+
"~TopCircuitMemWithMask\\|TopCircuitMemWithMask>mem",
290+
s"SInt<7>\\[$mSize\\]\\[4\\]",
291+
"SyncReadMem"
292+
),
293+
1
294+
),
295+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>mask", s"Bool\\[$mSize\\]", "Wire"), 1),
296+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>mask\\[0\\]", "Bool", "Wire"), 1),
297+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>idx", "UInt<2>", "IO"), 1),
298+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>in", s"SInt<7>\\[$mSize\\]", "IO"), 1),
299+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>in\\[0\\]", "SInt<7>", "IO"), 1),
300+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>out", s"SInt<7>\\[$mSize\\]", "IO"), 1),
301+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>out\\[0\\]", "SInt<7>", "IO"), 1),
302+
// tmp wire generated in syncreadmem
303+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>_WIRE", "UInt<2>", "Wire"), 1),
304+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>MPORT", s"SInt<7>\\[$mSize\\]", "MemPort"), 1),
305+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>MPORT\\[0\\]", "SInt<7>", "MemPort"), 1),
306+
(
307+
createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>MPORT_1", s"SInt<7>\\[$mSize\\]", "MemPort"),
308+
1
309+
),
310+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>MPORT_1\\[0\\]", "SInt<7>", "MemPort"), 1),
311+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>clock", "Clock", "IO"), 1),
312+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>reset", "Bool", "IO"), 1)
313+
)
314+
checkAnno(expectedMatches, os.read(targetDir / "TopCircuitMemWithMask.fir"))
315+
}
316+
317+
it("should annotate a Mem with mask") {
318+
val mSize = 100
319+
new ChiselStage(true)
320+
.execute(
321+
args,
322+
Seq(ChiselGeneratorAnnotation(() => new TopCircuitMemWithMask(SInt(7.W), classOf[Mem[SInt]], mSize)))
323+
)
324+
val expectedMatches = Seq(
325+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>mem", s"SInt<7>\\[$mSize\\]\\[4\\]", "Mem"), 1),
326+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>mask", s"Bool\\[$mSize\\]", "Wire"), 1),
327+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>mask\\[0\\]", "Bool", "Wire"), 1),
328+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>idx", "UInt<2>", "IO"), 1),
329+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>in", s"SInt<7>\\[$mSize\\]", "IO"), 1),
330+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>in\\[0\\]", "SInt<7>", "IO"), 1),
331+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>out", s"SInt<7>\\[$mSize\\]", "IO"), 1),
332+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>out\\[0\\]", "SInt<7>", "IO"), 1),
333+
// tmp wire generated in syncreadmem
334+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>MPORT", s"SInt<7>\\[$mSize\\]", "MemPort"), 1),
335+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>MPORT\\[0\\]", "SInt<7>", "MemPort"), 1),
336+
(
337+
createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>MPORT_1", s"SInt<7>\\[$mSize\\]", "MemPort"),
338+
1
339+
),
340+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>MPORT_1\\[0\\]", "SInt<7>", "MemPort"), 1),
341+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>clock", "Clock", "IO"), 1),
342+
(createExpected("~TopCircuitMemWithMask\\|TopCircuitMemWithMask>reset", "Bool", "IO"), 1)
343+
)
344+
checkAnno(expectedMatches, os.read(targetDir / "TopCircuitMemWithMask.fir"))
345+
}
346+
347+
it("should annotate an SRAM with mask") {
348+
val cName = "TopCircuitSRAMWithMask"
349+
new ChiselStage(true)
350+
.execute(
351+
args,
352+
Seq(ChiselGeneratorAnnotation(() => new TopCircuitSRAMWithMask(SInt(7.W))))
353+
)
354+
val expectedMatches = Seq(
355+
(createExpected(s"~$cName\\|$cName>mem_sram", "SInt<7>\\[2\\]\\[4\\]", "SramTarget"), 1),
356+
(createExpected(s"~$cName\\|$cName>mem.writePorts\\[0\\].mask", s"Bool\\[2\\]", "Wire"), 1),
357+
(createExpected(s"~$cName\\|$cName>mem.writePorts\\[0\\].mask\\[0\\]", "Bool", "Wire"), 1),
358+
// Since the inner type is a vector
359+
(createExpected(s"~$cName\\|$cName>mem.readPorts\\[0\\].data\\[0\\]", "SInt<7>", "Wire"), 1),
360+
(createExpected(s"~$cName\\|$cName>mem.writePorts\\[0\\].data\\[0\\]", "SInt<7>", "Wire"), 1),
361+
(createExpected(s"~$cName\\|$cName>clock", "Clock", "IO"), 1),
362+
(createExpected(s"~$cName\\|$cName>reset", "Bool", "IO"), 1)
363+
) ++ createExpectedSRAMs(s"~$cName\\|$cName>mem", 4, "SInt<7>\\[2\\]", 1, 1, 0)
364+
365+
checkAnno(expectedMatches, os.read(targetDir / s"$cName.fir"))
366+
367+
}
368+
}
273369
}

0 commit comments

Comments
 (0)