KunmingLake PrunedAddr Documentation
Background Introduction
In the RISC-V manual, B-Type and J-Type instructions are described as follows:
The only difference between the S and B formats is that the 12-bit immediate field is used to encode branch offsets in multiples of 2 in the B format. Instead of shifting all bits in the instruction-encoded immediate left by one in hardware as is conventionally done, the middle bits (imm[10:1]) and sign bit stay in fixed positions, while the lowest bit in S format (inst[7]) encodes a high-order bit in B format.
Similarly, the only difference between the U and J formats is that the 20-bit immediate is shifted left by 12 bits to form U immediates and by 1 bit to form J immediates. The location of instruction bits in the U and J format immediates is chosen to maximize overlap with the other formats and with each other.
This means that for branch instructions other than jalr
, the least significant bit of the jump target must be 0. For the jalr
instruction, the manual describes the calculation of the jump target as follows:
The target address is obtained by adding the sign-extended 12-bit I-immediate to the register rs1, then setting the least-significant bit of the result to zero.
This means the least significant bit of the jalr
jump target is also 0.
Combining these two parts, we can see that the least significant bit of all PCs must be 0. Therefore, all parts involving PC in the front-end do not need to store the least significant bit, which can save area.
In fact, when the C extension is disabled, the lowest 2 bits of the PC must be 0, otherwise an instruction misalignment exception will be reported.
Usage Guide
The design goal of PrunedAddr
is to be as similar to UInt
as possible in usage. However, due to Chisel's limitations, this goal cannot be fully realized. In areas where it differs from UInt
, it can be compared to Reg
or Wire
. The specific usage guide is as follows:
- Use
PrunedAddrInit
for conversion fromUInt
toPrunedAddr
, for example,val addr1 = PrunedAddrInit(addr2)
, where the type ofaddr2
isUInt
. - Use
toUInt
for conversion fromPrunedAddr
toUInt
, for example,addr.toUInt
. - The method
def +(offset: UInt)
should only be used whenoffset
is an immediate value. For other cases,def +(offset: PrunedAddr)
should be used. Ifoffset
is aUInt
and not an immediate,offset
should be converted toPrunedAddr
.
Remaining Issues
- Currently, the use of
PrunedAddr
is limited to within the front-end; the interface from the front-end to the back-end still usesUInt
. Ideally, the back-end should also entirely usePrunedAddr
. In this case, thetoUInt
method should only be used when outputting debugging information. - The method
def >>(offset: Int)
should be deleted to reduce confusion. The corresponding functionality can be achieved by directly selecting the corresponding bits. - For the number of pruned bits, the current implementation uses the parameter
instOffset
. Theoretically, this parameter should change with the switching of the C extension. However, XiangShan currently does not actually support disabling the C extension, and the correctness of disabling the C extension has not been verified.