| 
									
										
										
										
											2021-06-04 09:06:35 +08:00
										 |  |  | /***************************************************************************************
 | 
					
						
							|  |  |  | * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences | 
					
						
							| 
									
										
										
										
											2021-07-24 23:26:38 +08:00
										 |  |  | * Copyright (c) 2020-2021 Peng Cheng Laboratory | 
					
						
							| 
									
										
										
										
											2021-06-04 09:06:35 +08:00
										 |  |  | * | 
					
						
							|  |  |  | * XiangShan is licensed under Mulan PSL v2. | 
					
						
							|  |  |  | * You can use this software according to the terms and conditions of the Mulan PSL v2. | 
					
						
							|  |  |  | * You may obtain a copy of Mulan PSL v2 at: | 
					
						
							|  |  |  | *          http://license.coscl.org.cn/MulanPSL2
 | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, | 
					
						
							|  |  |  | * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, | 
					
						
							|  |  |  | * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * See the Mulan PSL v2 for more details. | 
					
						
							|  |  |  | ***************************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-20 11:11:51 +08:00
										 |  |  | package utils | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-19 21:19:20 +08:00
										 |  |  | import chipsalliance.rocketchip.config.Parameters | 
					
						
							| 
									
										
										
										
											2020-10-20 11:11:51 +08:00
										 |  |  | import chisel3._ | 
					
						
							|  |  |  | import chisel3.util._ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 15:38:15 +08:00
										 |  |  | class CircularQueuePtr[T <: CircularQueuePtr[T]](val entries: Int) extends Bundle { | 
					
						
							| 
									
										
										
										
											2020-10-20 11:11:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-19 21:19:20 +08:00
										 |  |  |   def this(f: Parameters => Int)(implicit p: Parameters) = this(f(p)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   val PTR_WIDTH = log2Up(entries) | 
					
						
							| 
									
										
										
										
											2020-10-20 11:11:51 +08:00
										 |  |  |   val flag = Bool() | 
					
						
							|  |  |  |   val value = UInt(PTR_WIDTH.W) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-21 18:52:10 +08:00
										 |  |  |   override def toPrintable: Printable = { | 
					
						
							|  |  |  |     p"$flag:$value" | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-10-20 11:11:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 15:38:15 +08:00
										 |  |  |   final def +(v: UInt): T = { | 
					
						
							|  |  |  |     val entries = this.entries | 
					
						
							|  |  |  |     val new_ptr = Wire(this.asInstanceOf[T].cloneType) | 
					
						
							|  |  |  |     if(isPow2(entries)){ | 
					
						
							|  |  |  |       new_ptr := (Cat(this.flag, this.value) + v).asTypeOf(new_ptr) | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       val new_value = this.value +& v | 
					
						
							|  |  |  |       val diff = Cat(0.U(1.W), new_value).asSInt() - Cat(0.U(1.W), entries.U.asTypeOf(new_value)).asSInt() | 
					
						
							|  |  |  |       val reverse_flag = diff >= 0.S | 
					
						
							|  |  |  |       new_ptr.flag := Mux(reverse_flag, !this.flag, this.flag) | 
					
						
							|  |  |  |       new_ptr.value := Mux(reverse_flag, | 
					
						
							|  |  |  |         diff.asUInt(), | 
					
						
							|  |  |  |         new_value | 
					
						
							|  |  |  |       ) | 
					
						
							| 
									
										
										
										
											2020-10-20 11:11:51 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-05 15:38:15 +08:00
										 |  |  |     new_ptr | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-10-20 11:11:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 15:38:15 +08:00
										 |  |  |   final def -(v: UInt): T = { | 
					
						
							|  |  |  |     val flipped_new_ptr = this + (this.entries.U - v) | 
					
						
							|  |  |  |     val new_ptr = Wire(this.asInstanceOf[T].cloneType) | 
					
						
							|  |  |  |     new_ptr.flag := !flipped_new_ptr.flag | 
					
						
							|  |  |  |     new_ptr.value := flipped_new_ptr.value | 
					
						
							|  |  |  |     new_ptr | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-10-21 15:55:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 15:38:15 +08:00
										 |  |  |   final def === (that_ptr: T): Bool = this.asUInt()===that_ptr.asUInt() | 
					
						
							| 
									
										
										
										
											2020-12-17 15:55:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 15:38:15 +08:00
										 |  |  |   final def =/= (that_ptr: T): Bool = this.asUInt()=/=that_ptr.asUInt() | 
					
						
							| 
									
										
										
										
											2022-07-06 16:28:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def toOH: UInt = UIntToOH(value, entries) | 
					
						
							| 
									
										
										
										
											2021-04-05 15:38:15 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-10-20 11:11:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 15:38:15 +08:00
										 |  |  | trait HasCircularQueuePtrHelper { | 
					
						
							| 
									
										
										
										
											2020-10-20 11:11:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 15:38:15 +08:00
										 |  |  |   def isEmpty[T <: CircularQueuePtr[T]](enq_ptr: T, deq_ptr: T): Bool = { | 
					
						
							| 
									
										
										
										
											2020-10-20 11:11:51 +08:00
										 |  |  |     enq_ptr === deq_ptr | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 15:38:15 +08:00
										 |  |  |   def isFull[T <: CircularQueuePtr[T]](enq_ptr: T, deq_ptr: T): Bool = { | 
					
						
							| 
									
										
										
										
											2020-10-20 11:11:51 +08:00
										 |  |  |     (enq_ptr.flag =/= deq_ptr.flag) && (enq_ptr.value === deq_ptr.value) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 15:38:15 +08:00
										 |  |  |   def distanceBetween[T <: CircularQueuePtr[T]](enq_ptr: T, deq_ptr: T): UInt = { | 
					
						
							| 
									
										
										
										
											2020-10-21 15:55:31 +08:00
										 |  |  |     assert(enq_ptr.entries == deq_ptr.entries) | 
					
						
							|  |  |  |     Mux(enq_ptr.flag === deq_ptr.flag, | 
					
						
							|  |  |  |       enq_ptr.value - deq_ptr.value, | 
					
						
							|  |  |  |       enq_ptr.entries.U + enq_ptr.value - deq_ptr.value) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 15:38:15 +08:00
										 |  |  |   def isAfter[T <: CircularQueuePtr[T]](left: T, right: T): Bool = { | 
					
						
							| 
									
										
										
										
											2021-12-27 15:21:08 +08:00
										 |  |  |     val differentFlag = left.flag ^ right.flag | 
					
						
							|  |  |  |     val compare = left.value > right.value | 
					
						
							|  |  |  |     differentFlag ^ compare | 
					
						
							| 
									
										
										
										
											2020-10-21 15:55:31 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2021-02-21 16:23:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 15:38:15 +08:00
										 |  |  |   def isBefore[T <: CircularQueuePtr[T]](left: T, right: T): Bool = { | 
					
						
							| 
									
										
										
										
											2021-12-27 15:21:08 +08:00
										 |  |  |     val differentFlag = left.flag ^ right.flag | 
					
						
							|  |  |  |     val compare = left.value < right.value | 
					
						
							|  |  |  |     differentFlag ^ compare | 
					
						
							| 
									
										
										
										
											2021-02-21 16:23:14 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-10-20 11:11:51 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-07-13 21:27:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Should only be used when left and right are continuous pointers.
 | 
					
						
							|  |  |  | class QPtrMatchMatrix[T <: CircularQueuePtr[T]](left: Seq[T], right: Seq[T]) { | 
					
						
							|  |  |  |   val matrix = left.map(l => right.map(_.value === l.value)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def apply(leftIndex: Int, rightIndex: Int): Bool = { | 
					
						
							|  |  |  |     require(leftIndex < left.length && rightIndex < right.length) | 
					
						
							|  |  |  |     if (leftIndex == 0 || rightIndex == 0) { | 
					
						
							|  |  |  |       matrix(leftIndex)(rightIndex) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       apply(leftIndex - 1, rightIndex - 1) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   def apply(leftIndex: Int): Seq[Bool] = right.indices.map(i => apply(leftIndex, i)) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-07-14 08:38:00 +08:00
										 |  |  | 
 |