Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a SyncReadMem wrapper with explicit read, write, and read/write ports #3228

Merged
merged 36 commits into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
b01a0f9
Implement fuzzer test to generate and check MemInterfaces
jardhu May 1, 2023
4cde261
Remove println
jardhu May 1, 2023
8294514
Apply suggestions from code review
jardhu May 1, 2023
9be4ece
Merge branch 'main' of github.com:chipsalliance/chisel into chisel-me…
jardhu May 10, 2023
8998eb2
Implement masking capability for MemInterfaces
jardhu May 11, 2023
bf7e037
Remove wrapper module and just instantiate the SyncReadMem directly
jardhu May 17, 2023
05c01ef
Remove clocked versions of mem interface call
jardhu May 17, 2023
be7040a
Mask argument renaming
jardhu May 17, 2023
00838da
Omit semicolons in MemInterfaceSpec
jardhu May 17, 2023
2ab8a80
Change names of value signals to 'data' in Memory ports
jardhu May 17, 2023
1483361
Scalafmt
jardhu May 17, 2023
ffba3bb
Don't emit clock warnings for clocked RDWR port
jardhu May 23, 2023
cd05510
Add clock wire for each memory port, allowing them to be optionally d…
jardhu May 23, 2023
1ed7cd6
Rename references of MemInterface to SRAM
jardhu May 23, 2023
ecaccd3
Rename rd, wr, wr to readPorts, writePorts, readwritePorts
jardhu May 31, 2023
e5b1923
Make portedness helper private
jardhu Jun 1, 2023
6169b25
Revert "Don't emit clock warnings for clocked RDWR port"
jardhu May 31, 2023
e2557e0
Rename MemInterface.scala to SRAM.scala
jardhu May 31, 2023
abf9d66
Remove unnecessary macro applications
jardhu Jun 1, 2023
07f6e43
Remove unnecessary comments
jardhu Jun 5, 2023
c3cbdb6
Use masked SRAM impl for masked API call, fixes test failing
jardhu Jun 5, 2023
a09e5b2
Use Option.when for mask signal
jared-barocsi Jun 6, 2023
0e2238c
Revert "Use Option.when for mask signal"
jardhu Jun 6, 2023
5302feb
Undo clock being in memory port bundles
jardhu Jun 6, 2023
9b6f96e
Error when creating a read-only or write-only SRAM
jardhu Jun 6, 2023
ddd1d78
Add memory element typeName and masked status to SRAMInterface.typeName
jardhu Jun 6, 2023
773a2f6
Make SRAMInterface constructor more similar in signature to SRAM.appl…
jardhu Jun 8, 2023
4bef798
Add basic documentation for SRAM
jardhu Jun 8, 2023
9540ad8
Scalafmt
jardhu Jun 8, 2023
1aeab48
Fix mdocs so it compiles
jardhu Jun 8, 2023
ace130c
Correct typo in documentation
jared-barocsi Jun 12, 2023
9bcd0f4
Merge branch 'main' into chisel-mem-interface-api
jared-barocsi Jun 13, 2023
fe132a3
Touch up on SRAM docs
jardhu Jun 14, 2023
a6fffc5
Merge branch 'chisel-mem-interface-api' of github.com:chipsalliance/c…
jardhu Jun 14, 2023
2972216
Fix references to mem.io in docs
jardhu Jun 14, 2023
6d5ff45
Update docs/src/explanations/memories.md
jackkoenig Jun 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions docs/src/explanations/memories.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,51 @@ Chisel memories can be initialized from an external `binary` or `hex` file emitt

For more information, check the experimental docs on [Loading Memories](../appendix/experimental-features#loading-memories) feature.

## SRAM

Chisel provides an API to generate `SRAM` memories, which are currently alternative APIs for `SyncReadMem`. The key difference between the `SRAM` and `SyncReadMem` APIs is the former's capability to declare a specific number of read, write, and read-write memory ports, which are interacted with using explicit bundles.

```scala mdoc:silent
class ModuleWithSRAM(numReadPorts: Int, numWritePorts: Int, numReadwritePorts: Int) extends Module {
val width: Int = 8

val io = IO(new SRAMInterface(1024, UInt(width.W), numReadPorts, numWritePorts, numReadwritePorts))

// Generate a SyncReadMem representing an SRAM with an explicit number of read, write, and read-write ports
io.mem :<>= SRAM(1024, UInt(width.W), numReadPorts, numWritePorts, numReadwritePorts)
}
```

To interact with a desired port, index into the `numReadPorts`, `numWritePorts`, and `numReadwritePorts` signals:

```scala mdoc:silent
class TopModule extends Module {
// Declare a 2 read, 2 write, 2 read-write ported SRAM with 8-bit UInt data members
val memModule = Module(new ModuleWithSRAM(2, 2, 2))

// Whenever we want to read from the first read port
mem.io.readPorts(0).address := 100.U
mem.io.readPorts(0).enable := true.B

// Read data is returned one cycle after enable is driven
val foo = WireInit(UInt(8.W), mem.io.readPorts(0).data)

// Whenever we want to write to the second write port
mem.io.writePorts(1).address := 5.U
mem.io.writePorts(1).enable := true.B
mem.io.writePorts(1).data := 12.U

// Whenever we want to read or write to the third read-write port
// Write:
mem.io.readwritePorts(2).address := 5.U
mem.io.readwritePorts(2).enable := true.B
mem.io.readwritePorts(2).isWrite := true.B
mem.io.readwritePorts(2).writeData := 100.U

// Read:
mem.io.readwritePorts(2).address := 5.U
mem.io.readwritePorts(2).enable := true.B
mem.io.readwritePorts(2).isWrite := false.B
val bar = WireInit(UInt(8.W), mem.io.readwritePorts(2).readData)
}
```
18 changes: 8 additions & 10 deletions src/main/scala/chisel3/util/SRAM.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,19 @@ class MemoryReadWritePort[T <: Data] private[chisel3] (tpe: T, addrWidth: Int, m
/** A IO bundle of signals connecting to the ports of a wrapped `SyncReadMem`, as requested by
* `SRAMInterface.apply`.
*
* @param memSize The size of the memory, used to calculate the address width
* @tparam tpe The data type of the memory port
* @param width The width of the address wires of each port
* @param numReadPorts The number of read ports
* @param numWritePorts The number of write ports
* @param numReadwritePorts The number of read/write ports
*/
class SRAMInterface[T <: Data](
memSize: BigInt,
tpe: T,
addrWidth: Int,
numReadPorts: Int,
numWritePorts: Int,
numReadwritePorts: Int,
masked: Boolean)
masked: Boolean = false)
extends Bundle {
if (masked) {
require(
Expand All @@ -94,6 +94,8 @@ class SRAMInterface[T <: Data](
}
override def typeName: String = s"SRAMInterface_${SRAM.portedness(numReadPorts, numWritePorts, numReadwritePorts)}${if(masked) "_masked" else ""}}_${tpe.typeName}"

val addrWidth = log2Up(memSize + 1)

val readPorts: Vec[MemoryReadPort[T]] = Vec(numReadPorts, new MemoryReadPort(tpe, addrWidth))
val writePorts: Vec[MemoryWritePort[T]] = Vec(numWritePorts, new MemoryWritePort(tpe, addrWidth, masked))
val readwritePorts: Vec[MemoryReadWritePort[T]] =
Expand All @@ -103,7 +105,7 @@ class SRAMInterface[T <: Data](
object SRAM {

/** Generates a [[SyncReadMem]] within the current module, connected to an explicit number
* of read, write, and read/write ports. This SRAM abstraction has both read and write capabilities: that is,
* of read, write, and read/write ports. This SRsizeAM abstraction has both read and write capabilities: that is,
* it contains at least one read accessor (a read-only or read-write port), and at least one write accessor
* (a write-only or read-write port).
*
Expand Down Expand Up @@ -178,9 +180,7 @@ object SRAM {
)
}

val addrWidth = log2Up(size + 1)

val _out = Wire(new SRAMInterface(tpe, addrWidth, numReadPorts, numWritePorts, numReadwritePorts, false))
val _out = Wire(new SRAMInterface(size, tpe, numReadPorts, numWritePorts, numReadwritePorts))
val mem = SyncReadMem(size, tpe)

for (i <- 0 until numReadPorts) {
Expand Down Expand Up @@ -230,9 +230,7 @@ object SRAM {
)
}

val addrWidth = log2Up(size + 1)

val _out = Wire(new SRAMInterface(tpe, addrWidth, numReadPorts, numWritePorts, numReadwritePorts, true))
val _out = Wire(new SRAMInterface(size, tpe, numReadPorts, numWritePorts, numReadwritePorts, true))
val mem = SyncReadMem(size, tpe)

for (i <- 0 until numReadPorts) {
Expand Down