Compare commits
3
Commits
master
..
ccd1b917d0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ccd1b917d0 | ||
|
|
9f6f4c9ada | ||
|
|
036a57d907 |
+13
-2
@@ -4,7 +4,8 @@
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// ALU:纯组合运算单元。
|
// ALU:纯组合运算单元。
|
||||||
//
|
//
|
||||||
// result 为主结果;result2 为第二结果,用于 MUL 的高 32 位与 DIVU 的余数。
|
// result 为主结果;result2 为第二结果(乘法的无符号高 32 位 / DIVU 的余数),
|
||||||
|
// 由译码器用 wb_sel=3 选取,用于无符号高位乘法 mulhu 与课程约定的 remu。
|
||||||
// 除法做了除零保护:b==0 时商为 32'hffff_ffff、余数为被除数。
|
// 除法做了除零保护:b==0 时商为 32'hffff_ffff、余数为被除数。
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
module cpu21_riscv_alu (
|
module cpu21_riscv_alu (
|
||||||
@@ -27,10 +28,17 @@ module cpu21_riscv_alu (
|
|||||||
localparam ALU_NOR = 4'd10;
|
localparam ALU_NOR = 4'd10;
|
||||||
localparam ALU_SLT = 4'd11;
|
localparam ALU_SLT = 4'd11;
|
||||||
localparam ALU_SLTU = 4'd12;
|
localparam ALU_SLTU = 4'd12;
|
||||||
reg [63:0] mult_result;
|
localparam ALU_MULH = 4'd13;
|
||||||
|
localparam ALU_MULHSU = 4'd14;
|
||||||
|
localparam ALU_PASSB = 4'd15; // 直接输出 B 端(供 LUI 使用)
|
||||||
|
reg [63:0] mult_result; // 无符号 32x32 乘积
|
||||||
|
reg signed [63:0] mult_ss; // 有符号 x 有符号
|
||||||
|
reg signed [63:0] mult_su; // 有符号 x 无符号
|
||||||
|
|
||||||
always @* begin
|
always @* begin
|
||||||
mult_result = a * b;
|
mult_result = a * b;
|
||||||
|
mult_ss = $signed(a) * $signed(b);
|
||||||
|
mult_su = $signed(a) * $signed({32'b0, b});
|
||||||
result2 = 32'b0;
|
result2 = 32'b0;
|
||||||
case (op)
|
case (op)
|
||||||
ALU_SLL: result = a << b[4:0];
|
ALU_SLL: result = a << b[4:0];
|
||||||
@@ -50,8 +58,11 @@ module cpu21_riscv_alu (
|
|||||||
ALU_OR: result = a | b;
|
ALU_OR: result = a | b;
|
||||||
ALU_XOR: result = a ^ b;
|
ALU_XOR: result = a ^ b;
|
||||||
ALU_NOR: result = ~(a | b);
|
ALU_NOR: result = ~(a | b);
|
||||||
|
ALU_MULH: result = mult_ss[63:32];
|
||||||
|
ALU_MULHSU: result = mult_su[63:32];
|
||||||
ALU_SLT: result = ($signed(a) < $signed(b)) ? 32'd1 : 32'd0;
|
ALU_SLT: result = ($signed(a) < $signed(b)) ? 32'd1 : 32'd0;
|
||||||
ALU_SLTU: result = (a < b) ? 32'd1 : 32'd0;
|
ALU_SLTU: result = (a < b) ? 32'd1 : 32'd0;
|
||||||
|
ALU_PASSB: result = b;
|
||||||
default: result = 32'b0;
|
default: result = 32'b0;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ module cpu21_riscv_branch_unit (
|
|||||||
input wire beq_i,
|
input wire beq_i,
|
||||||
input wire bne_i,
|
input wire bne_i,
|
||||||
input wire blt_i,
|
input wire blt_i,
|
||||||
|
input wire bge_i,
|
||||||
input wire bltu_i,
|
input wire bltu_i,
|
||||||
|
input wire bgeu_i,
|
||||||
input wire jal_i,
|
input wire jal_i,
|
||||||
input wire jalr_i,
|
input wire jalr_i,
|
||||||
// IF 级携带过来的预测信息
|
// IF 级携带过来的预测信息
|
||||||
@@ -31,15 +33,20 @@ module cpu21_riscv_branch_unit (
|
|||||||
output wire redirect_valid_o,
|
output wire redirect_valid_o,
|
||||||
output wire [31:0] redirect_pc_o
|
output wire [31:0] redirect_pc_o
|
||||||
);
|
);
|
||||||
// 条件分支裁决:beq 相等、bne 不等、blt 有符号小于、bltu 无符号小于。
|
// 比较结果预先算好,避免表达式过长被自动换行拆散。
|
||||||
|
wire lt_signed = $signed(src1_i) < $signed(src2_i);
|
||||||
|
wire ge_signed = $signed(src1_i) >= $signed(src2_i);
|
||||||
|
wire lt_unsigned = src1_i < src2_i;
|
||||||
|
wire ge_unsigned = src1_i >= src2_i;
|
||||||
|
|
||||||
|
// 条件分支裁决:beq 相等、bne 不等、blt/bge 有符号比较、bltu/bgeu 无符号比较。
|
||||||
assign branch_taken_o = branch_i &&
|
assign branch_taken_o = branch_i &&
|
||||||
((beq_i && (src1_i == src2_i)) ||
|
((beq_i && (src1_i == src2_i)) ||
|
||||||
(bne_i && (src1_i != src2_i)) ||
|
(bne_i && (src1_i != src2_i)) ||
|
||||||
(blt_i && ($signed(
|
(blt_i && lt_signed) ||
|
||||||
src1_i
|
(bge_i && ge_signed) ||
|
||||||
) < $signed(
|
(bltu_i && lt_unsigned) ||
|
||||||
src2_i
|
(bgeu_i && ge_unsigned));
|
||||||
))) || (bltu_i && (src1_i < src2_i)));
|
|
||||||
|
|
||||||
// 跳转目标:jalr 为 (rs1+imm) 且最低位清零;jal 为 PC+imm。
|
// 跳转目标:jalr 为 (rs1+imm) 且最低位清零;jal 为 PC+imm。
|
||||||
assign target_o = jalr_i ? ((src1_i + imm_i) & 32'hffff_fffe) : (pc_i + imm_i);
|
assign target_o = jalr_i ? ((src1_i + imm_i) & 32'hffff_fffe) : (pc_i + imm_i);
|
||||||
|
|||||||
+44
-11
@@ -29,7 +29,9 @@ module cpu21_riscv_decoder (
|
|||||||
output reg beq_o,
|
output reg beq_o,
|
||||||
output reg bne_o,
|
output reg bne_o,
|
||||||
output reg blt_o,
|
output reg blt_o,
|
||||||
|
output reg bge_o,
|
||||||
output reg bltu_o,
|
output reg bltu_o,
|
||||||
|
output reg bgeu_o,
|
||||||
output reg jal_o,
|
output reg jal_o,
|
||||||
output reg jalr_o,
|
output reg jalr_o,
|
||||||
output reg ecall_o,
|
output reg ecall_o,
|
||||||
@@ -47,6 +49,8 @@ module cpu21_riscv_decoder (
|
|||||||
localparam OP_BRANCH = 5'h18;
|
localparam OP_BRANCH = 5'h18;
|
||||||
localparam OP_JAL = 5'h1b;
|
localparam OP_JAL = 5'h1b;
|
||||||
localparam OP_SYS = 5'h1c;
|
localparam OP_SYS = 5'h1c;
|
||||||
|
// LUI 为扩展指令(标准 RISC-V opcode 0x37 -> IR[6:2]=0x0d)。
|
||||||
|
localparam OP_LUI = 5'h0d;
|
||||||
|
|
||||||
localparam ALU_SLL = 4'd0;
|
localparam ALU_SLL = 4'd0;
|
||||||
localparam ALU_SRA = 4'd1;
|
localparam ALU_SRA = 4'd1;
|
||||||
@@ -60,6 +64,9 @@ module cpu21_riscv_decoder (
|
|||||||
localparam ALU_XOR = 4'd9;
|
localparam ALU_XOR = 4'd9;
|
||||||
localparam ALU_SLT = 4'd11;
|
localparam ALU_SLT = 4'd11;
|
||||||
localparam ALU_SLTU = 4'd12;
|
localparam ALU_SLTU = 4'd12;
|
||||||
|
localparam ALU_MULH = 4'd13;
|
||||||
|
localparam ALU_MULHSU = 4'd14;
|
||||||
|
localparam ALU_PASSB = 4'd15; // LUI:直接输出 B 端(立即数)
|
||||||
|
|
||||||
wire [4:0] opcode = ir_i[6:2];
|
wire [4:0] opcode = ir_i[6:2];
|
||||||
wire [2:0] funct3 = ir_i[14:12];
|
wire [2:0] funct3 = ir_i[14:12];
|
||||||
@@ -87,7 +94,9 @@ module cpu21_riscv_decoder (
|
|||||||
beq_o = 1'b0;
|
beq_o = 1'b0;
|
||||||
bne_o = 1'b0;
|
bne_o = 1'b0;
|
||||||
blt_o = 1'b0;
|
blt_o = 1'b0;
|
||||||
|
bge_o = 1'b0;
|
||||||
bltu_o = 1'b0;
|
bltu_o = 1'b0;
|
||||||
|
bgeu_o = 1'b0;
|
||||||
jal_o = 1'b0;
|
jal_o = 1'b0;
|
||||||
jalr_o = 1'b0;
|
jalr_o = 1'b0;
|
||||||
ecall_o = 1'b0;
|
ecall_o = 1'b0;
|
||||||
@@ -102,13 +111,23 @@ module cpu21_riscv_decoder (
|
|||||||
uses_rs1_o = 1'b1;
|
uses_rs1_o = 1'b1;
|
||||||
uses_rs2_o = 1'b1;
|
uses_rs2_o = 1'b1;
|
||||||
reg_write_o = 1'b1;
|
reg_write_o = 1'b1;
|
||||||
// 电路中额外的 REMU 控制对应标准 R 型的 funct7=1/funct3=111
|
// M 扩展(funct7=0000001):mul/mulh/mulhsu/mulhu,外加课程约定的 remu
|
||||||
// 形式;此时 ALU 的 result2 即为余数。
|
// (funct3=111 形式)。mulhu 与 remu 都取 ALU 的 result2(wb_sel=3)。
|
||||||
if ((funct7 == 7'b0000001) && (funct3 == 3'b111)) begin
|
if (funct7 == 7'b0000001) begin
|
||||||
|
case (funct3)
|
||||||
|
3'b000: alu_op_o = ALU_MUL; // mul:无符号乘积低 32 位
|
||||||
|
3'b001: alu_op_o = ALU_MULH; // mulh:有符号乘积高 32 位
|
||||||
|
3'b010: alu_op_o = ALU_MULHSU; // mulhsu:有符号 x 无符号高 32 位
|
||||||
|
3'b011: begin // mulhu:无符号乘积高 32 位
|
||||||
|
alu_op_o = ALU_MUL;
|
||||||
|
wb_sel_o = 3'd3;
|
||||||
|
end
|
||||||
|
3'b111: begin // remu(课程约定):取余数
|
||||||
alu_op_o = ALU_DIVU;
|
alu_op_o = ALU_DIVU;
|
||||||
wb_sel_o = 3'd3;
|
wb_sel_o = 3'd3;
|
||||||
end else if ((funct7 == 7'b0000001) && (funct3 == 3'b000)) begin
|
end
|
||||||
alu_op_o = ALU_MUL;
|
default: reg_write_o = 1'b0;
|
||||||
|
endcase
|
||||||
end else begin
|
end else begin
|
||||||
// 标准 R 型 funct3 译码;add/sub 与 sra/srl 由 funct7[5] 区分。
|
// 标准 R 型 funct3 译码;add/sub 与 sra/srl 由 funct7[5] 区分。
|
||||||
case (funct3)
|
case (funct3)
|
||||||
@@ -125,7 +144,7 @@ module cpu21_riscv_decoder (
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// I 型运算(addi/slli/slti/xori/srai/srli/ori/andi)。
|
// I 型运算(addi/slli/slti/sltiu/xori/srai/srli/ori/andi)。
|
||||||
OP_I: begin
|
OP_I: begin
|
||||||
uses_rs1_o = 1'b1;
|
uses_rs1_o = 1'b1;
|
||||||
alu_src_o = 1'b1;
|
alu_src_o = 1'b1;
|
||||||
@@ -134,6 +153,7 @@ module cpu21_riscv_decoder (
|
|||||||
3'b000: alu_op_o = ALU_ADD; // addi:立即数加
|
3'b000: alu_op_o = ALU_ADD; // addi:立即数加
|
||||||
3'b001: alu_op_o = ALU_SLL; // slli:立即数逻辑左移
|
3'b001: alu_op_o = ALU_SLL; // slli:立即数逻辑左移
|
||||||
3'b010: alu_op_o = ALU_SLT; // slti:有符号小于置 1
|
3'b010: alu_op_o = ALU_SLT; // slti:有符号小于置 1
|
||||||
|
3'b011: alu_op_o = ALU_SLTU; // sltiu:无符号小于置 1(立即数符号扩展)
|
||||||
3'b100: alu_op_o = ALU_XOR; // xori:立即数异或
|
3'b100: alu_op_o = ALU_XOR; // xori:立即数异或
|
||||||
3'b101:
|
3'b101:
|
||||||
alu_op_o = (funct7[5] ? ALU_SRA : ALU_SRL); // srai/srli:立即数算术/逻辑右移
|
alu_op_o = (funct7[5] ? ALU_SRA : ALU_SRL); // srai/srli:立即数算术/逻辑右移
|
||||||
@@ -143,6 +163,16 @@ module cpu21_riscv_decoder (
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// 加载高位立即数 lui:rd = imm[31:12] << 12。
|
||||||
|
// 不读寄存器;用 ALU_SRC 选立即数,ALU 直通 B 端输出。
|
||||||
|
OP_LUI: begin
|
||||||
|
reg_write_o = 1'b1;
|
||||||
|
alu_src_o = 1'b1;
|
||||||
|
alu_op_o = ALU_PASSB;
|
||||||
|
imm_o = {ir_i[31:12], 12'b0};
|
||||||
|
wb_sel_o = 3'd0;
|
||||||
|
end
|
||||||
|
|
||||||
// 加载指令,当前仅支持 lw(funct3=010)。
|
// 加载指令,当前仅支持 lw(funct3=010)。
|
||||||
OP_LOAD: begin
|
OP_LOAD: begin
|
||||||
if (funct3 == 3'b010) begin
|
if (funct3 == 3'b010) begin
|
||||||
@@ -168,19 +198,22 @@ module cpu21_riscv_decoder (
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// 条件分支:beq(000)/bne(001)/blt(100,有符号小于)/bltu(110,无符号小于)。
|
// 条件分支:beq(000)/bne(001)/blt(100)/bge(101)/bltu(110)/bgeu(111)。
|
||||||
OP_BRANCH: begin
|
OP_BRANCH: begin
|
||||||
if ((funct3 == 3'b000) || (funct3 == 3'b001) ||
|
if ((funct3 == 3'b000) || (funct3 == 3'b001) || (funct3 == 3'b100) ||
|
||||||
(funct3 == 3'b100) || (funct3 == 3'b110)) begin
|
(funct3 == 3'b101) || (funct3 == 3'b110) || (funct3 == 3'b111)) begin
|
||||||
uses_rs1_o = 1'b1;
|
uses_rs1_o = 1'b1;
|
||||||
uses_rs2_o = 1'b1;
|
uses_rs2_o = 1'b1;
|
||||||
branch_o = 1'b1;
|
branch_o = 1'b1;
|
||||||
beq_o = (funct3 == 3'b000);
|
beq_o = (funct3 == 3'b000);
|
||||||
bne_o = (funct3 == 3'b001);
|
bne_o = (funct3 == 3'b001);
|
||||||
blt_o = (funct3 == 3'b100);
|
blt_o = (funct3 == 3'b100);
|
||||||
|
bge_o = (funct3 == 3'b101);
|
||||||
bltu_o = (funct3 == 3'b110);
|
bltu_o = (funct3 == 3'b110);
|
||||||
// 真值表:beq/bne 用减法比较,blt 用 ALU_SLT,bltu 用 ALU_SLTU。
|
bgeu_o = (funct3 == 3'b111);
|
||||||
alu_op_o = blt_o ? ALU_SLT : (bltu_o ? ALU_SLTU : ALU_SUB);
|
// 有符号比较用 ALU_SLT、无符号比较用 ALU_SLTU,相等/不等用减法;
|
||||||
|
// 分支是否成立由 EX 级的分支裁决单元决定,这里只与真值表保持一致。
|
||||||
|
alu_op_o = (blt_o || bge_o) ? ALU_SLT : ((bltu_o || bgeu_o) ? ALU_SLTU : ALU_SUB);
|
||||||
imm_o = {{19{ir_i[31]}}, ir_i[31], ir_i[7], ir_i[30:25], ir_i[11:8], 1'b0};
|
imm_o = {{19{ir_i[31]}}, ir_i[31], ir_i[7], ir_i[30:25], ir_i[11:8], 1'b0};
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -130,7 +130,9 @@ module cpu21_riscv_redirect_int_bpb #(
|
|||||||
reg idex_beq_q;
|
reg idex_beq_q;
|
||||||
reg idex_bne_q;
|
reg idex_bne_q;
|
||||||
reg idex_blt_q;
|
reg idex_blt_q;
|
||||||
|
reg idex_bge_q;
|
||||||
reg idex_bltu_q;
|
reg idex_bltu_q;
|
||||||
|
reg idex_bgeu_q;
|
||||||
reg idex_jal_q;
|
reg idex_jal_q;
|
||||||
reg idex_jalr_q;
|
reg idex_jalr_q;
|
||||||
reg idex_ecall_q;
|
reg idex_ecall_q;
|
||||||
@@ -182,7 +184,8 @@ module cpu21_riscv_redirect_int_bpb #(
|
|||||||
wire [2:0] f_funct3 = instr_i[14:12];
|
wire [2:0] f_funct3 = instr_i[14:12];
|
||||||
wire f_is_branch = (f_opcode == OP_BRANCH) &&
|
wire f_is_branch = (f_opcode == OP_BRANCH) &&
|
||||||
((f_funct3 == 3'b000) || (f_funct3 == 3'b001) ||
|
((f_funct3 == 3'b000) || (f_funct3 == 3'b001) ||
|
||||||
(f_funct3 == 3'b100) || (f_funct3 == 3'b110));
|
(f_funct3 == 3'b100) || (f_funct3 == 3'b101) ||
|
||||||
|
(f_funct3 == 3'b110) || (f_funct3 == 3'b111));
|
||||||
wire [31:0] bpb_predict_target;
|
wire [31:0] bpb_predict_target;
|
||||||
wire bpb_predict_hit;
|
wire bpb_predict_hit;
|
||||||
wire bpb_predict_taken;
|
wire bpb_predict_taken;
|
||||||
@@ -239,7 +242,9 @@ module cpu21_riscv_redirect_int_bpb #(
|
|||||||
wire d_beq;
|
wire d_beq;
|
||||||
wire d_bne;
|
wire d_bne;
|
||||||
wire d_blt;
|
wire d_blt;
|
||||||
|
wire d_bge;
|
||||||
wire d_bltu;
|
wire d_bltu;
|
||||||
|
wire d_bgeu;
|
||||||
wire d_jal;
|
wire d_jal;
|
||||||
wire d_jalr;
|
wire d_jalr;
|
||||||
wire d_ecall;
|
wire d_ecall;
|
||||||
@@ -268,7 +273,9 @@ module cpu21_riscv_redirect_int_bpb #(
|
|||||||
.beq_o (d_beq),
|
.beq_o (d_beq),
|
||||||
.bne_o (d_bne),
|
.bne_o (d_bne),
|
||||||
.blt_o (d_blt),
|
.blt_o (d_blt),
|
||||||
|
.bge_o (d_bge),
|
||||||
.bltu_o (d_bltu),
|
.bltu_o (d_bltu),
|
||||||
|
.bgeu_o (d_bgeu),
|
||||||
.jal_o (d_jal),
|
.jal_o (d_jal),
|
||||||
.jalr_o (d_jalr),
|
.jalr_o (d_jalr),
|
||||||
.ecall_o (d_ecall),
|
.ecall_o (d_ecall),
|
||||||
@@ -377,7 +384,9 @@ module cpu21_riscv_redirect_int_bpb #(
|
|||||||
.beq_i (idex_beq_q),
|
.beq_i (idex_beq_q),
|
||||||
.bne_i (idex_bne_q),
|
.bne_i (idex_bne_q),
|
||||||
.blt_i (idex_blt_q),
|
.blt_i (idex_blt_q),
|
||||||
|
.bge_i (idex_bge_q),
|
||||||
.bltu_i (idex_bltu_q),
|
.bltu_i (idex_bltu_q),
|
||||||
|
.bgeu_i (idex_bgeu_q),
|
||||||
.jal_i (idex_jal_q),
|
.jal_i (idex_jal_q),
|
||||||
.jalr_i (idex_jalr_q),
|
.jalr_i (idex_jalr_q),
|
||||||
.pred_taken_i (idex_pred_taken_q),
|
.pred_taken_i (idex_pred_taken_q),
|
||||||
@@ -548,7 +557,9 @@ module cpu21_riscv_redirect_int_bpb #(
|
|||||||
idex_beq_q <= 1'b0;
|
idex_beq_q <= 1'b0;
|
||||||
idex_bne_q <= 1'b0;
|
idex_bne_q <= 1'b0;
|
||||||
idex_blt_q <= 1'b0;
|
idex_blt_q <= 1'b0;
|
||||||
|
idex_bge_q <= 1'b0;
|
||||||
idex_bltu_q <= 1'b0;
|
idex_bltu_q <= 1'b0;
|
||||||
|
idex_bgeu_q <= 1'b0;
|
||||||
idex_jal_q <= 1'b0;
|
idex_jal_q <= 1'b0;
|
||||||
idex_jalr_q <= 1'b0;
|
idex_jalr_q <= 1'b0;
|
||||||
idex_ecall_q <= 1'b0;
|
idex_ecall_q <= 1'b0;
|
||||||
@@ -654,7 +665,9 @@ module cpu21_riscv_redirect_int_bpb #(
|
|||||||
idex_beq_q <= d_beq;
|
idex_beq_q <= d_beq;
|
||||||
idex_bne_q <= d_bne;
|
idex_bne_q <= d_bne;
|
||||||
idex_blt_q <= d_blt;
|
idex_blt_q <= d_blt;
|
||||||
|
idex_bge_q <= d_bge;
|
||||||
idex_bltu_q <= d_bltu;
|
idex_bltu_q <= d_bltu;
|
||||||
|
idex_bgeu_q <= d_bgeu;
|
||||||
idex_jal_q <= d_jal;
|
idex_jal_q <= d_jal;
|
||||||
idex_jalr_q <= d_jalr;
|
idex_jalr_q <= d_jalr;
|
||||||
idex_ecall_q <= d_ecall;
|
idex_ecall_q <= d_ecall;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
- 五级流水:IF、ID、EX、MEM、WB。
|
- 五级流水:IF、ID、EX、MEM、WB。
|
||||||
- EX/MEM 与 MEM/WB 前递,以及 load-use 一拍停顿。
|
- EX/MEM 与 MEM/WB 前递,以及 load-use 一拍停顿。
|
||||||
- 条件分支 `beq`、`bne`、`blt`(有符号小于)、`bltu`(无符号小于)在 EX 段判定,错误预测时清空 IF/ID、ID/EX 并重定向 PC。真值表中 BLT 的 `ALU_OP` 为 SLT,与实现一致。
|
- 条件分支 `beq`、`bne`、`blt`/`bge`(有符号)、`bltu`/`bgeu`(无符号)在 EX 段判定,错误预测时清空 IF/ID、ID/EX 并重定向 PC。真值表中 BLT 的 `ALU_OP` 为 SLT,与实现一致。
|
||||||
- `jal`、`jalr` 在 EX 段重定向,返回地址写回 `rd`。
|
- `jal`、`jalr` 在 EX 段重定向,返回地址写回 `rd`。
|
||||||
- 8 项全相联 BPB:标签 `PC[11:2]`,每项包含 valid、目标 PC、2 位饱和计数器和 3 位年龄字段。BPB 只由条件分支更新,避免 `jal`、`jalr` 占用不会被查询的表项;未命中时优先使用无效项,否则替换年龄最大的项。
|
- 8 项全相联 BPB:标签 `PC[11:2]`,每项包含 valid、目标 PC、2 位饱和计数器和 3 位年龄字段。BPB 只由条件分支更新,避免 `jal`、`jalr` 占用不会被查询的表项;未命中时优先使用无效项,否则替换年龄最大的项。
|
||||||
- 三路中断输入 `irq_i[2:0]`:两级同步、上升沿挂起、IRQ3 > IRQ2 > IRQ1 优先级,仅在 `ustatus[0]`(MIE)允许时响应。
|
- 三路中断输入 `irq_i[2:0]`:两级同步、上升沿挂起、IRQ3 > IRQ2 > IRQ1 优先级,仅在 `ustatus[0]`(MIE)允许时响应。
|
||||||
@@ -18,6 +18,9 @@
|
|||||||
- CSRRSI、CSRRCI,以及 CSRRW:支持 CSR 地址 `0x004`(`ustatus`)和 `0x041`(`uepc`)。立即数为 `IR[19:15]` 的零扩展值,并按 RISC-V 规则把旧 CSR 值写回 `rd`;这覆盖任务书中的 `csrrsi s6,0x41,0` 和 `csrrw zero,0x41,s6` 用法。
|
- CSRRSI、CSRRCI,以及 CSRRW:支持 CSR 地址 `0x004`(`ustatus`)和 `0x041`(`uepc`)。立即数为 `IR[19:15]` 的零扩展值,并按 RISC-V 规则把旧 CSR 值写回 `rd`;这覆盖任务书中的 `csrrsi s6,0x41,0` 和 `csrrw zero,0x41,s6` 用法。
|
||||||
- `ecall`:`a7 == 34` 时把 `a0` 锁存到 `led_data_o`;否则置 `halted_o`,直到 `go_i` 为高。
|
- `ecall`:`a7 == 34` 时把 `a0` 锁存到 `led_data_o`;否则置 `halted_o`,直到 `go_i` 为高。
|
||||||
- `sw` 和 `sb`:输出 `data_wstrb_o`,支持按字节写入。
|
- `sw` 和 `sb`:输出 `data_wstrb_o`,支持按字节写入。
|
||||||
|
- `lui`:加载高位立即数,`rd = imm[31:12] << 12`(按需求补充的扩展指令,标准 opcode `0x37`)。
|
||||||
|
- `sltiu`:I 型 `funct3=011`,立即数符号扩展后按无符号与 rs1 比较。
|
||||||
|
- M 扩展乘法(`funct7=0000001`):`mul`(乘积低 32 位)、`mulh`(有符号×有符号高 32 位)、`mulhsu`(有符号×无符号高 32 位)、`mulhu`(无符号×无符号高 32 位)。
|
||||||
|
|
||||||
## 指令编码
|
## 指令编码
|
||||||
|
|
||||||
@@ -25,12 +28,14 @@
|
|||||||
因此它与标准 RISC-V 指令的低 7 位 opcode 相差右移两位。
|
因此它与标准 RISC-V 指令的低 7 位 opcode 相差右移两位。
|
||||||
|
|
||||||
| 指令类别 | opcode | 说明 |
|
| 指令类别 | opcode | 说明 |
|
||||||
| ------------------------------ | -----: | --------------------------------------- |
|
| ----------------------------------------------- | -----: | ---------------------------------------------------------------------------- |
|
||||||
| R 型 | `0x0c` | add/sub/and/or/xor/slt/sltu/sll/srl/sra |
|
| R 型 | `0x0c` | add/sub/and/or/xor/slt/sltu/sll/srl/sra |
|
||||||
| I 型 ALU | `0x04` | addi/andi/ori/xori/slti/slli/srli/srai |
|
| M 扩展(R 型) | `0x0c` | `funct7=0000001`:mul/mulh/mulhsu/mulhu(另有课程约定的 remu,`funct3=111`) |
|
||||||
|
| I 型 ALU | `0x04` | addi/andi/ori/xori/slti/sltiu/slli/srli/srai |
|
||||||
|
| `lui`(扩展) | `0x0d` | 加载高位立即数,`rd = imm[31:12] << 12` |
|
||||||
| `lw` | `0x00` | `funct3=010` |
|
| `lw` | `0x00` | `funct3=010` |
|
||||||
| `sw` / `sb` | `0x08` | `funct3=010` / `000` |
|
| `sw` / `sb` | `0x08` | `funct3=010` / `000` |
|
||||||
| `beq` / `bne` / `blt` / `bltu` | `0x18` | `funct3=000` / `001` / `100` / `110` |
|
| `beq` / `bne` / `blt` / `bge` / `bltu` / `bgeu` | `0x18` | `funct3=000` / `001` / `100` / `101` / `110` / `111` |
|
||||||
| `jal` | `0x1b` | J 型立即数 |
|
| `jal` | `0x1b` | J 型立即数 |
|
||||||
| `jalr` | `0x19` | `funct3=000` |
|
| `jalr` | `0x19` | `funct3=000` |
|
||||||
| 系统类 | `0x1c` | `ecall`、`URET`、CSRRSI、CSRRCI |
|
| 系统类 | `0x1c` | `ecall`、`URET`、CSRRSI、CSRRCI |
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
# 指令扩展验证程序:每条被测指令的结果都通过 ecall(a7=34) 输出,最后用 halt 停机。
|
||||||
|
# 期望输出顺序见每行注释(共 24 次输出),同时保存在同目录 isa_test.expected(每行一项 LED 值)。
|
||||||
|
#
|
||||||
|
# 用法(在仓库根目录执行):
|
||||||
|
# python tools/rv_asm.py testbench/programs/isa_test.asm <仿真工作目录>/risc-v-benchmark_ccab.hex
|
||||||
|
# 再用 testbench/tb_no_intr.v 仿真;hex 命名为 risc-v-benchmark_ccab.hex 时会被测试
|
||||||
|
# 平台优先从仿真工作目录载入(参见 tb_no_intr.v 的 ROM 探测顺序)。
|
||||||
|
# print / halt 是 tools/rv_asm.py 提供的双字伪指令:
|
||||||
|
# print = addi a7,zero,34 + ecall;halt = addi a7,zero,10 + ecall。
|
||||||
|
|
||||||
|
# ---- sltiu:立即数符号扩展后做无符号比较 ----
|
||||||
|
addi t0, zero, 1
|
||||||
|
addi t1, zero, -1 # t1 = 0xffffffff
|
||||||
|
sltiu a0, t0, -1 # 1 <u 0xffffffff -> 00000001
|
||||||
|
print
|
||||||
|
sltiu a0, t1, 1 # 0xffffffff <u 1 -> 00000000
|
||||||
|
print
|
||||||
|
|
||||||
|
# ---- xor / sll / srl / sra(原有指令回归)----
|
||||||
|
addi t0, zero, 0xff
|
||||||
|
addi t1, zero, -1
|
||||||
|
xor a0, t0, t1 # 0xff ^ 0xffffffff -> ffffff00
|
||||||
|
print
|
||||||
|
|
||||||
|
addi t0, zero, 1
|
||||||
|
addi t1, zero, 31
|
||||||
|
sll a0, t0, t1 # 1 << 31 -> 80000000
|
||||||
|
print
|
||||||
|
|
||||||
|
addi t0, zero, -1
|
||||||
|
addi t1, zero, 28
|
||||||
|
srl a0, t0, t1 # 逻辑右移 -> 0000000f
|
||||||
|
print
|
||||||
|
sra a0, t0, t1 # 算术右移 -> ffffffff
|
||||||
|
print
|
||||||
|
|
||||||
|
# ---- mul:无符号乘积低 32 位 ----
|
||||||
|
addi t0, zero, 1234
|
||||||
|
addi t1, zero, 567
|
||||||
|
mul a0, t0, t1 # 1234*567 = 0x000aad1e
|
||||||
|
print
|
||||||
|
|
||||||
|
# ---- mulh / mulhu / mulhsu:64 位乘积的高 32 位 ----
|
||||||
|
addi t0, zero, -1 # 有符号 -1 / 无符号 0xffffffff
|
||||||
|
addi t1, zero, -1
|
||||||
|
mulh a0, t0, t1 # (-1)*(-1)=1 -> 00000000
|
||||||
|
print
|
||||||
|
mulhu a0, t0, t1 # 0xffffffff^2 -> fffffffe
|
||||||
|
print
|
||||||
|
addi t0, zero, -1
|
||||||
|
addi t1, zero, 2
|
||||||
|
mulhsu a0, t0, t1 # (-1)*2=-2 -> ffffffff
|
||||||
|
print
|
||||||
|
|
||||||
|
# ---- bltu:0 <u 0xffffffff 成立(按有符号比较则不成立)----
|
||||||
|
addi t0, zero, -1
|
||||||
|
bltu zero, t0, bltu_ok
|
||||||
|
addi a0, zero, 0x101 # 不应执行
|
||||||
|
print
|
||||||
|
bltu_ok:
|
||||||
|
addi a0, zero, 0x601 # 00000601
|
||||||
|
print
|
||||||
|
|
||||||
|
# ---- bge:有符号 >= ,(-1) >= 0 不成立,应走 fall-through ----
|
||||||
|
addi t0, zero, -1
|
||||||
|
bge t0, zero, bge_bad
|
||||||
|
addi a0, zero, 0x602 # 00000602
|
||||||
|
print
|
||||||
|
jal zero, bge_done
|
||||||
|
bge_bad:
|
||||||
|
addi a0, zero, 0x102 # 不应执行
|
||||||
|
print
|
||||||
|
bge_done:
|
||||||
|
|
||||||
|
# ---- bgeu:无符号 >= ,0xffffffff >=u 0 成立 ----
|
||||||
|
addi t0, zero, -1
|
||||||
|
bgeu t0, zero, bgeu_ok
|
||||||
|
addi a0, zero, 0x103 # 不应执行
|
||||||
|
print
|
||||||
|
bgeu_ok:
|
||||||
|
addi a0, zero, 0x603 # 00000603
|
||||||
|
print
|
||||||
|
|
||||||
|
# ---- bge 循环:从 -3 递增到 0(共 4 次输出)----
|
||||||
|
addi s1, zero, -3
|
||||||
|
bge_loop:
|
||||||
|
add a0, zero, s1
|
||||||
|
print # fffffffd / fffffffe / ffffffff / 00000000
|
||||||
|
addi s1, s1, 1
|
||||||
|
bge zero, s1, bge_loop
|
||||||
|
|
||||||
|
# ---- bgeu 循环:3 -> 1(共 3 次输出)----
|
||||||
|
addi t0, zero, 3
|
||||||
|
bgeu_loop:
|
||||||
|
add a0, zero, t0
|
||||||
|
print # 00000003 / 00000002 / 00000001
|
||||||
|
addi t0, t0, -1
|
||||||
|
addi t2, zero, 1
|
||||||
|
bgeu t0, t2, bgeu_loop
|
||||||
|
|
||||||
|
# ---- bltu 循环:4 -> 1(共 4 次输出)----
|
||||||
|
addi s1, zero, 4
|
||||||
|
bltu_loop:
|
||||||
|
add a0, zero, s1
|
||||||
|
print # 00000004 / 00000003 / 00000002 / 00000001
|
||||||
|
addi s1, s1, -1
|
||||||
|
bltu zero, s1, bltu_loop
|
||||||
|
|
||||||
|
halt
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
00000001
|
||||||
|
00000000
|
||||||
|
ffffff00
|
||||||
|
80000000
|
||||||
|
0000000f
|
||||||
|
ffffffff
|
||||||
|
000aad1e
|
||||||
|
00000000
|
||||||
|
fffffffe
|
||||||
|
ffffffff
|
||||||
|
00000601
|
||||||
|
00000602
|
||||||
|
00000603
|
||||||
|
fffffffd
|
||||||
|
fffffffe
|
||||||
|
ffffffff
|
||||||
|
00000000
|
||||||
|
00000003
|
||||||
|
00000002
|
||||||
|
00000001
|
||||||
|
00000004
|
||||||
|
00000003
|
||||||
|
00000002
|
||||||
|
00000001
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# LUI 指令测试:依次打印 lui 的结果,最后停机。
|
||||||
|
# 期望输出:12345000 / fffff000 / 80000000 / 12345678,随后停机(halted=1)。
|
||||||
|
# 用法:python tools/rv_asm.py testbench/programs/lui_test.asm <仿真工作目录>/risc-v-benchmark_ccab.hex
|
||||||
|
lui t0, 0x12345 # t0 = 0x12345000
|
||||||
|
add a0, zero, t0
|
||||||
|
addi a7, zero, 34
|
||||||
|
ecall
|
||||||
|
|
||||||
|
lui t0, 0xfffff # t0 = 0xfffff000
|
||||||
|
add a0, zero, t0
|
||||||
|
addi a7, zero, 34
|
||||||
|
ecall
|
||||||
|
|
||||||
|
lui t0, 0x80000 # t0 = 0x80000000
|
||||||
|
add a0, zero, t0
|
||||||
|
addi a7, zero, 34
|
||||||
|
ecall
|
||||||
|
|
||||||
|
lui t0, 0x12345 # 常见用法 lui+addi:0x12345678
|
||||||
|
addi t0, t0, 0x678
|
||||||
|
add a0, zero, t0
|
||||||
|
addi a7, zero, 34
|
||||||
|
ecall
|
||||||
|
|
||||||
|
addi a7, zero, 10 # a7=10 -> 停机
|
||||||
|
ecall
|
||||||
+220
@@ -0,0 +1,220 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""极简 RISC-V 汇编器:仅支持本项目测试所需的指令子集。
|
||||||
|
|
||||||
|
用法: python tools/rv_asm.py <input.asm> <output.hex>
|
||||||
|
同时生成 <output.hex>.lst 反汇编/编码清单,便于核对。
|
||||||
|
支持:add/sub/and/or/xor/sll/srl/sra/slt/sltu、
|
||||||
|
mul/mulh/mulhsu/mulhu、
|
||||||
|
addi/slti/sltiu/xori/ori/andi、slli/srli/srai、
|
||||||
|
lw/sw、beq/bne/blt/bge/bltu/bgeu、lui、jal/jalr、ecall、标签、# 注释
|
||||||
|
伪指令:print(= addi a7,zero,34 + ecall)、halt(= addi a7,zero,10 + ecall),各占两个字。
|
||||||
|
示例:python tools/rv_asm.py testbench/programs/isa_test.asm out.hex
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
REGS = {
|
||||||
|
"zero": 0,
|
||||||
|
"ra": 1,
|
||||||
|
"sp": 2,
|
||||||
|
"gp": 3,
|
||||||
|
"tp": 4,
|
||||||
|
"t0": 5,
|
||||||
|
"t1": 6,
|
||||||
|
"t2": 7,
|
||||||
|
"s0": 8,
|
||||||
|
"s1": 9,
|
||||||
|
"a0": 10,
|
||||||
|
"a1": 11,
|
||||||
|
"a2": 12,
|
||||||
|
"a3": 13,
|
||||||
|
"a4": 14,
|
||||||
|
"a5": 15,
|
||||||
|
"a6": 16,
|
||||||
|
"a7": 17,
|
||||||
|
"s2": 18,
|
||||||
|
"s3": 19,
|
||||||
|
"s4": 20,
|
||||||
|
"s5": 21,
|
||||||
|
"s6": 22,
|
||||||
|
"s7": 23,
|
||||||
|
"s8": 24,
|
||||||
|
"s9": 25,
|
||||||
|
"s10": 26,
|
||||||
|
"s11": 27,
|
||||||
|
"t3": 28,
|
||||||
|
"t4": 29,
|
||||||
|
"t5": 30,
|
||||||
|
"t6": 31,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def reg(t):
|
||||||
|
t = t.strip()
|
||||||
|
if t in REGS:
|
||||||
|
return REGS[t]
|
||||||
|
m = re.fullmatch(r"x(\d+)", t)
|
||||||
|
if m:
|
||||||
|
return int(m.group(1))
|
||||||
|
raise SystemExit("未知寄存器: " + t)
|
||||||
|
|
||||||
|
|
||||||
|
def num(t):
|
||||||
|
return int(t.strip(), 0)
|
||||||
|
|
||||||
|
|
||||||
|
def enc_r(f7, rs2, rs1, f3, rd):
|
||||||
|
return (f7 << 25) | (rs2 << 20) | (rs1 << 15) | (f3 << 12) | (rd << 7) | 0x33
|
||||||
|
|
||||||
|
|
||||||
|
def enc_i(imm, rs1, f3, rd, op=0x13):
|
||||||
|
return ((imm & 0xFFF) << 20) | (rs1 << 15) | (f3 << 12) | (rd << 7) | op
|
||||||
|
|
||||||
|
|
||||||
|
def enc_s(imm, rs2, rs1, f3):
|
||||||
|
imm &= 0xFFF
|
||||||
|
return (
|
||||||
|
((imm >> 5) << 25)
|
||||||
|
| (rs2 << 20)
|
||||||
|
| (rs1 << 15)
|
||||||
|
| (f3 << 12)
|
||||||
|
| ((imm & 0x1F) << 7)
|
||||||
|
| 0x23
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def enc_b(imm, rs2, rs1, f3):
|
||||||
|
imm &= 0x1FFF
|
||||||
|
return (
|
||||||
|
(((imm >> 12) & 1) << 31)
|
||||||
|
| (((imm >> 5) & 0x3F) << 25)
|
||||||
|
| (rs2 << 20)
|
||||||
|
| (rs1 << 15)
|
||||||
|
| (f3 << 12)
|
||||||
|
| (((imm >> 1) & 0xF) << 8)
|
||||||
|
| (((imm >> 11) & 1) << 7)
|
||||||
|
| 0x63
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def enc_u(imm, rd):
|
||||||
|
return ((imm & 0xFFFFF) << 12) | (rd << 7) | 0x37
|
||||||
|
|
||||||
|
|
||||||
|
def enc_j(imm, rd):
|
||||||
|
imm &= 0x1FFFFF
|
||||||
|
return (
|
||||||
|
(((imm >> 20) & 1) << 31)
|
||||||
|
| (((imm >> 1) & 0x3FF) << 21)
|
||||||
|
| (((imm >> 11) & 1) << 20)
|
||||||
|
| (((imm >> 12) & 0xFF) << 12)
|
||||||
|
| (rd << 7)
|
||||||
|
| 0x6F
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
RTYPE = {
|
||||||
|
"add": (0x00, 0),
|
||||||
|
"sub": (0x20, 0),
|
||||||
|
"sll": (0x00, 1),
|
||||||
|
"slt": (0x00, 2),
|
||||||
|
"sltu": (0x00, 3),
|
||||||
|
"xor": (0x00, 4),
|
||||||
|
"srl": (0x00, 5),
|
||||||
|
"sra": (0x20, 5),
|
||||||
|
"or": (0x00, 6),
|
||||||
|
"and": (0x00, 7),
|
||||||
|
"mul": (0x01, 0),
|
||||||
|
"mulh": (0x01, 1),
|
||||||
|
"mulhsu": (0x01, 2),
|
||||||
|
"mulhu": (0x01, 3),
|
||||||
|
}
|
||||||
|
ITYPE = {"addi": 0, "slti": 2, "sltiu": 3, "xori": 4, "ori": 6, "andi": 7}
|
||||||
|
SHIFT = {"slli": 1, "srli": 5, "srai": 5}
|
||||||
|
BTYPE = {"beq": 0, "bne": 1, "blt": 4, "bge": 5, "bltu": 6, "bgeu": 7}
|
||||||
|
# 双字伪指令:print = addi a7,zero,34 + ecall;halt = addi a7,zero,10 + ecall
|
||||||
|
PSEUDO_SIZE = {"print": 2, "halt": 2}
|
||||||
|
|
||||||
|
|
||||||
|
def assemble(lines):
|
||||||
|
labels, items, addr = {}, [], 0
|
||||||
|
for raw in lines:
|
||||||
|
line = raw.split("#")[0].strip()
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
while True:
|
||||||
|
m = re.match(r"^([A-Za-z_.$][\w.$]*)\s*:\s*(.*)$", line)
|
||||||
|
if not m:
|
||||||
|
break
|
||||||
|
labels[m.group(1)] = addr
|
||||||
|
line = m.group(2).strip()
|
||||||
|
if not line:
|
||||||
|
break
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
items.append((addr, line))
|
||||||
|
addr += 4 * PSEUDO_SIZE.get(line.split()[0].lower(), 1)
|
||||||
|
|
||||||
|
out = []
|
||||||
|
for addr, line in items:
|
||||||
|
parts = re.split(r"[\s,]+", line)
|
||||||
|
mn, a = parts[0].lower(), parts[1:]
|
||||||
|
if mn in RTYPE:
|
||||||
|
f7, f3 = RTYPE[mn]
|
||||||
|
w = enc_r(f7, reg(a[2]), reg(a[1]), f3, reg(a[0]))
|
||||||
|
elif mn in ITYPE:
|
||||||
|
im = num(a[2])
|
||||||
|
if not (-2048 <= im <= 2047):
|
||||||
|
raise SystemExit("I 型立即数超出 12 位有符号范围: " + line)
|
||||||
|
w = enc_i(im, reg(a[1]), ITYPE[mn], reg(a[0]))
|
||||||
|
elif mn in SHIFT:
|
||||||
|
w = enc_i(num(a[2]) & 0x1F, reg(a[1]), SHIFT[mn], reg(a[0]))
|
||||||
|
elif mn == "lui":
|
||||||
|
w = enc_u(num(a[1]), reg(a[0]))
|
||||||
|
elif mn in ("lw", "sw"):
|
||||||
|
m = re.fullmatch(r"(-?\w+)\((\w+)\)", a[1])
|
||||||
|
if not m:
|
||||||
|
raise SystemExit("内存操作数格式应为 imm(rs1): " + line)
|
||||||
|
im = num(m.group(1))
|
||||||
|
if not (-2048 <= im <= 2047):
|
||||||
|
raise SystemExit("访存偏移超出 12 位有符号范围: " + line)
|
||||||
|
if mn == "lw":
|
||||||
|
w = enc_i(im, reg(m.group(2)), 2, reg(a[0]), 0x03)
|
||||||
|
else:
|
||||||
|
w = enc_s(im, reg(a[0]), reg(m.group(2)), 2)
|
||||||
|
elif mn in BTYPE:
|
||||||
|
tgt = labels[a[2]] if a[2] in labels else num(a[2])
|
||||||
|
w = enc_b(tgt - addr, reg(a[1]), reg(a[0]), BTYPE[mn])
|
||||||
|
elif mn == "jal":
|
||||||
|
tgt = labels[a[1]] if a[1] in labels else num(a[1])
|
||||||
|
w = enc_j(tgt - addr, reg(a[0]))
|
||||||
|
elif mn == "jalr":
|
||||||
|
w = enc_i(num(a[2]), reg(a[1]), 0, reg(a[0]), 0x67)
|
||||||
|
elif mn == "ecall":
|
||||||
|
w = 0x00000073
|
||||||
|
elif mn == "print":
|
||||||
|
w = [enc_i(34, 0, 0, 17), 0x00000073]
|
||||||
|
elif mn == "halt":
|
||||||
|
w = [enc_i(10, 0, 0, 17), 0x00000073]
|
||||||
|
else:
|
||||||
|
raise SystemExit("未知助记符: " + mn)
|
||||||
|
out.append((addr, line, w if isinstance(w, list) else [w]))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
src, dst = sys.argv[1], sys.argv[2]
|
||||||
|
with open(src, encoding="utf-8") as f:
|
||||||
|
prog = assemble(f.readlines())
|
||||||
|
with open(dst, "w", encoding="ascii") as f:
|
||||||
|
for _, _, ws in prog:
|
||||||
|
for w in ws:
|
||||||
|
f.write("%08X\n" % w)
|
||||||
|
with open(dst + ".lst", "w", encoding="utf-8") as f:
|
||||||
|
for addr, line, ws in prog:
|
||||||
|
f.write("%04X: %s %s\n" % (addr, " ".join("%08X" % w for w in ws), line))
|
||||||
|
print("已生成 %s(%d 个字)" % (dst, sum(len(ws) for _, _, ws in prog)))
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user