增加puamips的cache文件
This commit is contained in:
parent
41da1f4c3e
commit
3134b79c54
|
@ -26,3 +26,29 @@ case class CpuConfig(
|
||||||
case class BranchPredictorConfig(
|
case class BranchPredictorConfig(
|
||||||
val bhtDepth: Int = 5,
|
val bhtDepth: Int = 5,
|
||||||
val phtDepth: Int = 6)
|
val phtDepth: Int = 6)
|
||||||
|
|
||||||
|
case class CacheConfig(
|
||||||
|
nway: Int = 2, // 路数
|
||||||
|
nbank: Int = 8, // bank数
|
||||||
|
nset: Int,
|
||||||
|
bankWidth: Int // bytes per bank
|
||||||
|
) {
|
||||||
|
val config = CpuConfig()
|
||||||
|
val indexWidth = log2Ceil(nset) // 6
|
||||||
|
val bankIndexWidth = log2Ceil(nbank) // 3
|
||||||
|
val bankOffsetWidth = log2Ceil(bankWidth) // 3
|
||||||
|
val offsetWidth = bankIndexWidth + bankOffsetWidth // 6
|
||||||
|
val tagWidth = 32 - indexWidth - offsetWidth // 20
|
||||||
|
val tagvWidth = tagWidth + 1 // 21
|
||||||
|
val bankWidthBits = bankWidth * 8 // 64
|
||||||
|
val burstSize = 16
|
||||||
|
val ninst = config.instFetchNum // TODO:改成可随意修改的参数
|
||||||
|
require(isPow2(nset))
|
||||||
|
require(isPow2(nway))
|
||||||
|
require(isPow2(nbank))
|
||||||
|
require(isPow2(bankWidth))
|
||||||
|
require(
|
||||||
|
tagWidth + indexWidth + bankIndexWidth + bankOffsetWidth == 32,
|
||||||
|
"basic request calculation"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
package cache.memory
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.util._
|
||||||
|
import cpu.CpuConfig
|
||||||
|
|
||||||
|
/** LUT ram for XPM, one port for read/write, one port for read
|
||||||
|
* @param depth
|
||||||
|
* how many lines there are in the bank
|
||||||
|
* @param width
|
||||||
|
* how wide in bits each line is
|
||||||
|
* @param config
|
||||||
|
* implicit configuration to control generate ram for simulation or elaboration
|
||||||
|
*/
|
||||||
|
class LUTRam(depth: Int, width: Int)(implicit val config: CpuConfig) extends Module {
|
||||||
|
require(isPow2(depth))
|
||||||
|
val waddridth = log2Ceil(depth)
|
||||||
|
val io = IO(new Bundle {
|
||||||
|
val raddr = Input(UInt(waddridth.W))
|
||||||
|
val rdata = Output(UInt(width.W))
|
||||||
|
|
||||||
|
val waddr = Input(UInt(waddridth.W))
|
||||||
|
val wdata = Input(UInt(width.W))
|
||||||
|
val wen = Input(Bool())
|
||||||
|
val writeOutput = Output(UInt(width.W))
|
||||||
|
})
|
||||||
|
|
||||||
|
if (config.build) {
|
||||||
|
val bank = Module(
|
||||||
|
new LUTRamIP(
|
||||||
|
wdataidth = width,
|
||||||
|
waddridth = waddridth,
|
||||||
|
byteWriteWidth = width,
|
||||||
|
numberOfLines = depth,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
bank.io.clka := clock
|
||||||
|
bank.io.clkb := clock
|
||||||
|
bank.io.rsta := reset
|
||||||
|
bank.io.rstb := reset
|
||||||
|
|
||||||
|
bank.io.regcea := false.B
|
||||||
|
bank.io.regceb := false.B
|
||||||
|
bank.io.ena := true.B
|
||||||
|
bank.io.enb := true.B
|
||||||
|
|
||||||
|
bank.io.addra := io.waddr
|
||||||
|
bank.io.wea := io.wen
|
||||||
|
bank.io.dina := io.wdata
|
||||||
|
io.writeOutput := DontCare
|
||||||
|
|
||||||
|
bank.io.addrb := io.raddr
|
||||||
|
io.rdata := bank.io.doutb
|
||||||
|
} else {
|
||||||
|
val bank = RegInit(VecInit(Seq.fill(depth)(0.U(width.W))))
|
||||||
|
io.rdata := bank(io.raddr)
|
||||||
|
io.writeOutput := DontCare
|
||||||
|
when(io.wen) {
|
||||||
|
bank(io.waddr) := io.wdata
|
||||||
|
}.otherwise {
|
||||||
|
io.writeOutput := bank(io.waddr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package cache.memory
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.util.log2Ceil
|
||||||
|
|
||||||
|
/** XPM 2019.2 XPM_MEMORY_DPDISTRAM, at page 124 of UG953(2019.2) by default, this is initialized to
|
||||||
|
* all 0
|
||||||
|
*
|
||||||
|
* @param wdataidth
|
||||||
|
* : the size of the data to store in each line, in bits
|
||||||
|
* @param waddridth
|
||||||
|
* : the width of request
|
||||||
|
* @param byteWriteWidth
|
||||||
|
* : addressable size of write
|
||||||
|
* @param numberOfLines
|
||||||
|
* : how many **bits** there are in the memory
|
||||||
|
*/
|
||||||
|
class LUTRamIP(wdataidth: Int, waddridth: Int, byteWriteWidth: Int, numberOfLines: Int)
|
||||||
|
extends BlackBox(
|
||||||
|
Map(
|
||||||
|
"ADDR_WIDTH_A" -> waddridth,
|
||||||
|
"ADDR_WIDTH_B" -> waddridth,
|
||||||
|
"MEMORY_SIZE" -> numberOfLines * wdataidth,
|
||||||
|
"WRITE_DATA_WIDTH_A" -> wdataidth,
|
||||||
|
"READ_DATA_WIDTH_A" -> wdataidth,
|
||||||
|
"READ_DATA_WIDTH_B" -> wdataidth,
|
||||||
|
"BYTE_WRITE_WIDTH_A" -> byteWriteWidth,
|
||||||
|
"READ_LATENCY_A" -> 0,
|
||||||
|
"READ_LATENCY_B" -> 0,
|
||||||
|
"READ_RESET_VALUE_A" -> 0,
|
||||||
|
"READ_RESET_VALUE_B" -> 0,
|
||||||
|
"CLOCKING_MODE" -> "common_clock",
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
override def desiredName: String = "xpm_memory_dpdistram"
|
||||||
|
require(
|
||||||
|
waddridth == log2Ceil(numberOfLines),
|
||||||
|
"request width should be log 2 of number of lines to request all",
|
||||||
|
)
|
||||||
|
require(
|
||||||
|
wdataidth - (wdataidth / byteWriteWidth) * byteWriteWidth == 0,
|
||||||
|
"data width should be a multiple of byte write width",
|
||||||
|
)
|
||||||
|
require(waddridth <= 20, "request width should be 1 to 20")
|
||||||
|
val io = IO(new Bundle {
|
||||||
|
val clka = Input(Clock())
|
||||||
|
val clkb = Input(Clock())
|
||||||
|
val rsta = Input(Reset())
|
||||||
|
val rstb = Input(Reset())
|
||||||
|
|
||||||
|
val ena = Input(Bool())
|
||||||
|
val enb = Input(Bool())
|
||||||
|
val regcea = Input(Bool())
|
||||||
|
val regceb = Input(Bool())
|
||||||
|
|
||||||
|
val dina = Input(UInt(wdataidth.W))
|
||||||
|
val addra = Input(UInt(waddridth.W))
|
||||||
|
val addrb = Input(UInt(waddridth.W))
|
||||||
|
|
||||||
|
val wea = Input(UInt((wdataidth / byteWriteWidth).W))
|
||||||
|
|
||||||
|
val douta = Output(UInt(wdataidth.W))
|
||||||
|
val doutb = Output(UInt(wdataidth.W))
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package cache.memory
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.util._
|
||||||
|
import cpu.CacheConfig
|
||||||
|
|
||||||
|
class ReadOnlyPort[+T <: Data](gen: T)(implicit cacheConfig: CacheConfig) extends Bundle {
|
||||||
|
val addr = Input(UInt(log2Ceil(cacheConfig.nset * cacheConfig.nbank).W))
|
||||||
|
val data = Output(gen)
|
||||||
|
}
|
||||||
|
|
||||||
|
class WriteOnlyPort[+T <: Data](gen: T)(implicit cacheConfig: CacheConfig) extends Bundle {
|
||||||
|
val addr = Input(UInt(log2Ceil(cacheConfig.nset * cacheConfig.nbank).W))
|
||||||
|
val en = Input(Bool())
|
||||||
|
val data = Input(gen)
|
||||||
|
}
|
||||||
|
|
||||||
|
class WriteOnlyMaskPort[+T <: Data](gen: T)(implicit cacheConfig: CacheConfig) extends Bundle {
|
||||||
|
val addr = Input(UInt(log2Ceil(cacheConfig.nset * cacheConfig.nbank).W))
|
||||||
|
val en = Input(UInt(cacheConfig.bankWidth.W))
|
||||||
|
val data = Input(gen)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ReadWritePort[+T <: Data](gen: T)(implicit cacheConfig: CacheConfig) extends Bundle {
|
||||||
|
val addr = Input(UInt(log2Ceil(cacheConfig.nset * cacheConfig.nbank).W))
|
||||||
|
val en = Input(Bool())
|
||||||
|
val wdata = Input(gen)
|
||||||
|
val rdata = Output(gen)
|
||||||
|
}
|
||||||
|
|
||||||
|
class MaskedReadWritePort[+T <: Data](gen: T)(implicit cacheConfig: CacheConfig) extends Bundle {
|
||||||
|
val addr = Input(UInt(log2Ceil(cacheConfig.nset * cacheConfig.nbank).W))
|
||||||
|
val writeMask = Input(UInt(cacheConfig.bankWidth.W))
|
||||||
|
val wdata = Input(gen)
|
||||||
|
val rdata = Output(gen)
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package cache.memory
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
|
||||||
|
import chisel3.util._
|
||||||
|
import cpu.CpuConfig
|
||||||
|
|
||||||
|
/** simple dual port ram, with a port for reading and a port for writing
|
||||||
|
*
|
||||||
|
* @param depth
|
||||||
|
* how many lines there are in the ram
|
||||||
|
* @param width
|
||||||
|
* how wide in bits each line is
|
||||||
|
* @param byteAddressable
|
||||||
|
* is it byte addressable?
|
||||||
|
* @param cpuCfg
|
||||||
|
* the implicit configuration for simulation and elaboration
|
||||||
|
*/
|
||||||
|
class SimpleDualPortRam(depth: Int, width: Int, byteAddressable: Boolean)(implicit
|
||||||
|
val config: CpuConfig,
|
||||||
|
) extends Module {
|
||||||
|
require(isPow2(depth))
|
||||||
|
require(
|
||||||
|
width % 8 == 0 || !byteAddressable,
|
||||||
|
"if memory is byte addressable, then the adderss width must be a multiple of 8",
|
||||||
|
)
|
||||||
|
val waddridth = log2Ceil(depth)
|
||||||
|
|
||||||
|
val io = IO(new Bundle {
|
||||||
|
val raddr = Input(UInt(waddridth.W))
|
||||||
|
val ren = Input(Bool())
|
||||||
|
val rdata = Output(UInt(width.W))
|
||||||
|
|
||||||
|
val waddr = Input(UInt(waddridth.W))
|
||||||
|
val wen = Input(Bool())
|
||||||
|
val wstrb = Input(UInt((if (byteAddressable) width / 8 else 1).W))
|
||||||
|
val wdata = Input(UInt(width.W))
|
||||||
|
})
|
||||||
|
|
||||||
|
if (config.build) {
|
||||||
|
val memory = Module(
|
||||||
|
new SimpleDualPortRamIP(
|
||||||
|
wdataidth = width,
|
||||||
|
byteWriteWidth = if (byteAddressable) 8 else width,
|
||||||
|
numberOfLines = depth,
|
||||||
|
waddridth = waddridth,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
memory.io.clka := clock
|
||||||
|
memory.io.clkb := clock
|
||||||
|
memory.io.rstb := reset
|
||||||
|
|
||||||
|
memory.io.addra := io.waddr
|
||||||
|
memory.io.ena := io.wen
|
||||||
|
memory.io.dina := io.wdata
|
||||||
|
memory.io.wea := io.wstrb
|
||||||
|
|
||||||
|
memory.io.addrb := io.raddr
|
||||||
|
memory.io.enb := io.ren
|
||||||
|
memory.io.regceb := false.B
|
||||||
|
io.rdata := memory.io.doutb
|
||||||
|
} else {
|
||||||
|
assert(
|
||||||
|
io.wstrb.orR || !io.wen,
|
||||||
|
"when write port enable is high, write vector cannot be all 0",
|
||||||
|
)
|
||||||
|
if (byteAddressable) {
|
||||||
|
val bank = SyncReadMem(depth, Vec(width / 8, UInt(8.W)))
|
||||||
|
when(io.ren) {
|
||||||
|
io.rdata := bank(io.raddr).asTypeOf(io.rdata)
|
||||||
|
}.otherwise {
|
||||||
|
io.rdata := DontCare
|
||||||
|
}
|
||||||
|
when(io.wen) {
|
||||||
|
bank.write(io.waddr, io.wdata.asTypeOf(Vec(width / 8, UInt(8.W))), io.wstrb.asBools)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val bank = SyncReadMem(depth, UInt(width.W))
|
||||||
|
|
||||||
|
when(io.ren) {
|
||||||
|
io.rdata := bank.read(io.raddr)
|
||||||
|
}.otherwise {
|
||||||
|
io.rdata := 0.U(32.W)
|
||||||
|
}
|
||||||
|
|
||||||
|
when(io.wen) {
|
||||||
|
bank.write(io.waddr, io.wdata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package cache.memory
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.util.log2Ceil
|
||||||
|
|
||||||
|
/** simple dual port ram
|
||||||
|
*
|
||||||
|
* @param wdataidth
|
||||||
|
* : width of every data line
|
||||||
|
* @param byteWriteWidth
|
||||||
|
* : how many bits to write per mask
|
||||||
|
* @param numberOfLines
|
||||||
|
* : how many lines of data are in the ram
|
||||||
|
* @param waddridth
|
||||||
|
* : how wide is the request (to cover all lines)
|
||||||
|
* @param memoryPrimitive
|
||||||
|
* : should I use auto, block ram or distributed ram
|
||||||
|
*/
|
||||||
|
class SimpleDualPortRamIP(
|
||||||
|
wdataidth: Int = 32,
|
||||||
|
byteWriteWidth: Int = 8,
|
||||||
|
numberOfLines: Int,
|
||||||
|
waddridth: Int,
|
||||||
|
memoryPrimitive: String = "block",
|
||||||
|
) extends BlackBox(
|
||||||
|
Map(
|
||||||
|
"ADDR_WIDTH_A" -> waddridth,
|
||||||
|
"ADDR_WIDTH_B" -> waddridth,
|
||||||
|
"WRITE_DATA_WIDTH_A" -> wdataidth,
|
||||||
|
"READ_DATA_WIDTH_B" -> wdataidth,
|
||||||
|
"BYTE_WRITE_WIDTH_A" -> byteWriteWidth,
|
||||||
|
"CLOCKING_MODE" -> "common_clock",
|
||||||
|
"READ_LATENCY_B" -> 1,
|
||||||
|
"MEMORY_SIZE" -> numberOfLines * wdataidth,
|
||||||
|
"MEMORY_PRIMITIVE" -> memoryPrimitive,
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
override def desiredName: String = "xpm_memory_sdpram"
|
||||||
|
require(waddridth <= 20, "request width should be 1 to 20")
|
||||||
|
require(
|
||||||
|
wdataidth - (wdataidth / byteWriteWidth) * byteWriteWidth == 0,
|
||||||
|
"data width should be a multiple of byte write width",
|
||||||
|
)
|
||||||
|
require(
|
||||||
|
List("auto", "block", "distributed", "ultra").contains(memoryPrimitive),
|
||||||
|
"memory primitive should be auto, block ram, dist ram or ultra ram",
|
||||||
|
)
|
||||||
|
require(
|
||||||
|
waddridth == log2Ceil(numberOfLines),
|
||||||
|
"request width should be log 2 of number of lines to request all",
|
||||||
|
)
|
||||||
|
val io = IO(new Bundle {
|
||||||
|
// clock and reset
|
||||||
|
val clka = Input(Clock())
|
||||||
|
val clkb = Input(Clock())
|
||||||
|
val rstb = Input(Reset())
|
||||||
|
|
||||||
|
val addra = Input(UInt(waddridth.W))
|
||||||
|
val dina = Input(UInt(wdataidth.W))
|
||||||
|
val ena = Input(Bool())
|
||||||
|
val wea = Input(UInt((wdataidth / byteWriteWidth).W))
|
||||||
|
|
||||||
|
val addrb = Input(UInt(waddridth.W))
|
||||||
|
val enb = Input(Bool())
|
||||||
|
val regceb = Input(Bool())
|
||||||
|
val doutb = Output(UInt(wdataidth.W))
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue