1
+ //
2
+ //
3
+ // File Name : riscv.c
4
+ // Used on :
5
+ // Author : Ted Fried, MicroCore Labs
6
+ // Creation : 3/29/2020
7
+ // Code Type : C Source
8
+ //
9
+ // Description:
10
+ // ============
11
+ //
12
+ // Simple and compact RISC-V RS32I implementation written in C.
13
+ //
14
+ //------------------------------------------------------------------------
15
+ //
16
+ // Modification History:
17
+ // =====================
18
+ //
19
+ // Revision 1 10/8/15
20
+ // Initial revision
21
+ //
22
+ //
23
+ //------------------------------------------------------------------------
24
+ //
25
+ // Copyright (c) 2020 Ted Fried
26
+ //
27
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
28
+ // of this software and associated documentation files (the "Software"), to deal
29
+ // in the Software without restriction, including without limitation the rights
30
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
31
+ // copies of the Software, and to permit persons to whom the Software is
32
+ // furnished to do so, subject to the following conditions:
33
+ //
34
+ // The above copyright notice and this permission notice shall be included in all
35
+ // copies or substantial portions of the Software.
36
+ //
37
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
39
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
40
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
41
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
42
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
43
+ // SOFTWARE.
44
+ //
45
+ //------------------------------------------------------------------------
46
+
47
+ #include <stdio.h>
48
+
49
+ #define U_immediate rv5_opcode >> 12
50
+ #define J_immediate_SE (rv5_opcode&0x80000000) ? 0xFFE00000 | (rv5_opcode&0x000FF000) | (rv5_opcode&0x00100000)>>9 | (rv5_opcode&0x80000000)>>11 | (rv5_opcode&0x7FE00000)>>20 : (rv5_opcode&0x000FF000) | (rv5_opcode&0x00100000)>>9 | (rv5_opcode&0x80000000)>>11 | (rv5_opcode&0x7FE00000)>>20
51
+ #define B_immediate_SE (rv5_opcode&0x80000000) ? 0xFFFFE000 | (rv5_opcode&0xF00)>>7 | (rv5_opcode&0x7E000000)>>20 | (rv5_opcode&0x80)<<4 | (rv5_opcode&0x80000000)>> 19 : (rv5_opcode&0xF00)>>7 | (rv5_opcode&0x7E000000)>>20 | (rv5_opcode&0x80)<<4 | (rv5_opcode&0x80000000)>> 19
52
+ #define I_immediate_SE (rv5_opcode&0x80000000) ? 0xFFFFF000 | rv5_opcode >> 20 : rv5_opcode >> 20
53
+ #define S_immediate_SE (rv5_opcode&0x80000000) ? 0xFFFFF000 | (rv5_opcode&0xFE000000)>>20 | (rv5_opcode&0xF80)>>7 : (rv5_opcode&0xFE000000)>>20 | (rv5_opcode&0xF80)>>7
54
+
55
+ #define funct7 ((unsigned char) ((rv5_opcode&0xFE000000) >> 25) )
56
+ #define rs2 ((unsigned char) ((rv5_opcode&0x01F00000) >> 20) )
57
+ #define rs1 ((unsigned char) ((rv5_opcode&0x000F8000) >> 15) )
58
+ #define funct3 ((unsigned char) ((rv5_opcode&0x00007000) >> 12) )
59
+ #define rd ((unsigned char) ((rv5_opcode&0x00000F80) >> 7 ) )
60
+ #define opcode ((rv5_opcode&0x0000007F) )
61
+
62
+
63
+ unsigned int shamt ;
64
+ unsigned long rv5_reg [32 ];
65
+ unsigned long rv5_instruction_RAM [4096 ];
66
+ unsigned long rv5_user_memory [4096 ] ;
67
+ unsigned long rv5_opcode ;
68
+ unsigned long rv5_pc = 0 ;
69
+ unsigned long temp ;
70
+
71
+
72
+ int main ()
73
+
74
+ {
75
+ while (1 )
76
+ {
77
+
78
+ rv5_opcode = rv5_instruction_RAM [rv5_pc >>2 ];
79
+ shamt = rs2 ;
80
+
81
+ printf ("PC:0x%x Opcode:0x%x " , rv5_pc , rv5_opcode );
82
+
83
+ if (opcode == 0b0110111 ) { rv5_reg [rd ] = U_immediate << 12 ; printf (" LUI " ); } else // LUI
84
+ if (opcode == 0b0010111 ) { rv5_reg [rd ] = (U_immediate << 12 ) + rv5_pc ; printf (" AUIPC " ); } else // AUIPC
85
+ if (opcode == 0b1101111 ) { rv5_reg [rd ] = rv5_pc + 0x4 ; rv5_pc = (J_immediate_SE ) + rv5_pc - 0x4 ; printf (" JAL " ); } else // JAL
86
+ if (opcode == 0b1100111 ) { rv5_reg [rd ] = rv5_pc + 0x4 ; rv5_pc = (((I_immediate_SE ) + rv5_reg [rs1 ]) & 0xFFFFFFFE ) - 0x4 ; printf (" JALR " ); } else // JALR
87
+ if (opcode == 0b1100011 && funct3 == 0b000 ) { if (rv5_reg [rs1 ]== rv5_reg [rs2 ]) rv5_pc = ( (B_immediate_SE ) + rv5_pc ) - 0x4 ; printf (" BEQ " ); } else // BEQ
88
+ if (opcode == 0b1100011 && funct3 == 0b001 ) { if (rv5_reg [rs1 ]!= rv5_reg [rs2 ]) rv5_pc = ( (B_immediate_SE ) + rv5_pc ) - 0x4 ; printf (" BNE " ); } else // BNE
89
+ if (opcode == 0b1100011 && funct3 == 0b100 ) { if ((signed long )rv5_reg [rs1 ]< (signed long )rv5_reg [rs2 ]) rv5_pc = ((B_immediate_SE ) + rv5_pc ) - 0x4 ; printf (" BLT " ); } else // BLT
90
+ if (opcode == 0b1100011 && funct3 == 0b101 ) { if ((signed long )rv5_reg [rs1 ]>=(signed long )rv5_reg [rs2 ]) rv5_pc = ((B_immediate_SE ) + rv5_pc ) - 0x4 ; printf (" BGE " ); } else // BGE
91
+ if (opcode == 0b1100011 && funct3 == 0b110 ) { if (rv5_reg [rs1 ]>=rv5_reg [rs2 ]) rv5_pc = ( (B_immediate_SE ) + rv5_pc ) - 0x4 ; printf (" BLTU " ); } else // BLTU
92
+ if (opcode == 0b1100011 && funct3 == 0b111 ) { if (rv5_reg [rs1 ]>=rv5_reg [rs2 ]) rv5_pc = ( (B_immediate_SE ) + rv5_pc ) - 0x4 ; printf (" BGTU " ); } else // BGTU
93
+ if (opcode == 0b0000011 && funct3 == 0b000 ) { rv5_reg [rd ] = (rv5_user_memory [(I_immediate_SE )+ rv5_reg [rs1 ]] & 0x80 ) ? 0xFFFFFF00 | rv5_user_memory [(I_immediate_SE )+ rv5_reg [rs1 ]] : (rv5_user_memory [(I_immediate_SE )+ rv5_reg [rs1 ]] & 0xFF ); printf (" LB " ); } else // LB
94
+ if (opcode == 0b0000011 && funct3 == 0b001 ) { rv5_reg [rd ] = (rv5_user_memory [(I_immediate_SE )+ rv5_reg [rs1 ]] & 0x8000 ) ? 0xFFFF0000 | rv5_user_memory [(I_immediate_SE )+ rv5_reg [rs1 ]] : (rv5_user_memory [(I_immediate_SE )+ rv5_reg [rs1 ]] & 0xFFFF ); printf (" LH " ); } else // LH
95
+ if (opcode == 0b0000011 && funct3 == 0b010 ) { rv5_reg [rd ] = rv5_user_memory [(I_immediate_SE )+ rv5_reg [rs1 ]]; printf (" LW " ); } else // LW
96
+ if (opcode == 0b0000011 && funct3 == 0b100 ) { rv5_reg [rd ] = rv5_user_memory [(I_immediate_SE )+ rv5_reg [rs1 ]] & 0x000000FF ; printf (" LBU " ); } else // LBU
97
+ if (opcode == 0b0000011 && funct3 == 0b101 ) { rv5_reg [rd ] = rv5_user_memory [(I_immediate_SE )+ rv5_reg [rs1 ]] & 0x0000FFFF ; printf (" LHU " ); } else // LHU
98
+ if (opcode == 0b0100011 && funct3 == 0b000 ) { rv5_user_memory [(S_immediate_SE )+ rv5_reg [rs1 ]] = (rv5_user_memory [(S_immediate_SE )+ rv5_reg [rs1 ]]& 0xFFFFFF00 ) | (rv5_reg [rs2 ]& 0xFF ); printf (" SB " ); } else // SB
99
+ if (opcode == 0b0100011 && funct3 == 0b001 ) { rv5_user_memory [(S_immediate_SE )+ rv5_reg [rs1 ]] = (rv5_user_memory [(S_immediate_SE )+ rv5_reg [rs1 ]]& 0xFFFF0000 ) | (rv5_reg [rs2 ]& 0xFFFF ); printf (" SH " ); } else // SH
100
+ if (opcode == 0b0100011 && funct3 == 0b010 ) { rv5_user_memory [(S_immediate_SE )+ rv5_reg [rs1 ]] = rv5_reg [rs2 ]; printf (" SW " ); } else // SW
101
+ if (opcode == 0b0010011 && funct3 == 0b000 ) { rv5_reg [rd ] = (I_immediate_SE ) + rv5_reg [rs1 ]; printf (" ADDI " ); } else // ADDI
102
+ if (opcode == 0b0010011 && funct3 == 0b010 ) { if ((signed long )rv5_reg [rs1 ] < ((signed long )I_immediate_SE )) rv5_reg [rd ]= 1 ; else rv5_reg [rd ]= 0 ; printf (" SLTI " ); } else // SLTI
103
+ if (opcode == 0b0010011 && funct3 == 0b011 ) { if (rv5_reg [rs1 ] < (I_immediate_SE )) rv5_reg [rd ]= 1 ; else rv5_reg [rd ]= 0 ; printf (" SLTIU " ); } else // SLTIU
104
+ if (opcode == 0b0010011 && funct3 == 0b100 ) { rv5_reg [rd ] = rv5_reg [rs1 ] ^ (I_immediate_SE ); printf (" XORI " ); } else // XORI
105
+ if (opcode == 0b0010011 && funct3 == 0b110 ) { rv5_reg [rd ] = rv5_reg [rs1 ] | (I_immediate_SE ); printf (" ORI " ); } else // ORI
106
+ if (opcode == 0b0010011 && funct3 == 0b111 ) { rv5_reg [rd ] = rv5_reg [rs1 ] & (I_immediate_SE ); printf (" ANDI " ); } else // ANDI
107
+ if (opcode == 0b0010011 && funct3 == 0b001 && funct7 == 0b0000000 ) { rv5_reg [rd ] = rv5_reg [rs1 ] << shamt ; printf (" SLLI " ); } else // SLLI
108
+ if (opcode == 0b0010011 && funct3 == 0b101 && funct7 == 0b0100000 ) {rv5_reg [rd ]= rv5_reg [rs1 ]; temp = rv5_reg [rs1 ]& 0x80000000 ; while (shamt > 0 ) { rv5_reg [rd ]= (rv5_reg [rd ]>>1 )|temp ; shamt -- ;} printf (" SRAI " ); } else // SRAI
109
+ if (opcode == 0b0010011 && funct3 == 0b101 && funct7 == 0b0000000 ) { rv5_reg [rd ] = rv5_reg [rs1 ] >> shamt ; printf (" SRLI " ); } else // SRLI
110
+ if (opcode == 0b0110011 && funct3 == 0b000 && funct7 == 0b0100000 ) { rv5_reg [rd ] = rv5_reg [rs1 ] - rv5_reg [rs2 ]; printf (" SUB " ); } else // SUB
111
+ if (opcode == 0b0110011 && funct3 == 0b000 ) { rv5_reg [rd ] = rv5_reg [rs1 ] + rv5_reg [rs2 ]; printf (" ADD " ); } else // ADD
112
+ if (opcode == 0b0110011 && funct3 == 0b001 ) { rv5_reg [rd ] = rv5_reg [rs1 ] << (rv5_reg [rs2 ]& 0x1F ); printf (" SLL " ); } else // SLL
113
+ if (opcode == 0b0110011 && funct3 == 0b010 ) { if ((signed long )rv5_reg [rs1 ] < (signed long )rv5_reg [rs2 ]) rv5_reg [rd ]= 1 ; else rv5_reg [rd ]= 0 ; printf (" SLT " ); } else // SLT
114
+ if (opcode == 0b0110011 && funct3 == 0b011 ) { if (rv5_reg [rs1 ] < rv5_reg [rs2 ]) rv5_reg [rd ]= 1 ; else rv5_reg [rd ]= 0 ; printf (" SLTU " ); } else // SLTU
115
+ if (opcode == 0b0110011 && funct3 == 0b100 ) { rv5_reg [rd ] = rv5_reg [rs1 ] ^ rv5_reg [rs2 ]; printf (" XOR " ); } else // XOR
116
+ if (opcode == 0b0110011 && funct3 == 0b101 && funct7 == 0b0100000 ) {rv5_reg [rd ]= rv5_reg [rs1 ]; shamt = (rv5_reg [rs2 ]& 0x1F ); temp = rv5_reg [rs1 ]& 0x80000000 ; while (shamt > 0 ) { rv5_reg [rd ]= (rv5_reg [rd ]>>1 )|temp ; shamt -- ;} printf (" SRA " ); } else // SRA
117
+ if (opcode == 0b0110011 && funct3 == 0b101 && funct7 == 0b0000000 ) { rv5_reg [rd ] = rv5_reg [rs1 ] >> (rv5_reg [rs2 ]& 0x1F ); printf (" SRL " ); } else // SRL
118
+ if (opcode == 0b0110011 && funct3 == 0b110 ) { rv5_reg [rd ] = rv5_reg [rs1 ] | rv5_reg [rs2 ]; printf (" OR " ); } else // OR
119
+ if (opcode == 0b0110011 && funct3 == 0b111 ) { rv5_reg [rd ] = rv5_reg [rs1 ] & rv5_reg [rs2 ]; printf (" AND " ); } else printf (" **INVALID** " ); // AND
120
+
121
+ rv5_pc = rv5_pc + 0x4 ;
122
+ rv5_reg [0 ]= 0 ;
123
+
124
+ printf ("rd:%d rs1:%d rs2:%d U_immediate:0x%x J_immediate:0x%x B_immediate:0x%x I_immediate:0x%x S_immediate:0x%x funct3:0x%x funct7:0x%x\n" ,rd ,rs1 ,rs2 ,U_immediate ,J_immediate_SE ,B_immediate_SE ,I_immediate_SE ,S_immediate_SE ,funct3 ,funct7 );
125
+ printf ("Regs: " ); for (int i = 0 ; i < 32 ; i ++ ) { printf ("r%d:%x " ,i ,rv5_reg [i ]); } printf ("\n" ); //scanf("%c",&temp);
126
+ printf ("Memory: " ); for (int i = 0 ; i < 7 ; i ++ ) { printf ("Addr%d:%x " ,i ,rv5_user_memory [i ]); } printf ("\n" ); scanf ("%c" ,& temp );
127
+
128
+ }
129
+
130
+ }
0 commit comments