增加puamips的cache文件
This commit is contained in:
parent
41da1f4c3e
commit
3134b79c54
|
@ -26,3 +26,29 @@ case class CpuConfig(
|
|||
case class BranchPredictorConfig(
|
||||
val bhtDepth: Int = 5,
|
||||
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