Skip to content

Commit

Permalink
improve readability
Browse files Browse the repository at this point in the history
  • Loading branch information
midnighter95 committed Jul 1, 2022
1 parent 48d2b85 commit 79ff5a5
Showing 1 changed file with 34 additions and 62 deletions.
96 changes: 34 additions & 62 deletions src/main/scala/rocket/ICache.scala
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,31 @@ class ICacheErrors(implicit p: Parameters) extends CoreBundle()(p)
* ECC
* Instruction Tightly Integrated Memory(ITIM)
*
* PipeLine:
* Stage 0 : access data and tag SRAM in parallel
* Stage 1 : receive paddr from CPU
* compare tag and paddr when the entry is valid
* if hit : pick up the target instruction
* if miss : start refilling in stage 2
* Stage 2 : respond to CPU or start a refill
*
* Note: Page size = 4KB thus paddr[11:0] = vaddr[11:0]
* considering sets = 64, cachelineBytes =64
* use vaddr[11:6] to access tag_array
* use vaddr[11:2] to access data_array
*
* ITIM:
* It can have an optional dynamic configurable ITIM sharing SRAM with I$ by configuring [[icacheParams.itimAddr]].
* │ tag │ set │offset│
* ├way┘ → indicate way location
* │ line │
* if `way` == b11 (last way), deallocate
* if write to ITIM all I$ will be invalidate
*
* The optional dynamic configurable ITIM sharing SRAM with I$ by configuring [[icacheParams.itimAddr]].
* if PutFullData/PutPartialData to the ITIM address, it will dynamically allocate base address to the address of this accessing from SRAM.
* if access to last way of ITIM, it set will change back to I$.
*
* * If ITIM is configured:
* If ITIM is configured:
* set: if address to access is not to be configured to ITIM yet,
* a memory accessing to ITIM address range will modify `scratchpadMax`,
* from ITIM base to `scratchpadMax` will be used as ITIM.
Expand Down Expand Up @@ -160,7 +174,7 @@ class ICache(val icacheParams: ICacheParams, val staticIdForMetadataUseOnly: Int
/** @todo why [[wordBytes]] is defined by [[icacheParams.fetchBytes]], rather than 32 directly? */
private val wordBytes = icacheParams.fetchBytes

/** @todo Instruction Tightly Integrated Memory node. */
/** Instruction Tightly Integrated Memory node. */
val slaveNode =
TLManagerNode(icacheParams.itimAddr.toSeq.map { itimAddr => TLSlavePortParameters.v1(
Seq(TLSlaveParameters.v1(
Expand Down Expand Up @@ -250,24 +264,6 @@ class ICacheBundle(val outer: ICache) extends CoreBundle()(outer.p) {
val keep_clock_enabled = Bool(OUTPUT)
}

/** Rocket virtually-indexed physically-tagged (VIPT) L1 Instruction Cache module,
*
* It hides TLB access latency(Stage 0 -> Stage 1)
*
*
* `tag_array` read starts at Stage 0 with vaddr[11:6]
* write with `index(vaddr, paddr)`
* `data_array` read starts at Stage 0 with vaddr[11:2]
* write with `index(vaddr, paddr)` truncating TileLink beat count
*
* ITIM:
* │ tag │ set │offset│
* │way│
* if `way` == b11 (last way), deallocate
* if write to ITIM all I$ will be invalidate
*/
class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
with HasL1ICacheParameters {
override val cacheParams = outer.icacheParams // Use the local parameters
Expand Down Expand Up @@ -298,8 +294,7 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
val io_mmio_address_prefix = outer.mmioAddressPrefixSinkNodeOpt.map(_.bundle)
/** register indicates wheather ITIM is enabled. */
val scratchpadOn = RegInit(false.B)
/** a cut point to SRAM, indicates which SRAM will be used as SRAM or Cache.
* todo: (yyq) if enable ITIM, the ITIM size is fixed to (way = 11)?*/
/** a cut point to SRAM, indicates which SRAM will be used as SRAM or Cache. */
val scratchpadMax = tl_in.map(tl => Reg(UInt(width = log2Ceil(nSets * (nWays - 1)))))
/** line is a minimal granularity accessing to SRAM, check if a line is in the scratchpad or not.
* Accessing from [[tl_in]]: convert address to line with `untagBits+log2Ceil(nWays)-1, blockOffBits`(slices of address)
Expand Down Expand Up @@ -388,14 +383,11 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
*/
val s1_hit = s1_tag_hit.reduce(_||_) || Mux(s1_slaveValid, true.B, addrMaybeInScratchpad(io.s1_paddr))
dontTouch(s1_hit)
/** stage 2 valid signal. */
val s2_valid = RegNext(s1_valid && !io.s1_kill, Bool(false))
/** CPU I$ Hit in stage 2. */
val s2_hit = RegNext(s1_hit)

/** status register to indicate flush is cache. */
val invalidated = Reg(Bool())
/** status register to indicate there is a outstanding refill. */
val refill_valid = RegInit(false.B)
/** register to indicate [[tl_out]] is performing a hint.
* prefetch only happens after refilling
Expand Down Expand Up @@ -446,7 +438,7 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
v
}

/** init tag SRAM, indexed with virtual memory(vaddr[11:6]),
/** init tag SRAM, indexed with virtual memory,
* content with `refillError ## tag[19:0]` after ECC
* */
val tag_array = DescribedSRAM(
Expand All @@ -455,12 +447,7 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
size = nSets,
data = Vec(nWays, UInt(width = tECC.width(1 + tagBits)))
)

/** read tag at stage 0 with virtual memory.
* `!refill_done && s0_valid` -> write will block read
*/
val tag_rdata = tag_array.read(s0_vaddr(untagBits-1,blockOffBits), !refill_done && s0_valid)

/** register indicates the ongoing GetAckData transaction is corrupted. */
val accruedRefillError = Reg(Bool())
/** wire indicates the ongoing GetAckData transaction is corrupted. */
Expand All @@ -480,8 +467,6 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)

/** true indicate this cacheline is valid,
* indexed by (wayIndex ## setIndex)
*
* after reset, all valid is false.
* after refill_done and not FENCE.I, (repl_way ## refill_idx) set to true.
*/
val vb_array = Reg(init=Bits(0, nSets*nWays))
Expand Down Expand Up @@ -570,6 +555,16 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
* └─set──┴─offset─┘
* └────row───┘
*
* Data SRAM is indexed with virtual memory(vaddr[11:2]),
* vaddr[11:3]->row,
* vaddr[2]->bank=i,
* Cache line size = refillCycels(8) * bank(2) * datasize(4 bytes) = 64 bytes
* data width = 32
* read:
* read happens in stage 0
* write:
* It takes 8 beats to refill 16 instruction in each refilling cycle.
* Data_array receives data[63:0](2 instructions) at once,they will be allocated in deferent bank according to vaddr[2]
*/
val data_arrays = Seq.tabulate(tl_out.d.bits.data.getWidth / wordBits) {
i =>
Expand All @@ -580,34 +575,19 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
data = Vec(nWays, UInt(width = dECC.width(wordBits)))
)
}
/** init data SRAM, indexed with virtual memory(vaddr[11:2]),
* vaddr[11:3]->row,
* vaddr[2]->bank=i,
* Cache line size = refillCycels(8) * bank(2) * datasize(4 bytes) = 64 bytes
* 4-way,
* data width = 32
* read:
* read happens in stage 0
* write:
* It takes 8 beats to refill 16 instruction in each refilling cycle.
* Data_array receives data[63:0](2 instructions) at once,they will be allocated in deferent bank according to vaddr[2]
* */

for ((data_array , i) <- data_arrays zipWithIndex) {
/** bank match (vaddr[2]) */
def wordMatch(addr: UInt) = addr.extract(log2Ceil(tl_out.d.bits.data.getWidth/8)-1, log2Ceil(wordBits/8)) === i
/** calculate row (vaddr[11:3]).
* row means the index for data_array
* vaddr[11:6]=row[8:3]
* vaddr[5:3]=row[2:0]
*/
def row(addr: UInt) = addr(untagBits-1, blockOffBits-log2Ceil(refillCycles))
/** CPU or ITIM read match this bank. */
/** read_enable signal*/
val s0_ren = (s0_valid && wordMatch(s0_vaddr)) || (s0_slaveValid && wordMatch(s0_slaveAddr))
/** refill from [[tl_out]] or ITIM write. */
/** write_enable signal
* refill from [[tl_out]] or ITIM write. */
val wen = (refill_one_beat && !invalidated) || (s3_slaveValid && wordMatch(s1s3_slaveAddr))
/** index to access [[data_array]]. */
val mem_idx =
// I$ refill. refill_idx[2:0]is the beats
// I$ refill. refill_idx[2:0] is the beats
Mux(refill_one_beat, (refill_idx << log2Ceil(refillCycles)) | refill_cnt,
// ITIM write.
Mux(s3_slaveValid, row(s1s3_slaveAddr),
Expand Down Expand Up @@ -639,28 +619,21 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)

/** clock gate signal for [[s2_tag_hit]], [[s2_dout]], [[s2_tag_disparity]], [[s2_tl_error]], [[s2_scratchpad_hit]]. */
val s1_clk_en = s1_valid || s1_slaveValid
/** stage 2 of [[s1_tag_hit]]. */
val s2_tag_hit = RegEnable(Mux(s1_dont_read, 0.U.asTypeOf(s1_tag_hit), s1_tag_hit), s1_clk_en)
/** way index to access [[data_arrays]]. */
val s2_hit_way = OHToUInt(s2_tag_hit)
/** ITIM index to access [[data_arrays]].
* replace tag with way, word set to 0.
*/
val s2_scratchpad_word_addr = Cat(s2_hit_way, Mux(s2_slaveValid, s1s3_slaveAddr, io.s2_vaddr)(untagBits-1, log2Ceil(wordBits/8)), UInt(0, log2Ceil(wordBits/8)))
/** stage 2 of [[s1_dout]]. */
val s2_dout = RegEnable(s1_dout, s1_clk_en)
/** way selected from [[s2_dout]]. */
val s2_way_mux = Mux1H(s2_tag_hit, s2_dout)

/** stage 2 of [[s1_tag_disparity]]. */
val s2_tag_disparity = RegEnable(s1_tag_disparity, s1_clk_en).asUInt.orR
/** stage 2 of [[s1_tl_error]]. */
val s2_tl_error = RegEnable(s1_tl_error.asUInt.orR, s1_clk_en)
/** ECC decode result for [[data_arrays]]. */
val s2_data_decoded = dECC.decode(s2_way_mux)
/** ECC error happened, correctable or uncorrectable, ask CPU to replay. */
val s2_disparity = s2_tag_disparity || s2_data_decoded.error

/** access hit in ITIM, if [[s1_slaveValid]], this access is from [[tl_in]], else from CPU [[io]]. */
val s1_scratchpad_hit = Mux(s1_slaveValid, lineInScratchpad(scratchpadLine(s1s3_slaveAddr)), addrInScratchpad(io.s1_paddr))
/** stage 2 of [[s1_scratchpad_hit]]. */
Expand Down Expand Up @@ -864,7 +837,6 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer)
x.readalloc := io.s2_cacheable
x.writealloc := io.s2_cacheable
}
// Tie off unused channels
tl_out.b.ready := Bool(true)
tl_out.c.valid := Bool(false)
tl_out.e.valid := Bool(false)
Expand Down

0 comments on commit 79ff5a5

Please sign in to comment.