diff --git a/src/main/scala/base-cpu.scala b/src/main/scala/base-cpu.scala index ce57545b..0be8b27c 100644 --- a/src/main/scala/base-cpu.scala +++ b/src/main/scala/base-cpu.scala @@ -14,9 +14,4 @@ class CoreIO extends Bundle { class BaseCPU extends Module { val io = IO(new CoreIO()) - - // These signals are not and should not be used in the CPU implementation at all - - // they correspond with the port<=>memory connection, but we are in the pipeline<=> port side - io.imem.bus <> 0.U.asTypeOf(new MemPortBusIO) - io.dmem.bus <> 0.U.asTypeOf(new MemPortBusIO) } \ No newline at end of file diff --git a/src/main/scala/components/memory/base-memory-components.scala b/src/main/scala/components/memory/base-memory-components.scala index ce6bcee6..6deaec42 100644 --- a/src/main/scala/components/memory/base-memory-components.scala +++ b/src/main/scala/components/memory/base-memory-components.scala @@ -33,15 +33,26 @@ abstract class BaseDualPortedMemory(size: Int, memfile: String) extends Module { * Base class for all instruction ports. Simply declares the IO. */ abstract class BaseIMemPort extends Module { - val io = IO (new IMemPortIO) - io <> 0.U.asTypeOf (new IMemPortIO) + val io = IO (new Bundle { + val pipeline = new IMemPortIO + val bus = Flipped (new MemPortBusIO) + }) + + io.pipeline <> 0.U.asTypeOf (new IMemPortIO) + io.bus <> 0.U.asTypeOf (new MemPortBusIO) } /** * Base class for all data ports. Simply declares the IO. */ abstract class BaseDMemPort extends Module { - val io = IO (new DMemPortIO) - io <> 0.U.asTypeOf (new DMemPortIO) - io.good := io.bus.response.valid + val io = IO (new Bundle { + val pipeline = new DMemPortIO + val bus = Flipped (new MemPortBusIO) + }) + + io.pipeline <> 0.U.asTypeOf (new DMemPortIO) + io.bus <> 0.U.asTypeOf (new MemPortBusIO) + + io.pipeline.good := io.bus.response.valid } diff --git a/src/main/scala/components/memory/memory-combin-ports.scala b/src/main/scala/components/memory/memory-combin-ports.scala index 79e74b18..5eb111c5 100644 --- a/src/main/scala/components/memory/memory-combin-ports.scala +++ b/src/main/scala/components/memory/memory-combin-ports.scala @@ -13,9 +13,9 @@ import dinocpu.MemoryOperation._ */ class ICombinMemPort extends BaseIMemPort { // When the pipeline is supplying a high valid signal - when (io.valid) { + when (io.pipeline.valid) { val request = Wire(new Request) - request.address := io.address + request.address := io.pipeline.address request.operation := Read request.writedata := 0.U @@ -26,8 +26,8 @@ class ICombinMemPort extends BaseIMemPort { } // When the memory is outputting a valid instruction - io.good := io.bus.response.valid - io.instruction := io.bus.response.bits.data + io.pipeline.good := io.bus.response.valid + io.pipeline.instruction := io.bus.response.bits.data } /** @@ -36,16 +36,16 @@ class ICombinMemPort extends BaseIMemPort { * The I/O for this module is defined in [[DMemPortIO]]. */ class DCombinMemPort extends BaseDMemPort { - io.good := io.bus.response.valid && io.memread && !io.memwrite + io.pipeline.good := io.bus.response.valid && io.pipeline.memread && !io.pipeline.memwrite - when (io.valid && (io.memread || io.memwrite)) { + when (io.pipeline.valid && (io.pipeline.memread || io.pipeline.memwrite)) { // Check that we are not issuing a read and write at the same time - assert(!(io.memread && io.memwrite)) + assert(!(io.pipeline.memread && io.pipeline.memwrite)) - io.bus.request.bits.address := io.address + io.bus.request.bits.address := io.pipeline.address io.bus.request.valid := true.B - when (io.memwrite) { + when (io.pipeline.memwrite) { // We issue a ReadWrite to the backing memory. // Basic run-down of the ReadWrite operation: // - DCombinMemPort sends a ReadWrite at a specific address, **addr**. @@ -66,53 +66,53 @@ class DCombinMemPort extends BaseDMemPort { // Response path when (io.bus.response.valid) { - when (io.memwrite) { + when (io.pipeline.memwrite) { // Perform writedata modification and send it down io.request.writedata. val writedata = Wire (UInt (32.W)) // When not writing a whole word - when (io.maskmode =/= 2.U) { + when (io.pipeline.maskmode =/= 2.U) { // Read in the existing piece of data at the address, so we "overwrite" only part of it - val offset = io.address (1, 0) + val offset = io.pipeline.address (1, 0) val readdata = Wire (UInt (32.W)) readdata := io.bus.response.bits.data val data = Wire (UInt (32.W)) // Mask the portion of the existing data so it can be or'd with the writedata - when (io.maskmode === 0.U) { + when (io.pipeline.maskmode === 0.U) { data := readdata & ~(0xff.U << (offset * 8.U)) } .otherwise { data := readdata & ~(0xffff.U << (offset * 8.U)) } - writedata := data | (io.writedata << (offset * 8.U)) + writedata := data | (io.pipeline.writedata << (offset * 8.U)) } .otherwise { // Write the entire word - writedata := io.writedata + writedata := io.pipeline.writedata } io.bus.request.bits.writedata := writedata - } .elsewhen (io.memread) { + } .elsewhen (io.pipeline.memread) { // Perform normal masking and sign extension on the read data val readdata_mask = Wire(UInt(32.W)) val readdata_mask_sext = Wire(UInt(32.W)) - val offset = io.address(1,0) - when (io.maskmode === 0.U) { + val offset = io.pipeline.address(1,0) + when (io.pipeline.maskmode === 0.U) { // Byte readdata_mask := (io.bus.response.bits.data >> (offset * 8.U)) & 0xff.U - } .elsewhen (io.maskmode === 1.U) { + } .elsewhen (io.pipeline.maskmode === 1.U) { // Half-word readdata_mask := (io.bus.response.bits.data >> (offset * 8.U)) & 0xffff.U } .otherwise { readdata_mask := io.bus.response.bits.data } - when (io.sext) { - when (io.maskmode === 0.U) { + when (io.pipeline.sext) { + when (io.pipeline.maskmode === 0.U) { // Byte sign extension readdata_mask_sext := Cat(Fill(24, readdata_mask(7)), readdata_mask(7, 0)) - } .elsewhen (io.maskmode === 1.U) { + } .elsewhen (io.pipeline.maskmode === 1.U) { // Half-word sign extension readdata_mask_sext := Cat(Fill(16, readdata_mask(15)), readdata_mask(15, 0)) } .otherwise { @@ -123,7 +123,7 @@ class DCombinMemPort extends BaseDMemPort { readdata_mask_sext := readdata_mask } - io.readdata := readdata_mask_sext + io.pipeline.readdata := readdata_mask_sext } } } diff --git a/src/main/scala/components/memory/memory-noncombin-ports.scala b/src/main/scala/components/memory/memory-noncombin-ports.scala index 46b21852..003c5703 100644 --- a/src/main/scala/components/memory/memory-noncombin-ports.scala +++ b/src/main/scala/components/memory/memory-noncombin-ports.scala @@ -45,18 +45,18 @@ class DNonCombinMemPort extends BaseDMemPort { // 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)) - when (io.valid && (io.memread || io.memwrite) && 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.memread && io.memwrite)) + assert (! (io.pipeline.memread && io.pipeline.memwrite)) // On either a read or write we must read a whole block from memory. Store the necessary // information to redirect the memory's response back into itself through a write // operation and get the right subset of the block on a read. - outstandingReq.bits.address := io.address - outstandingReq.bits.writedata := io.writedata - outstandingReq.bits.maskmode := io.maskmode - outstandingReq.bits.sext := io.sext - when (io.memwrite) { + outstandingReq.bits.address := io.pipeline.address + outstandingReq.bits.writedata := io.pipeline.writedata + outstandingReq.bits.maskmode := io.pipeline.maskmode + outstandingReq.bits.sext := io.pipeline.sext + when (io.pipeline.memwrite) { outstandingReq.bits.operation := Write } .otherwise { outstandingReq.bits.operation := Read @@ -64,7 +64,7 @@ class DNonCombinMemPort extends BaseDMemPort { sending := true.B // Program memory to perform a read. Always read since we must read before write. - io.bus.request.bits.address := io.address + io.bus.request.bits.address := io.pipeline.address io.bus.request.bits.writedata := 0.U io.bus.request.bits.operation := Read io.bus.request.valid := true.B @@ -138,7 +138,7 @@ class DNonCombinMemPort extends BaseDMemPort { readdata_mask_sext := readdata_mask } - io.readdata := readdata_mask_sext + io.pipeline.readdata := readdata_mask_sext } // Mark the outstanding request register as being invalid, unless sending outstandingReq.valid := sending diff --git a/src/main/scala/components/memory/memory-port-io.scala b/src/main/scala/components/memory/memory-port-io.scala index a510ab69..ccf4dbc3 100644 --- a/src/main/scala/components/memory/memory-port-io.scala +++ b/src/main/scala/components/memory/memory-port-io.scala @@ -29,9 +29,6 @@ class MemPortIO extends Bundle { val address = Input(UInt(32.W)) val valid = Input(Bool()) val good = Output(Bool()) - - // Port <=> Memory - val bus = Flipped(new MemPortBusIO) } /** diff --git a/src/main/scala/top.scala b/src/main/scala/top.scala index 7ee2a5ed..ff8d675f 100644 --- a/src/main/scala/top.scala +++ b/src/main/scala/top.scala @@ -18,6 +18,6 @@ class Top(val conf: CPUConfig) extends Module val dmem = Module(conf.getDMemPort()) mem.wireMemory (imem, dmem) - cpu.io.imem <> imem.io - cpu.io.dmem <> dmem.io + cpu.io.imem <> imem.io.pipeline + cpu.io.dmem <> dmem.io.pipeline } diff --git a/src/test/scala/components/CombinMemoryUnitTest.scala b/src/test/scala/components/CombinMemoryUnitTest.scala index b2d11261..359feeb7 100644 --- a/src/test/scala/components/CombinMemoryUnitTest.scala +++ b/src/test/scala/components/CombinMemoryUnitTest.scala @@ -44,19 +44,19 @@ class CombinMemoryTestHarness(size: Int, memFile: String) extends Module { memory.io := DontCare - imem.io.address := io.imem_address - imem.io.valid := io.imem_valid - io.imem_instruction := imem.io.instruction - io.imem_good := imem.io.good - dmem.io.address := io.dmem_address - dmem.io.valid := io.dmem_valid - dmem.io.writedata := io.dmem_writedata - dmem.io.memread := io.dmem_memread - dmem.io.memwrite := io.dmem_memwrite - dmem.io.maskmode := io.dmem_maskmode - dmem.io.sext := io.dmem_sext - io.dmem_readdata := dmem.io.readdata - io.dmem_good := dmem.io.good + imem.io.pipeline.address := io.imem_address + imem.io.pipeline.valid := io.imem_valid + io.imem_instruction := imem.io.pipeline.instruction + io.imem_good := imem.io.pipeline.good + dmem.io.pipeline.address := io.dmem_address + dmem.io.pipeline.valid := io.dmem_valid + dmem.io.pipeline.writedata := io.dmem_writedata + dmem.io.pipeline.memread := io.dmem_memread + dmem.io.pipeline.memwrite := io.dmem_memwrite + dmem.io.pipeline.maskmode := io.dmem_maskmode + dmem.io.pipeline.sext := io.dmem_sext + io.dmem_readdata := dmem.io.pipeline.readdata + io.dmem_good := dmem.io.pipeline.good memory.wireMemory (imem, dmem) } diff --git a/src/test/scala/components/NonCombinMemoryUnitTest.scala b/src/test/scala/components/NonCombinMemoryUnitTest.scala index 0534cc6e..d4a693a9 100644 --- a/src/test/scala/components/NonCombinMemoryUnitTest.scala +++ b/src/test/scala/components/NonCombinMemoryUnitTest.scala @@ -47,19 +47,19 @@ class NonCombinMemoryTestHarness(size: Int, memFile: String, latency: Int) exten memory.io := DontCare - imem.io.address := io.imem_address - imem.io.valid := io.imem_valid - io.imem_instruction := imem.io.instruction - io.imem_good := imem.io.good - dmem.io.address := io.dmem_address - dmem.io.valid := io.dmem_valid - dmem.io.writedata := io.dmem_writedata - dmem.io.memread := io.dmem_memread - dmem.io.memwrite := io.dmem_memwrite - dmem.io.maskmode := io.dmem_maskmode - dmem.io.sext := io.dmem_sext - io.dmem_readdata := dmem.io.readdata - io.dmem_good := dmem.io.good + imem.io.pipeline.address := io.imem_address + imem.io.pipeline.valid := io.imem_valid + io.imem_instruction := imem.io.pipeline.instruction + io.imem_good := imem.io.pipeline.good + dmem.io.pipeline.address := io.dmem_address + dmem.io.pipeline.valid := io.dmem_valid + dmem.io.pipeline.writedata := io.dmem_writedata + dmem.io.pipeline.memread := io.dmem_memread + dmem.io.pipeline.memwrite := io.dmem_memwrite + dmem.io.pipeline.maskmode := io.dmem_maskmode + dmem.io.pipeline.sext := io.dmem_sext + io.dmem_readdata := dmem.io.pipeline.readdata + io.dmem_good := dmem.io.pipeline.good memory.wireMemory (imem, dmem) }