Add jal instruction
This commit is contained in:
12
bench/tests/op/jal.s
Normal file
12
bench/tests/op/jal.s
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# expected: 00000004, 0000008, 0000000C
|
||||||
|
.text
|
||||||
|
_start:
|
||||||
|
jal x31, step1
|
||||||
|
step1:
|
||||||
|
jal x31, step2
|
||||||
|
step2:
|
||||||
|
jal x31, step3
|
||||||
|
step3:
|
||||||
|
nop
|
||||||
|
|
||||||
|
|
||||||
46
build.sc
46
build.sc
@@ -14,28 +14,28 @@ import mill.bsp._
|
|||||||
// See: https://github.com/com-lihaoyi/mill/issues/3840
|
// See: https://github.com/com-lihaoyi/mill/issues/3840
|
||||||
|
|
||||||
object `TPchisel` extends SbtModule { m =>
|
object `TPchisel` extends SbtModule { m =>
|
||||||
override def millSourcePath = super.millSourcePath / os.up
|
override def millSourcePath = super.millSourcePath / os.up
|
||||||
override def scalaVersion = "2.13.16"
|
override def scalaVersion = "2.13.16"
|
||||||
override def scalacOptions = Seq(
|
override def scalacOptions = Seq(
|
||||||
"-language:reflectiveCalls",
|
"-language:reflectiveCalls",
|
||||||
"-deprecation",
|
"-deprecation",
|
||||||
"-feature",
|
"-feature",
|
||||||
"-Xcheckinit",
|
"-Xcheckinit",
|
||||||
"-Ymacro-annotations",
|
"-Ymacro-annotations",
|
||||||
"-unchecked",
|
"-unchecked",
|
||||||
"-Xfatal-warnings",
|
"-Xfatal-warnings",
|
||||||
"-Ywarn-dead-code",
|
"-Ywarn-dead-code",
|
||||||
"-Ywarn-unused"
|
"-Ywarn-unused"
|
||||||
)
|
|
||||||
override def ivyDeps = Agg(
|
|
||||||
ivy"org.chipsalliance::chisel:7.2.0",
|
|
||||||
)
|
|
||||||
override def scalacPluginIvyDeps = Agg(
|
|
||||||
ivy"org.chipsalliance:::chisel-plugin:7.2.0",
|
|
||||||
)
|
|
||||||
object test extends SbtTests with TestModule.ScalaTest {
|
|
||||||
override def ivyDeps = m.ivyDeps() ++ Agg(
|
|
||||||
ivy"org.scalatest::scalatest::3.2.19"
|
|
||||||
)
|
)
|
||||||
}
|
override def ivyDeps = Agg(
|
||||||
|
ivy"org.chipsalliance::chisel:7.2.0"
|
||||||
|
)
|
||||||
|
override def scalacPluginIvyDeps = Agg(
|
||||||
|
ivy"org.chipsalliance:::chisel-plugin:7.2.0"
|
||||||
|
)
|
||||||
|
object test extends SbtTests with TestModule.ScalaTest {
|
||||||
|
override def ivyDeps = m.ivyDeps() ++ Agg(
|
||||||
|
ivy"org.scalatest::scalatest::3.2.19"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,16 +10,21 @@ class CUInterface extends Bundle {
|
|||||||
val alu_opcode = Output(AluOpCode())
|
val alu_opcode = Output(AluOpCode())
|
||||||
val optype = Output(OpType())
|
val optype = Output(OpType())
|
||||||
|
|
||||||
|
// True if the decoded instruction is a jump
|
||||||
|
val is_jump = Output(Bool())
|
||||||
|
|
||||||
// Muxers
|
// Muxers
|
||||||
// The naming convention is as follows : mux_xxx_yyy.
|
// The naming convention is as follows : mux_xxx_yyy.
|
||||||
// If the signal is hot, xxx is selected otherwise yyy is selected
|
// If the signal is hot, xxx is selected otherwise yyy is selected
|
||||||
val mux_alu_imm = Output(Bool())
|
val mux_alu_imm = Output(Bool())
|
||||||
val mux_rega_pc = Output(Bool())
|
val mux_rega_pc = Output(Bool())
|
||||||
val mux_regb_imm = Output(Bool())
|
val mux_regb_imm = Output(Bool())
|
||||||
|
val mux_incrpc4_imm = Output(Bool())
|
||||||
|
val mux_regpc_executepc = Output(Bool())
|
||||||
}
|
}
|
||||||
|
|
||||||
object OpType extends ChiselEnum {
|
object OpType extends ChiselEnum {
|
||||||
val U, I, IR = Value
|
val U, I, IR, J = Value
|
||||||
}
|
}
|
||||||
|
|
||||||
object OpCode extends ChiselEnum {
|
object OpCode extends ChiselEnum {
|
||||||
@@ -46,6 +51,8 @@ object OpCode extends ChiselEnum {
|
|||||||
// add, and, or, xor, sll, srl, sra, slt, stlu
|
// add, and, or, xor, sll, srl, sra, slt, stlu
|
||||||
val OpR = 0b0110011.U;
|
val OpR = 0b0110011.U;
|
||||||
|
|
||||||
|
// Type J
|
||||||
|
val JAL = 0b1101111.U
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -55,9 +62,12 @@ class ControlUnit() extends Module {
|
|||||||
io.reg_file_we := false.B
|
io.reg_file_we := false.B
|
||||||
io.alu_opcode := AluOpCode.Add
|
io.alu_opcode := AluOpCode.Add
|
||||||
io.optype := OpType.U
|
io.optype := OpType.U
|
||||||
|
io.is_jump := false.B;
|
||||||
io.mux_alu_imm := true.B;
|
io.mux_alu_imm := true.B;
|
||||||
io.mux_rega_pc := true.B;
|
io.mux_rega_pc := true.B;
|
||||||
io.mux_regb_imm := true.B;
|
io.mux_regb_imm := true.B;
|
||||||
|
io.mux_incrpc4_imm := true.B;
|
||||||
|
io.mux_regpc_executepc := true.B;
|
||||||
|
|
||||||
// Decode instruction
|
// Decode instruction
|
||||||
val opcode = io.instruction(6, 0);
|
val opcode = io.instruction(6, 0);
|
||||||
@@ -76,21 +86,33 @@ class ControlUnit() extends Module {
|
|||||||
io.alu_opcode := AluOpCode.Add
|
io.alu_opcode := AluOpCode.Add
|
||||||
io.reg_file_we := true.B // Write to regfile
|
io.reg_file_we := true.B // Write to regfile
|
||||||
io.mux_rega_pc := false.B // Send PC to ALU A
|
io.mux_rega_pc := false.B // Send PC to ALU A
|
||||||
io.mux_alu_imm := false.B; // Send immu to ALU B
|
io.mux_regb_imm := false.B; // Send immu to ALU B
|
||||||
io.optype := OpType.U
|
io.optype := OpType.U
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpImm instructions
|
// OpImm instructions
|
||||||
is(OpCode.OpImm) {
|
is(OpCode.OpImm) {
|
||||||
io.reg_file_we := true.B
|
io.reg_file_we := true.B // Write to regfile
|
||||||
opImm(funct3, funct7, io);
|
opImm(funct3, funct7, io);
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpR instructions
|
// OpR instructions
|
||||||
is(OpCode.OpR) {
|
is(OpCode.OpR) {
|
||||||
io.reg_file_we := true.B
|
io.reg_file_we := true.B // Write to regfile
|
||||||
opR(funct3, funct7, io);
|
opR(funct3, funct7, io);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// J instructions
|
||||||
|
is(OpCode.JAL) {
|
||||||
|
io.alu_opcode := AluOpCode.Add
|
||||||
|
io.reg_file_we := true.B // Write to regfile
|
||||||
|
io.mux_rega_pc := false.B // Send PC to ALU A
|
||||||
|
io.mux_regb_imm := false.B; // Send imm to ALU B
|
||||||
|
io.is_jump := true.B
|
||||||
|
io.mux_incrpc4_imm := false.B; // Send the immediate in PC
|
||||||
|
io.mux_regpc_executepc := false.B; // Add the immediate to the previous PC
|
||||||
|
io.optype := OpType.J
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,14 @@ class ImmediateDecoder extends Module {
|
|||||||
val imm_u = Cat(io.instruction(31, 12), 0.U(12.W));
|
val imm_u = Cat(io.instruction(31, 12), 0.U(12.W));
|
||||||
val imm_i = Cat(Fill(20, io.instruction(31)), io.instruction(31, 20));
|
val imm_i = Cat(Fill(20, io.instruction(31)), io.instruction(31, 20));
|
||||||
val imm_ir = io.instruction(24, 20);
|
val imm_ir = io.instruction(24, 20);
|
||||||
|
val imm_j = Cat(
|
||||||
|
Fill(11, io.instruction(31)),
|
||||||
|
io.instruction(31),
|
||||||
|
io.instruction(19, 12),
|
||||||
|
io.instruction(20),
|
||||||
|
io.instruction(30, 21),
|
||||||
|
0.U
|
||||||
|
);
|
||||||
|
|
||||||
switch(io.op_type) {
|
switch(io.op_type) {
|
||||||
is(OpType.U) {
|
is(OpType.U) {
|
||||||
@@ -31,5 +39,8 @@ class ImmediateDecoder extends Module {
|
|||||||
is(OpType.IR) {
|
is(OpType.IR) {
|
||||||
io.immediate := imm_ir
|
io.immediate := imm_ir
|
||||||
}
|
}
|
||||||
|
is(OpType.J) {
|
||||||
|
io.immediate := imm_j
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,32 +12,38 @@ class Rv32i(sim: Boolean = true) extends Module {
|
|||||||
|
|
||||||
val reg_pc = RegInit(0.U(32.W));
|
val reg_pc = RegInit(0.U(32.W));
|
||||||
val reg_file = Module(new RegFile(sim));
|
val reg_file = Module(new RegFile(sim));
|
||||||
val instruction = io.ibus.rdata;
|
|
||||||
|
|
||||||
reg_file.io.rd_data := 0.U;
|
reg_file.io.rd_data := 0.U;
|
||||||
io.x31 := reg_file.io.x31
|
io.x31 := reg_file.io.x31
|
||||||
if (sim) {
|
if (sim) {
|
||||||
io.valid_x31.get := reg_file.io.valid_x31.get && Delay.Delay(
|
io.valid_x31.get := reg_file.io.valid_x31.get
|
||||||
!reset.asBool,
|
|
||||||
1,
|
|
||||||
false.B
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val alu = Module(new Alu());
|
val alu = Module(new Alu());
|
||||||
val immediate_decoder = Module(new ImmediateDecoder());
|
val immediate_decoder = Module(new ImmediateDecoder());
|
||||||
val control_unit = Module(new ControlUnit());
|
val control_unit = Module(new ControlUnit());
|
||||||
|
|
||||||
|
// PC delayed to execute stage for auipc op
|
||||||
|
val execute_pc = Delay.Delay(reg_pc, 1, 0.U);
|
||||||
|
// True if the instruction in the execute stage is a jump
|
||||||
|
val is_jump = Delay.Delay(control_unit.io.is_jump, 1, false.B);
|
||||||
|
val instruction = Mux(is_jump, 0b00000000000000000000000000010011.U, io.ibus.rdata);
|
||||||
|
|
||||||
immediate_decoder.io.instruction := instruction
|
immediate_decoder.io.instruction := instruction
|
||||||
immediate_decoder.io.op_type := control_unit.io.optype
|
immediate_decoder.io.op_type := control_unit.io.optype
|
||||||
alu.io.opcode := control_unit.io.alu_opcode;
|
alu.io.opcode := control_unit.io.alu_opcode;
|
||||||
reg_file.io.we := control_unit.io.reg_file_we
|
reg_file.io.we := control_unit.io.reg_file_we
|
||||||
|
|
||||||
// Increment PC each clock
|
// Increment PC each clock
|
||||||
reg_pc := reg_pc + 4.U;
|
reg_pc := Mux(
|
||||||
|
control_unit.io.mux_regpc_executepc,
|
||||||
// PC delayed to execute stage for auipc op
|
reg_pc,
|
||||||
val execute_pc = Delay.Delay(reg_pc, 1, 0.U);
|
execute_pc
|
||||||
|
) + Mux(
|
||||||
|
control_unit.io.mux_incrpc4_imm,
|
||||||
|
4.U,
|
||||||
|
immediate_decoder.io.immediate
|
||||||
|
);
|
||||||
|
|
||||||
// Fetch instruction
|
// Fetch instruction
|
||||||
io.ibus.en := true.B;
|
io.ibus.en := true.B;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class ZzTop(file: String = "", sim: Boolean = true) extends Module {
|
|||||||
// clock et reset sont les signaux implicites
|
// clock et reset sont les signaux implicites
|
||||||
clkg.io.clk_in1 := clock
|
clkg.io.clk_in1 := clock
|
||||||
clkg.io.reset := reset
|
clkg.io.reset := reset
|
||||||
val rst = (reset.asBool || !clkg.io.locked).asAsyncReset
|
val rst = reset.asBool || !clkg.io.locked
|
||||||
|
|
||||||
// Ces deux IPs doivent tourner à 125 MHz
|
// Ces deux IPs doivent tourner à 125 MHz
|
||||||
val vmem = Module(new IDMem(sim, 17))
|
val vmem = Module(new IDMem(sim, 17))
|
||||||
@@ -34,7 +34,7 @@ class ZzTop(file: String = "", sim: Boolean = true) extends Module {
|
|||||||
vgad.io.clk := clkg.io.clk_out2 // Clock pixel
|
vgad.io.clk := clkg.io.clk_out2 // Clock pixel
|
||||||
|
|
||||||
// Expose core for testing usage
|
// Expose core for testing usage
|
||||||
val core = withClockAndReset(clkg.io.clk_out1, rst) {
|
withClockAndReset(clkg.io.clk_out1, rst) {
|
||||||
val interconnect = Module(new BusInterconnect)
|
val interconnect = Module(new BusInterconnect)
|
||||||
val core = Module(new Rv32i(sim))
|
val core = Module(new Rv32i(sim))
|
||||||
val dmem = Module(new IDMem(sim, 16, file))
|
val dmem = Module(new IDMem(sim, 16, file))
|
||||||
@@ -70,7 +70,5 @@ class ZzTop(file: String = "", sim: Boolean = true) extends Module {
|
|||||||
io.r := vgad.io.r
|
io.r := vgad.io.r
|
||||||
io.g := vgad.io.g
|
io.g := vgad.io.g
|
||||||
io.b := vgad.io.b
|
io.b := vgad.io.b
|
||||||
|
|
||||||
core
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user