====== 3. Seminar - Design of simple processor control unit ====== Task assignment and description: EN: {{ .:03_seminar_assignment-en.pdf |}} CZ: {{.:03_cviceni_zadani.pdf|}} \\ \\ \\ The second part of the seminar - Explanation of basic instructions of selected CPU and their use Description of RISC-V instruction set and architecture at RISCV.org pages [[https://riscv.org/technical/specifications/|https://riscv.org/technical/specifications/]] * Volume 1, Unprivileged Spec * Volume 2, Privileged Spec The compact decription of the RISC-V instructions {{https://cw.fel.cvut.cz/b212/_media/courses/b35apo/tutorials/03/riscvcard.pdf | riscvcard.pdf}} Detailed description of minimal RISC-V subset: ^ Instruction ^ Instruction Syntax ^ Operation ^ Description ^ | add | add rd, rs1, rs2 | rd ← rs1 + rs2; | Add: Add together values in two registers (rs1 + rs2) and stores the result in register rd. | | addi | addi rd, rd1, imm12 | rd ← rs1 + imm12; | Add immediate: Adds a value in rs1 and a signed constant (12-bit immediate value) and stores the result in rd. | | sub | sub rd,rs1,rs2 | rd ← rs1 - rs2 | Subtract: Subtracts a value in register rs2 from value of rs1 and stores result in rd. | | bne | bne rs1, rs2, Label | if rs1 != rs2 go to PC+2*imm12; else go to PC+4 | Branch on not equal: (conditional) jump if value in rs1 is not equal to a value in rs2 (imm12 = Label - PC)| | beq | beq rs1, rs2, Label | if rs1 == rs2 go to PC+2*imm12; else go to PC+4 | Branch on equal: (conditional) jump if value in rs1 is equal to a value in rs2 (imm12 = Label - PC) | | slt | slt rd,rs1,rs2 | rd ← (rs1 < rs2) | Set on less than: set register rd to one, if the condition rs1 < rs2 is true | | slli | slli rd,rs1,imm5 | rd ← rs1 << imm5 | Shift Left Logical: Shifts value in the register to the left by imm5 bits (ekvivalent to operation multiplication by constant 2imm5 ) | | j | j Label | PC ← PC + 2*imm20 | Jump: unconditional jump to the Label (imm20 = Label - PC)| | lw | lw rd, imm12(rs1) | [rd] ← Mem[[rs1] + imm12]; |Load word: Loads a word from address in memory and stores it in register rd. | | sw | sw rs2, imm12(rs1) | Mem[[rs1] + imm12] ← [rs2]; | Store word: Stores a value in register rs2 to given address in memory. | | lui | lui rd, imm20 | [rd] ← imm20<<12 | Load upper immediate: Stores given immediate value (constant) imm20 to upper part of register rd. Register is 32 bits long and imm20 is 20 bits. | | li | li rd, Immediate | lui rd, (Immediate+0x800)[31:12]; \\ addi rd,rd, Immediate[11:0] | Load Immediate: sets register rd to 32-bitovou constant. It is pseudo-instruction - it is translated into sequence of actual instructions according to the value range. | | la | la rd, LabelAddr | auipc rd, (LabelAddr - pc + 0x800)[31:12]; \\ addi rd, rd, (LabelAddr - pc)[11:0]; | Load Address: sets register rd 32-bit value computer relative to actual PC/instruction address. It is pseudo-instruction - it is translated into sequence of actual instructions according to the value range.| Description of individual MIPS instructions: ^ Instruction ^ Instruction Syntax ^ Operation ^ Description ^ | add | add \$d, \$s, \$t | \$d = \$s + \$t; | Add: Add together values in two registers (\$s + \$t) and stores the result in register \$d. | | addi | addi \$t, \$s, C | \$t = \$s + C; | Add immediate: Adds a value in \$s and a signed constant (immediate value) and stores the result in \$t. | | sub | sub \$d,\$s,\$t | \$d = \$s - \$t | Subtract: Subtracts a value in register \$t from value of \$s and stores result in \$d. | | and | and d,s,t | \$d = s & \$t | And: Logical and (bit-wise conjunction) | | andi | andi d,s,C | \$d = s & C | And immediate: Logical and with constant (no sign extension of C) | | or | or d,s,t | \$d = \$s | \$t | Or: Logical or (bit-vise inclusive disjunction) | | ori | ori d,s,t | \$d = \$s | C | Or: Logical or with constant (no sign extension of C) | | slt | slt \$d, \$s, \$t | \$d = \$s + \$t; | Set if less then: if value \$s < \$t set \$d to 1 else to 0. | | bne | bne \$s, \$t, offset | if \$s != \$t go to PC+4+4*offset; else go to PC+4 | Branch on not equal: (conditional) jump if value in \$s is not equal to a value in \$t. | | beq | beq \$s, \$t, offset | if \$s == \$t go to PC+4+4*offset; else go to PC+4 | Branch on equal: (conditional) jump if value in \$s is equal to a value in \$t. | | jump | j C | PC = (PC ∧ 0xf0000000) ∨ 4*C | Jump: Unconditional jump to label C. | | lw | lw \$t,C(\$s) | \$t = Memory[\$s + C] | Load word: Loads a word from address in memory and stores it in register \$t. | | sw | sw \$t,C(\$s) | Memory[\$s + C] = \$t | Store word: Stores a value in register \$t to given address in memory. | | lui | lui \$t,C | \$t = C << 16 | Load upper immediate: Stores given immediate value (constant) C to upper part of register \$t. Register is 32 bits long and C is 16 bits. | \\ ==== Examples how to transcribe short fragments of C language code into assembler ==== ^ **//if//** command ^^ | if (i ==j) f = g + h; f = f – i; | // s0=f, s1=g, s2=h, s3=i, s4=j bne s3, s4, L1 // If i!=j, go to label L1 add s0, s1, s2 // if block: f=g+h L1: sub s0, s0, s3 // f = f-i | ^ **//if-else//** Command ^^ | if (i ==j) f = g + h; else f = f – i; | // s0=f, s1=g, s2=h, s3=i, s4=j bne s3, s4, else // If i!=j, go to else label add s0, s1, s2 // if block: f=g+h j L2 // jump behind the else block to L2 else: sub s0, s0, s3 // else block: f = f-i L2: | ^ **//while//** Cycle ^^ | int pow = 1; int x = 0; while(pow != 128) { pow = pow*2; x = x + 1; } | // s0=pow, s1=x addi s0, $0, 1 // pow = 1 addi s1, $0, 0 // x = 0 addi t0, $0, 128 // t0 = 128 pro porovnávání while: beq s0, t0, done // compare pow with value 128 in t0 (always have to compare two registers) sll s0, s0, 1 // pow = pow*2 addi s1, s1, 1 // x = x+1 j while done: | ^ **//for//** Cycle ^^ | int sum = 0; for(int i=0; i!=10; i++) { sum = sum + i; } | // Is equivalent to following while cycle:: int sum = 0; int i = 0; while(i!=10){ sum = sum + i; i++; } | ^ Read values from the data memory. ^^ | // // Just as an example... int a, *pa=0x80020040; int b, *pb=0x80020044; int c, *pc=0x00001234; a = *pa; b = *pb; c = *pc; | // s0=pa (Base address), s1=a, s2=b, s3=c lui s0, 0x8002 // pa = 0x80020000; lw s1, 0x40(s0) // a = *pa; lw s2, 0x44(s0) // b = *pb; addi s0, $0, 0x1234 // pc = 0x00001234; lw s3, 0x0(s0) // c = *pc; | \\