-
Notifications
You must be signed in to change notification settings - Fork 1
How to add new instruction to the decoder
UlisesLuzius edited this page Feb 13, 2019
·
1 revision
In order to add instructions, we will follow the process of adding ADD/SUB immediate instructions. Steps of this process are present in the commit https://github.com/UlisesLuzius/protoflex-chisel/commit/67339e7e45d8bc81d016aa6001e7abf0d4a05107
- Get instructions bitcodes from common/bitcodes.scala and add Bitpats to common/instructions.scala
object INSTRUCTIONS
{
def INST_X = BitPat.dontCare(32)
...
// Add/subtract (immediate)
// I_ASImm
// 31 | 30 | 29 | 28 27 26 25 24 | 23 22 | 21 20 19 18 17 16 15 14 13 12 11 10 | 09 08 07 06 05 | 04 03 02 01 00 | Instruction Page | Variant
// 1 | 0 | 0 | 1 0 0 0 1 | - | imm12 | Rn | Rd | ADD | 64-bit
// 1 | 0 | 1 | 1 0 0 0 1 | - | imm12 | Rn | Rd | ADDS | 64-bit
// 1 | 1 | 0 | 1 0 0 0 1 | - | imm12 | Rn | Rd | SUB | 64-bit
// 1 | 1 | 1 | 1 0 0 0 1 | - | imm12 | Rn | Rd | SUBS | 64-bit
+ def ADD_I = BitPat("b10010001????????????????????????")
+ def ADDS_I = BitPat("b10110001????????????????????????")
+ def SUB_I = BitPat("b11010001????????????????????????")
+ def SUBS_I = BitPat("b11110001????????????????????????")
...
}
- Add instruction constant to DEC_LITS in common/decode_consts.scala
object DEC_LITS
{
// Valault Defues
val IMM_W = 26
...
// Types
val TYPE_W = 3 // Log2ceil(nb_insts)
val I_X = 0
val I_LogSR = 1
val I_BImm = 2
val I_BCImm = 3
+ val I_ASImm = 4
...
}
- Add instruction to DEC_LITS.decode_table
object DEC_LITS
{
// Valault Defues
val IMM_W = 26
...
def decode_table(inst_type : Int ): List[BigInt] =
inst_type match {
// RD INSTRUCTION
// EN VALID
// | RS1 COND |
// | EN EN |
// | | RS2 SHIFT| |
// | | EN EN | |
// | | | IMM | | |
// | | | EN | | |
// | | | | | | |
// | | | | | | |
// | | | | | | |
case I_X => List(N, N, N, N, N, N, N)
case I_LogSR => List(Y, Y, Y, N, Y, N, Y)
case I_BImm => List(N, N, N, Y, N, N, Y)
case I_BCImm => List(N, N, N, Y, N, Y, Y)
+ case I_ASImm => List(Y, Y, N, Y, N, Y, Y)
}
}
In case a new control field is created, add it to the list (E.G field) :
object DEC_LITS
{
...
def decode_table(inst_type : Int): List[BigInt] =
inst match {
// RD INSTRUCTION
// EN VALID
// | RS1 COND |
// | EN EN |
// | | RS2 SHIFT| |
// | | EN EN | |
// | | | IMM | | |
// | | | EN | | E.G |
// | | | | | | FIELD
// | | | | | | | |
// | | | | | | | |
case I_X => List(N, N, N, N, N, N, N, N)
...
}}
- Add instruction to BitPattern decoder in common/decode_consts.DECODE_MATCHING_TABLES
object DECODE_MATCHING_TABLES
{
...
def decode_table: Array[(BitPat, List[UInt])] =
Array(
// Logical (shifted register)
AND -> List(I_LogSR, OP_AND, Y, Y, Y, N, Y, N, Y),
BIC -> List(I_LogSR, OP_BIC, Y, Y, Y, N, Y, N, Y),
ORR -> List(I_LogSR, OP_ORR, Y, Y, Y, N, Y, N, Y),
ORN -> List(I_LogSR, OP_ORN, Y, Y, Y, N, Y, N, Y),
EOR -> List(I_LogSR, OP_EOR, Y, Y, Y, N, Y, N, Y),
EON -> List(I_LogSR, OP_EON, Y, Y, Y, N, Y, N, Y),
ANDS -> List(I_LogSR, OP_AND, Y, Y, Y, N, Y, Y, Y),
BICS -> List(I_LogSR, OP_BIC, Y, Y, Y, N, Y, Y, Y),
// Unconditional branch (immediate)
B -> List(I_BImm , OP_B, N, N, N, Y, N, N, Y),
BL -> List(I_BImm , OP_B, N, N, N, Y, N, N, Y),
// Compare & branch (immediate)
BCond -> List(I_BCImm, OP_BCOND, N, N, N, Y, N, Y, Y),
// Add/subtract (immediate)
+ ADD_I -> List(I_ASImm, OP_ADD, Y, Y, N, Y, N, Y, Y),
+ ADDS_I -> List(I_ASImm, OP_ADD, Y, Y, N, Y, N, Y, Y),
+ SUB_I -> List(I_ASImm, OP_SUB, Y, Y, N, Y, N, Y, Y),
+ SUBS_I -> List(I_ASImm, OP_SUB, Y, Y, N, Y, N, Y, Y),
)
...
In case a control field was added, don't forget same as in last example and add the field to decode_table and decode_default lists.
- Add op related constants
object DECODE_CONTROL_SIGNALS
{
...
// ALU Operation Signals
val OP_AND = DEC_LITS.OP_AND.U(OP_W)
val OP_BIC = DEC_LITS.OP_BIC.U(OP_W)
val OP_ORR = DEC_LITS.OP_ORR.U(OP_W)
val OP_ORN = DEC_LITS.OP_ORN.U(OP_W)
val OP_EOR = DEC_LITS.OP_EOR.U(OP_W)
val OP_EON = DEC_LITS.OP_EON.U(OP_W)
+ val OP_ADD = DEC_LITS.OP_ADD.U(OP_W)
+ val OP_SUB = DEC_LITS.OP_SUB.U(OP_W)
...
}
- Update decoded instruction signals such as directing bit ranges to corresponding structures; in this case no extra field was added but lets add a egField for the sake of the tutorial.
// 31 | 30 | 29 | 28 27 26 25 24 | 23 22 | 21 20 19 18 17 16 15 14 13 12 11 10 | 09 08 07 06 05 | 04 03 02 01 00 | Instruction Page | Variant
// 1 | 0 | 0 | 1 0 0 0 1 | - | imm12 | Rn | Rd | ADD | 64-bit
From the bitpatterns of the instruction, we can see that we have 3 fields : rd (4,0); rs1 (9,5); imm(21,10) and flag_set (ADD VS ADDS) (nzcv_en is extracted by the decode table).
class DInst exetends Bundle
{
// Data
val rd = REG_T
val rs1 = REG_T
...
// New Inst field
+ val egField = EG_T
+ val egField_en = Bool()
...
def decode(inst : UInt, tag : UInt) = {
val decoder = ListLookup(inst, decode_default, decode_table)
// Data
val itype = decoder.head
rd := MuxLookup(itype, REG_X, Array( I_LogSR -> inst( 4, 0),
+ I_ASImm -> inst( 4, 0)))
rs1 := MuxLookup(itype, REG_X, Array( I_LogSR -> inst( 9, 5),
+ I_ASImm -> inst( 9, 5)))
rs2 := MuxLookup(itype, REG_X, Array( I_LogSR -> inst(20,16) ))
imm := MuxLookup(itype, IMM_X, Array( I_LogSR -> inst(15,10),
I_BImm -> inst(25, 0),
I_BCImm -> inst(23, 5),
+ I_ASImm -> inst(21,10)))
shift := MuxLookup(itype, SHIFT_X, Array( I_LogSR -> inst(23,22) ))
+ egField := MuxLookup(itype, egField_X, Array( I_egInst -> inst(n1, n2) )
// Control
val cdecoder = decoder.tail
// Extrafield ---v
+ val csignals = Seq(op, rd_en, rs1_en, rs2_en, imm_en, shift_en, cond_en, egField_en, inst_en)
csignals zip cdecoder map { case (s, d) => s:= d }
this.tag := tag
this.itype := itype
this
}
At this stage we got our decoded instruction ready and it's time to write verification.