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

Extend ShiftRegisterMem with single-port SRAM implementation #8

Merged
merged 2 commits into from
Dec 21, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
64 changes: 33 additions & 31 deletions src/main/scala/craft/ShiftRegisterMem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,45 @@ import chisel3.util._

object ShiftRegisterMem {

// use_sp_mem = use single port SRAMs? if false, use dual-port SRAMs
def apply[T <: Data](in: T, n: Int, en: Bool = true.B, use_sp_mem: Boolean = false, name: String = null): T =
{
requireIsHardware(in)
//require(n%2 == 0, "Odd ShiftRegsiterMem not supported yet")

if (n == 0) {
in
} else if (n == 1) {
val out = RegEnable(in, en)
out
//} else if (use_sp_mem && n%2 == 0) { // TODO: this passes the test but doesn't work for all cases
// val out = Wire(in.cloneType)
// val mem = SyncReadMem(n/2, Vec(in, in))
// if (name != null) {
// println(s"Name support not implemented")
// //sram.setName(name)
// }
// val index_counter = Counter(en, n)._1
// val raddr = (index_counter + 2.U) >> 1.U
// val waddr = RegEnable(index_counter >> 1.U, (n/2-1).U, en)
// val wen = index_counter(0) && en
// val des = Reg(in.cloneType)
// val ser = Reg(in.cloneType)

// val sram_out = Reg(next=mem.read(raddr, !wen))

// when (wen) {
// mem.write(waddr, Vec(des, in))
// out := ser
// } .otherwise {
// des := in
// out := sram_out(0)
// ser := sram_out(1)
// }
// out
} else if (use_sp_mem) {
require(n % 2 == 0, "Odd shift register length with single-port SRAMs is not supported")

val out_sp0 = Wire(in.cloneType)
out_sp0 := DontCare

val out_sp1 = Wire(in.cloneType)
out_sp1 := DontCare

val mem_sp0 = SyncReadMem(n / 2, in.cloneType)
val mem_sp1 = SyncReadMem(n / 2, in.cloneType)

val index_counter = Counter(en, n)._1
val raddr_sp0 = index_counter >> 1.U
val raddr_sp1 = RegEnable(raddr_sp0, (n / 2 - 1).U, en)

val wen_sp0 = index_counter(0)
val wen_sp1 = WireDefault(false.B)
wen_sp1 := ~wen_sp0

when(en) {
val rdwrPort = mem_sp0(raddr_sp0)
when(wen_sp0) { rdwrPort := in }.otherwise { out_sp0 := rdwrPort }
}

when(en) {
val rdwrPort = mem_sp1(raddr_sp1)
when(wen_sp1) { rdwrPort := in }.otherwise { out_sp1 := rdwrPort }
}
val out = Mux(~wen_sp1, out_sp0, out_sp1)
out
} else {
val mem = SyncReadMem(n, in.cloneType)
if (name != null) {
Expand All @@ -52,11 +55,10 @@ object ShiftRegisterMem {
val raddr = Counter(en, n)._1
val out = mem.read(raddr)

val waddr = RegEnable(raddr, (n-1).U, en) //next, init, enable
when (en) {
val waddr = RegEnable(raddr, (n - 1).U, en)
when(en) {
mem.write(waddr, in)
}

out
}
}
Expand Down
34 changes: 11 additions & 23 deletions src/test/scala/craft/ShiftRegisterMemSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class ShiftRegisterMemSpec extends AnyFlatSpec with Matchers {
4 -> true,
5 -> true,
0 -> true,
0 -> true,
0 -> false, //true
0 -> true,
0 -> true,
0 -> true,
Expand All @@ -53,36 +53,22 @@ class ShiftRegisterMemSpec extends AnyFlatSpec with Matchers {
val X = -1

def runTest (dut : (UInt, Bool) => UInt, expected: Seq[Int]) =
chisel3.iotesters.Driver(() => new SRMemModule(dut)) {
chisel3.iotesters.Driver.execute(Array(
"--backend-name", "treadle"), () => new SRMemModule(dut)) {
c => new SRMemTester(c, testVector, expected)
} should be (true)

it should "work with single-ported memories, an enable, and an odd shift" in {
def testMem(in: UInt, en: Bool): UInt = ShiftRegisterMem(in, 5, en)

runTest(testMem _,
Seq(X, X, X, X, X, X, 1, 2, 3, 4, 5, 0, 0)
)
}

it should "work with single-ported memories, an enable, and an even shift" in {
def testMem(in: UInt, en: Bool): UInt = ShiftRegisterMem(in, 6, en)
def testMem(in: UInt, en: Bool): UInt = ShiftRegisterMem(in, 6, en, use_sp_mem = true)

runTest(testMem _,
Seq(X, X, X, X, X, X, X, 1, 2, 3, 4, 5, 0)
)
}

it should "work with single-ported memories, no enable, and an odd shift" in {
def testMem(in: UInt, en: Bool) = ShiftRegisterMem(in, 5)

runTest(testMem _,
Seq(X, X, X, X, X, 1, 6, 2, 3, 4, 5, 0, 0)
//Seq(X, X, X, X, X, X, X, 1, 2, 3, 4, 5, 0)
Seq(X, X, X, X, X, X, X, 1, 1, 2, 3, 4, 5)
)
}

it should "work with single-ported memories, no enable, and an even shift" in {
def testMem(in: UInt, en: Bool) = ShiftRegisterMem(in, 6)
def testMem(in: UInt, en: Bool) = ShiftRegisterMem(in, 6, use_sp_mem = true)

runTest(testMem _,
Seq(X, X, X, X, X, X, 1, 6, 2, 3, 4, 5, 0)
Expand All @@ -93,15 +79,17 @@ class ShiftRegisterMemSpec extends AnyFlatSpec with Matchers {
def testMem(in: UInt, en: Bool): UInt = ShiftRegisterMem(in, 5, en, use_sp_mem = false)

runTest(testMem _,
Seq(X, X, X, X, X, X, 1, 2, 3, 4, 5, 0, 0)
//Seq(X, X, X, X, X, X, 1, 2, 3, 4, 5, 0, 0)
Seq(X, X, X, X, X, X, 1, 2, 2, 3, 4, 5, 0)
)
}

it should "work with dual-ported memories, an enable, and an even shift" in {
def testMem(in: UInt, en: Bool): UInt = ShiftRegisterMem(in, 6, en, use_sp_mem = false)

runTest(testMem _,
Seq(X, X, X, X, X, X, X, 1, 2, 3, 4, 5, 0)
//Seq(X, X, X, X, X, X, X, 1, 2, 3, 4, 5, 0)
Seq(X, X, X, X, X, X, X, 1, 1, 2, 3, 4, 5)
)
}

Expand Down