Skip to content

Commit

Permalink
Modify noncombin memory to follow new good policy
Browse files Browse the repository at this point in the history
  • Loading branch information
Jared Barocsi committed Jul 31, 2019
1 parent fecc7df commit 5face5e
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 26 deletions.
25 changes: 9 additions & 16 deletions src/main/scala/components/memory/memory-noncombin-ports.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class OutstandingReq extends Bundle {
class INonCombinMemPort extends ICombinMemPort {
// To fake combinational writes
// TODO: It may be a good idea to move this into a custom utility module
val imemBusy = Reg (new Bool)
val imemBusy = RegInit (false.B)
imemBusy := DontCare

when (io.pipeline.valid) {
Expand All @@ -33,7 +33,9 @@ class INonCombinMemPort extends ICombinMemPort {
imemBusy := false.B
}

io.pipeline.good := (~ imemBusy || io.bus.response.valid)
val ready = !imemBusy || io.bus.response.valid

io.pipeline.good := ready
}

/**
Expand All @@ -42,19 +44,6 @@ class INonCombinMemPort extends ICombinMemPort {
* The I/O for this module is defined in [[DMemPortIO]].
*/
class DNonCombinMemPort extends BaseDMemPort {
// To fake combinational writes
// TODO: It may be a good idea to move this into a custom utility module
val dmemBusy = Reg (new Bool)
dmemBusy := DontCare

io.pipeline.good := (! dmemBusy || io.bus.response.valid)

when (io.pipeline.valid && io.pipeline.memread && !io.pipeline.memwrite) {
dmemBusy := true.B
} .elsewhen (io.bus.response.valid) {
dmemBusy := false.B
}

// A register to hold intermediate data (e.g., write data, mask mode) while the request
// is outstanding to memory.
val outstandingReq = RegInit(0.U.asTypeOf(Valid(new OutstandingReq)))
Expand All @@ -68,7 +57,11 @@ class DNonCombinMemPort extends BaseDMemPort {
// Ready if either we don't have an outstanding request or the outstanding request is a read and
// it has been satisfied this cycle. Note: we cannot send a read until one cycle after the write has
// been sent.
val ready = !outstandingReq.valid || (io.bus.response.valid && (outstandingReq.valid && outstandingReq.bits.operation === MemoryOperation.Read))
val wasRequestARead = outstandingReq.valid && outstandingReq.bits.operation === MemoryOperation.Read
val ready = !outstandingReq.valid || (io.bus.response.valid && wasRequestARead)

io.pipeline.good := ready

when (io.pipeline.valid && (io.pipeline.memread || io.pipeline.memwrite) && ready) {
// Check if we aren't issuing both a read and write at the same time
assert (! (io.pipeline.memread && io.pipeline.memwrite))
Expand Down
31 changes: 21 additions & 10 deletions src/test/scala/components/NonCombinMemoryUnitTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ class AsyncMemoryUnitTester$IMemRead(m: NonCombinMemoryTestHarness, size: Int, l
}
// Test data port writes and instruction port reads
class AsyncMemoryUnitTester$IMemWrite(m: NonCombinMemoryTestHarness, size: Int, latency: Int) extends PeekPokeTester(m) {
println ("First expect\n")
expect(m.io.dmem_good, 1)
println ("Done\n")
// write ascending data to memory
for (i <- 0 until size/8) {
poke(m.io.dmem_address, i*4)
Expand All @@ -129,20 +131,25 @@ class AsyncMemoryUnitTester$IMemWrite(m: NonCombinMemoryTestHarness, size: Int,
poke(m.io.dmem_valid, 0)

if (latency > 1) {
// Data memory does not stall on writes
expect(m.io.dmem_good, 1)
expect(m.io.dmem_good, 0)
step(latency - 1)
}
// We expect not good from the dmemport, as this is the cycle used to perform a writeback
expect(m.io.dmem_good, 0)
// We wait 1 extra cycle for the data memory to send the write back
step(1)

// Memory should be outputting high on good
// Memory should now be good
expect(m.io.dmem_good, 1)
}

poke (m.io.dmem_memwrite, 0)
poke (m.io.dmem_valid, 0)

// Check that data memory remains good after performing an operation
for (i <- 0 until 4) {
step(1)
expect(m.io.dmem_good, 1)
}
expect (m.io.imem_good, 1)

// expect ascending bytes, the first size/8 of them being incremented by 100, on instruction port
Expand All @@ -164,6 +171,12 @@ class AsyncMemoryUnitTester$IMemWrite(m: NonCombinMemoryTestHarness, size: Int,
}
expect(m.io.imem_good, 1)
}

// Check that memory remains good after performing operations (idling)
for (i <- 0 until 4) {
step (1)
expect (m.io.imem_good, 1)
}
}

// Test data port reading a zeroed memory file
Expand Down Expand Up @@ -242,10 +255,11 @@ class AsyncMemoryUnitTester$DMemWrite(m: NonCombinMemoryTestHarness, size: Int,
poke(m.io.dmem_valid, 0)
if (latency > 1) {
// Data memory does not stall on writes
expect(m.io.dmem_good, 1)
expect(m.io.dmem_good, 0)
step(latency - 1)
}
// We wait 1 extra cycle for the data memory to send the write back
// Memory should not be outputting high since this is the cycle used for the writeback
expect(m.io.dmem_good, 0)
step(1)

expect(m.io.dmem_good, 1)
Expand Down Expand Up @@ -300,7 +314,6 @@ class AsyncMemoryUnitTester$DMemWrite(m: NonCombinMemoryTestHarness, size: Int,
*/
class NonCombinMemoryTester extends ChiselFlatSpec {
val latency = new Random().nextInt (4) + 3

// imem side
"DualPortedNonCombinMemory" should s"have all zeros in instruction port (with treadle and $latency latency cycles)" in {
Driver(() => new NonCombinMemoryTestHarness(2048, "src/test/resources/raw/zero.hex", latency), "treadle") {
Expand All @@ -311,20 +324,18 @@ class NonCombinMemoryTester extends ChiselFlatSpec {
Driver(() => new NonCombinMemoryTestHarness(2048, "src/test/resources/raw/ascending.hex", latency), "treadle") {
m => new AsyncMemoryUnitTester$IMemRead(m, 2048, latency)
} should be (true)
}
}
"DualPortedNonCombinMemory" should s"store words with data port and load with instruction port (with treadle and $latency latency cycles)" in {
Driver(() => new NonCombinMemoryTestHarness(2048, "src/test/resources/raw/ascending.hex", latency), "treadle") {
m => new AsyncMemoryUnitTester$IMemWrite(m, 2048, latency)
} should be (true)
}

// dmem side
"DualPortedNonCombinMemory" should s"have all zeros in data port (with treadle and $latency latency cycles)" in {
Driver(() => new NonCombinMemoryTestHarness(2048, "src/test/resources/raw/zero.hex", latency), "treadle") {
m => new AsyncMemoryUnitTester$DMemZero(m, 2048, latency)
} should be (true)
}

"DualPortedNonCombinMemory" should s"have increasing words in data port (with treadle and $latency latency cycles)" in {
Driver(() => new NonCombinMemoryTestHarness(2048, "src/test/resources/raw/ascending.hex", latency), "treadle") {
m => new AsyncMemoryUnitTester$DMemRead(m, 2048, latency)
Expand Down

0 comments on commit 5face5e

Please sign in to comment.