newStep.v

This commit is contained in:
2025-11-27 04:28:54 +03:00
parent a84b8fcfde
commit 6e38a6c1af
85 changed files with 25646 additions and 6801 deletions

808
riscv_assembly.v Normal file
View File

@@ -0,0 +1,808 @@
/*
* A simple assembler for RiscV written in VERILOG.
* See table page 104 of RiscV instruction manual.
* Bruno Levy, March 2022
*/
// Machine code will be generated in MEM,
// starting from address 0 (can be changed below,
// initial value of memPC).
//
// Example:
//
// module MyModule( my inputs, my outputs ...);
// ...
// reg [31:0] MEM [0:255];
// `include "riscv_assembly.v" // yes, needs to be included from here.
// integer L0_;
// initial begin
// ADD(x1,x0,x0);
// ADDI(x2,x0,32);
// Label(L0_); ADDI(x1,x1,1);
// BNE(x1, x2, LabelRef(L0_));
// EBREAK();
// end
// 1) simulate with icarus, it will complain about uninitialized labels,
// and will display for each Label() statement the address to be used
// (in the present case, it is 8)
// 2) replace the declaration of the label:
// integer L0_ = 8;
// re-simulate with icarus
// If you made an error, it will be detected
// 3) synthesize with yosys
// (if you do not use labels, you can synthesize directly, of course...)
//
//
// You can change the address where code is generated
// by assigning to memPC (needs to be a word boundary).
//
// NOTE: to be checked, LUI, AUIPC take as argument
// pre-shifted constant, unlike in GNU assembly
integer memPC;
initial memPC = 0;
/***************************************************************************/
/*
* Register names.
* Looks stupid, but makes assembly code more legible (without it,
* one does not make the difference between immediate values and
* register ids).
*/
localparam x0 = 0, x1 = 1, x2 = 2, x3 = 3, x4 = 4, x5 = 5, x6 = 6, x7 = 7,
x8 = 8, x9 = 9, x10=10, x11=11, x12=12, x13=13, x14=14, x15=15,
x16=16, x17=17, x18=18, x19=19, x20=20, x21=21, x22=22, x23=23,
x24=24, x25=25, x26=26, x27=27, x28=28, x29=29, x30=30, x31=31;
// add x0,x0,x0
localparam [31:0] NOP_CODEOP = 32'b0000000_00000_00000_000_00000_0110011;
/***************************************************************************/
/*
* R-Type instructions.
* rd <- rs1 OP rs2
*/
task RType;
input [6:0] opcode;
input [4:0] rd;
input [4:0] rs1;
input [4:0] rs2;
input [2:0] funct3;
input [6:0] funct7;
begin
MEM[memPC[31:2]] = {funct7, rs2, rs1, funct3, rd, opcode};
memPC = memPC + 4;
end
endtask
task ADD;
input [4:0] rd;
input [4:0] rs1;
input [4:0] rs2;
RType(7'b0110011, rd, rs1, rs2, 3'b000, 7'b0000000);
endtask
task SUB;
input [4:0] rd;
input [4:0] rs1;
input [4:0] rs2;
RType(7'b0110011, rd, rs1, rs2, 3'b000, 7'b0100000);
endtask
task SLL;
input [4:0] rd;
input [4:0] rs1;
input [4:0] rs2;
RType(7'b0110011, rd, rs1, rs2, 3'b001, 7'b0000000);
endtask
task SLT;
input [4:0] rd;
input [4:0] rs1;
input [4:0] rs2;
RType(7'b0110011, rd, rs1, rs2, 3'b010, 7'b0000000);
endtask
task SLTU;
input [4:0] rd;
input [4:0] rs1;
input [4:0] rs2;
RType(7'b0110011, rd, rs1, rs2, 3'b011, 7'b0000000);
endtask
task XOR;
input [4:0] rd;
input [4:0] rs1;
input [4:0] rs2;
RType(7'b0110011, rd, rs1, rs2, 3'b100, 7'b0000000);
endtask
task SRL;
input [4:0] rd;
input [4:0] rs1;
input [4:0] rs2;
RType(7'b0110011, rd, rs1, rs2, 3'b101, 7'b0000000);
endtask
task SRA;
input [4:0] rd;
input [4:0] rs1;
input [4:0] rs2;
RType(7'b0110011, rd, rs1, rs2, 3'b101, 7'b0100000);
endtask
task OR;
input [4:0] rd;
input [4:0] rs1;
input [4:0] rs2;
RType(7'b0110011, rd, rs1, rs2, 3'b110, 7'b0000000);
endtask
task AND;
input [4:0] rd;
input [4:0] rs1;
input [4:0] rs2;
RType(7'b0110011, rd, rs1, rs2, 3'b111, 7'b0000000);
endtask
/***************************************************************************/
/*
* I-Type instructions.
* rd <- rs1 OP imm
*/
task IType;
input [6:0] opcode;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
input [2:0] funct3;
begin
MEM[memPC[31:2]] = {imm[11:0], rs1, funct3, rd, opcode};
memPC = memPC + 4;
end
endtask
task ADDI;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
IType(7'b0010011, rd, rs1, imm, 3'b000);
end
endtask
task SLTI;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
IType(7'b0010011, rd, rs1, imm, 3'b010);
end
endtask
task SLTIU;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
IType(7'b0010011, rd, rs1, imm, 3'b011);
end
endtask
task XORI;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
IType(7'b0010011, rd, rs1, imm, 3'b100);
end
endtask
task ORI;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
IType(7'b0010011, rd, rs1, imm, 3'b110);
end
endtask
task ANDI;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
IType(7'b0010011, rd, rs1, imm, 3'b111);
end
endtask
// The three shifts, SLLI, SRLI, SRAI, encoded in RType format
// (rs2 is replaced with shift amount=imm[4:0])
task SLLI;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
RType(7'b0010011, rd, rs1, imm[4:0], 3'b001, 7'b0000000);
end
endtask
task SRLI;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
RType(7'b0010011, rd, rs1, imm[4:0], 3'b101, 7'b0000000);
end
endtask
task SRAI;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
RType(7'b0010011, rd, rs1, imm[4:0], 3'b101, 7'b0100000);
end
endtask
/***************************************************************************/
/*
* Jumps (JAL and JALR)
*/
task JType;
input [6:0] opcode;
input [4:0] rd;
input [31:0] imm;
begin
MEM[memPC[31:2]] = {imm[20], imm[10:1], imm[11], imm[19:12], rd, opcode};
memPC = memPC + 4;
end
endtask
task JAL;
input [4:0] rd;
input [31:0] imm;
begin
JType(7'b1101111, rd, imm);
end
endtask
// JALR is encoded in the IType format.
task JALR;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
IType(7'b1100111, rd, rs1, imm, 3'b000);
end
endtask
/***************************************************************************/
/*
* Branch instructions.
*/
task BType;
input [6:0] opcode;
input [4:0] rs1;
input [4:0] rs2;
input [31:0] imm;
input [2:0] funct3;
begin
MEM[memPC[31:2]] = {imm[12],imm[10:5], rs2, rs1, funct3, imm[4:1], imm[11], opcode};
memPC = memPC + 4;
end
endtask
task BEQ;
input [4:0] rs1;
input [4:0] rs2;
input [31:0] imm;
begin
BType(7'b1100011, rs1, rs2, imm, 3'b000);
end
endtask
task BNE;
input [4:0] rs1;
input [4:0] rs2;
input [31:0] imm;
begin
BType(7'b1100011, rs1, rs2, imm, 3'b001);
end
endtask
task BLT;
input [4:0] rs1;
input [4:0] rs2;
input [31:0] imm;
begin
BType(7'b1100011, rs1, rs2, imm, 3'b100);
end
endtask
task BGE;
input [4:0] rs1;
input [4:0] rs2;
input [31:0] imm;
begin
BType(7'b1100011, rs1, rs2, imm, 3'b101);
end
endtask
task BLTU;
input [4:0] rs1;
input [4:0] rs2;
input [31:0] imm;
begin
BType(7'b1100011, rs1, rs2, imm, 3'b110);
end
endtask
task BGEU;
input [4:0] rs1;
input [4:0] rs2;
input [31:0] imm;
begin
BType(7'b1100011, rs1, rs2, imm, 3'b111);
end
endtask
/***************************************************************************/
/*
* LUI and AUIPC
*/
task UType;
input [6:0] opcode;
input [4:0] rd;
input [31:0] imm;
begin
MEM[memPC[31:2]] = {imm[31:12], rd, opcode};
memPC = memPC + 4;
end
endtask
task LUI;
input [4:0] rd;
input [31:0] imm;
begin
UType(7'b0110111, rd, imm);
end
endtask
task AUIPC;
input [4:0] rd;
input [31:0] imm;
begin
UType(7'b0010111, rd, imm);
end
endtask
/***************************************************************************/
/*
* Load instructions
*/
task LB;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
IType(7'b0000011, rd, rs1, imm, 3'b000);
end
endtask
task LH;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
IType(7'b0000011, rd, rs1, imm, 3'b001);
end
endtask
task LW;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
IType(7'b0000011, rd, rs1, imm, 3'b010);
end
endtask
task LBU;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
IType(7'b0000011, rd, rs1, imm, 3'b100);
end
endtask
task LHU;
input [4:0] rd;
input [4:0] rs1;
input [31:0] imm;
begin
IType(7'b0000011, rd, rs1, imm, 3'b101);
end
endtask
/***************************************************************************/
/*
* Store instructions
*/
task SType;
input [6:0] opcode;
input [4:0] rs1;
input [4:0] rs2;
input [31:0] imm;
input [2:0] funct3;
begin
MEM[memPC[31:2]] = {imm[11:5], rs2, rs1, funct3, imm[4:0], opcode};
memPC = memPC + 4;
end
endtask
// Note: in SB, SH, SW, rs1 and rs2 are swapped, to match assembly code:
// for instance:
//
// rs2 rs1
// sw ra, 0(sp)
task SB;
input [4:0] rs1;
input [4:0] rs2;
input [31:0] imm;
begin
SType(7'b0100011, rs2, rs1, imm, 3'b000);
end
endtask
task SH;
input [4:0] rs1;
input [4:0] rs2;
input [31:0] imm;
begin
SType(7'b0100011, rs2, rs1, imm, 3'b001);
end
endtask
task SW;
input [4:0] rs1;
input [4:0] rs2;
input [31:0] imm;
begin
SType(7'b0100011, rs2, rs1, imm, 3'b010);
end
endtask
/***************************************************************************/
/*
* SYSTEM instructions
*/
task FENCE;
input [3:0] pred;
input [3:0] succ;
begin
MEM[memPC[31:2]] = {4'b0000, pred, succ, 5'b00000, 3'b000, 5'b00000, 7'b1110011};
memPC = memPC + 4;
end
endtask
task FENCE_I;
begin
MEM[memPC[31:2]] = {4'b0000, 4'b0000, 4'b0000, 5'b00000, 3'b001, 5'b00000, 7'b1110011};
memPC = memPC + 4;
end
endtask
task ECALL;
begin
MEM[memPC[31:2]] = {12'b000000000000, 5'b00000, 3'b000, 5'b00000, 7'b1110011};
memPC = memPC + 4;
end
endtask
task EBREAK;
begin
MEM[memPC[31:2]] = {12'b000000000001, 5'b00000, 3'b000, 5'b00000, 7'b1110011};
memPC = memPC + 4;
end
endtask
task CSRRW;
input [4:0] rd;
input [11:0] csr;
input [4:0] rs1;
begin
MEM[memPC[31:2]] = {csr, rs1, 3'b001, rd, 7'b1110011};
memPC = memPC + 4;
end
endtask
task CSRRS;
input [4:0] rd;
input [11:0] csr;
input [4:0] rs1;
begin
MEM[memPC[31:2]] = {csr, rs1, 3'b010, rd, 7'b1110011};
memPC = memPC + 4;
end
endtask
task CSRRC;
input [4:0] rd;
input [11:0] csr;
input [4:0] rs1;
begin
MEM[memPC[31:2]] = {csr, rs1, 3'b011, rd, 7'b1110011};
memPC = memPC + 4;
end
endtask
task CSRRWI;
input [4:0] rd;
input [11:0] csr;
input [31:0] imm;
begin
MEM[memPC[31:2]] = {csr, imm[4:0], 3'b101, rd, 7'b1110011};
memPC = memPC + 4;
end
endtask
task CSRRSI;
input [4:0] rd;
input [11:0] csr;
input [31:0] imm;
begin
MEM[memPC[31:2]] = {csr, imm[4:0], 3'b110, rd, 7'b1110011};
memPC = memPC + 4;
end
endtask
task CSRRCI;
input [4:0] rd;
input [11:0] csr;
input [31:0] imm;
begin
MEM[memPC[31:2]] = {csr, imm[4:0], 3'b111, rd, 7'b1110011};
memPC = memPC + 4;
end
endtask
/***************************************************************************/
/*
* Labels.
* Example of usage:
*
* ADD(x1,x0,x0);
* Label(L0_); ADDI(x1,x1,1);
* JAL(x0, LabelRef(L0_));
*/
integer ASMerror=0;
task Label;
inout integer L;
begin
`ifdef BENCH
if(L[0] === 1'bx) begin
$display("Missing label initialization");
ASMerror = 1;
end else if(L != memPC) begin
$display("Incorrect label initialization");
$display("Expected: %0d Got: %0d",memPC,L);
ASMerror = 1;
end
$display("Label:",memPC);
`endif
end
endtask
function [31:0] LabelRef;
input integer L;
begin
`ifdef BENCH
if(L[0] === 1'bx) begin
$display("Reference to uninitialized label");
ASMerror = 1;
end
`endif
LabelRef = L - memPC;
end
endfunction
task endASM;
begin
`ifdef GET_ASM_LABELS
$finish();
`endif
`ifdef BENCH
if(ASMerror) $finish();
`endif
end
endtask
/****************************************************************************/
/*
* RISC-V ABI register names.
*/
localparam zero = x0;
localparam ra = x1;
localparam sp = x2;
localparam gp = x3;
localparam tp = x4;
localparam t0 = x5;
localparam t1 = x6;
localparam t2 = x7;
localparam fp = x8;
localparam s0 = x8;
localparam s1 = x9;
localparam a0 = x10;
localparam a1 = x11;
localparam a2 = x12;
localparam a3 = x13;
localparam a4 = x14;
localparam a5 = x15;
localparam a6 = x16;
localparam a7 = x17;
localparam s2 = x18;
localparam s3 = x19;
localparam s4 = x20;
localparam s5 = x21;
localparam s6 = x22;
localparam s7 = x23;
localparam s8 = x24;
localparam s9 = x25;
localparam s10 = x26;
localparam s11 = x27;
localparam t3 = x28;
localparam t4 = x29;
localparam t5 = x30;
localparam t6 = x31;
/*
* RISC-V pseudo-instructions
*/
task NOP;
begin
ADD(x0,x0,x0);
end
endtask
// See https://stackoverflow.com/questions/50742420/
// risc-v-build-32-bit-constants-with-lui-and-addi
// Add imm[11] << 12 to the constant passed to LUI,
// so that it cancels sign expansion done by ADDI
// if imm[11] is 1.
task LI;
input [4:0] rd;
input [31:0] imm;
begin
if(imm == 0) begin
ADD(rd,zero,zero);
end else if($signed(imm) >= -2048 && $signed(imm) < 2048) begin
ADDI(rd,zero,imm);
end else begin
LUI(rd,imm + (imm[11] << 12)); // cancel sign expansion
if(imm[11:0] != 0) begin
ADDI(rd,rd,imm[11:0]);
end
end
end
endtask
task CALL;
input [31:0] offset;
begin
AUIPC(x6, offset);
JALR(x1, x6, offset[11:0]);
end
endtask
task RET;
begin
JALR(x0,x1,0);
end
endtask
task MV;
input [4:0] rd;
input [4:0] rs1;
begin
ADD(rd,rs1,zero);
end
endtask
task J;
input [31:0] imm;
begin
// TODO: far targets
JAL(zero,imm);
end
endtask
task JR;
input [4:0] rs1;
input [31:0] imm;
begin
JALR(zero,rs1,imm);
end
endtask
task BEQZ;
input [4:0] rs1;
input [31:0] imm;
begin
BEQ(rs1,x0,imm);
end
endtask
task BNEZ;
input [4:0] rs1;
input [31:0] imm;
begin
BNE(rs1,x0,imm);
end
endtask
task BGT;
input [4:0] rs1;
input [4:0] rs2;
input [31:0] imm;
begin
BLT(rs2,rs1,imm);
end
endtask
task DATAW;
input [31:0] w;
begin
MEM[memPC[31:2]] = w;
memPC = memPC+4;
end
endtask
task DATAB;
input [7:0] b1;
input [7:0] b2;
input [7:0] b3;
input [7:0] b4;
begin
MEM[memPC[31:2]][ 7: 0] = b1;
MEM[memPC[31:2]][15: 8] = b2;
MEM[memPC[31:2]][23:16] = b3;
MEM[memPC[31:2]][31:24] = b4;
memPC = memPC+4;
end
endtask
/****************************************************************************/