-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
942fb96
commit 99066f6
Showing
11 changed files
with
348 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.vscode/launch.json | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module github.com/alabarjasteh/mips-simulator | ||
|
||
go 1.16 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/alabarjasteh/mips-simulator/mips" | ||
) | ||
|
||
type Instruction int64 | ||
|
||
func main() { | ||
mem := mips.NewMemory() | ||
cpu := mips.NewCPU(mem) | ||
|
||
for { | ||
_, instData := cpu.Fetch() | ||
instruction, err := cpu.Decode(instData) | ||
if err != nil { | ||
fmt.Printf("error: %v", err) | ||
return | ||
} | ||
err = cpu.Execute(instruction) | ||
if err != nil { | ||
fmt.Printf("error: %v", err) | ||
return | ||
} | ||
} | ||
} | ||
|
||
// func fetchBurst(pc *int, mem *memory.Mem, reg *register.IfDec) { | ||
// inst, err := mem.FetchInstruction(*pc) | ||
// if err != nil { | ||
// log.Fatal(err) | ||
// } | ||
// reg.IR = inst | ||
// log.Printf("IR : %v", reg.IR) | ||
// *pc += 4 | ||
// reg.NPC = *pc | ||
// } | ||
|
||
// func decodeBurst(rf *register.File, ifDec *register.IfDec, decEx *register.DecEx) { | ||
// r1, r2 := getReadingRegisters(rf, ifDec.IR) | ||
// imm := extractImmediate(ifDec.IR) | ||
// decEx.IR = ifDec.IR | ||
// decEx.NPC = ifDec.NPC | ||
// decEx.R1 = r1 | ||
// decEx.R2 = r2 | ||
// decEx.Imm = imm | ||
// } | ||
|
||
// func executeBurst() { | ||
|
||
// } | ||
|
||
// func memoryBurst() {} | ||
// func writebackBurst() {} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
10001100000000010000000000010000 | ||
10001100000000100000000000010100 | ||
00000000001000100001100000100000 | ||
10101100000000110000000000011000 | ||
00000000000000000000000000000001 | ||
00000000000000000000000000000011 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package mips | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
) | ||
|
||
type CPU struct { | ||
PC int | ||
Memory Memory | ||
RegFile [32]int32 | ||
} | ||
|
||
func NewCPU(mem Memory) *CPU { | ||
return &CPU{ | ||
PC: 0, | ||
RegFile: [32]int32{}, | ||
Memory: mem, | ||
} | ||
} | ||
|
||
func (cpu *CPU) Fetch() (npc int, instData int) { | ||
ins := cpu.Memory[cpu.PC] | ||
fmt.Printf("instruction: %b\n", ins) | ||
cpu.PC += 4 | ||
npc = cpu.PC | ||
return npc, ins | ||
} | ||
|
||
func (cpu *CPU) Decode(insData int) (*Instruction, error) { | ||
fmt.Printf("inst: %b\n", insData) | ||
opcode := insData >> 26 | ||
fmt.Printf("opcode: %b\n", opcode) | ||
opcodeType, err := getOpcodeType(opcode) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
ins := &Instruction{} | ||
ins.Opcode = opcode | ||
ins.OpcodeType = opcodeType | ||
|
||
switch opcodeType { | ||
case OpcodeTypeR: | ||
insTypeR := &InstructionTypeR{} | ||
insTypeR.FuncCode = insData & 0b111111 | ||
insTypeR.DestinationRegister = (insData >> 11) & 0b11111 | ||
insTypeR.TargetRegister = (insData >> 16) & 0b11111 | ||
insTypeR.SourceRegister = (insData >> 21) & 0b11111 | ||
f, ok := FunctionTypeRMap[insTypeR.FuncCode] | ||
if !ok { | ||
return nil, errors.New("unsupported funcCode") | ||
} | ||
insTypeR.Function = f | ||
|
||
ins.TypeR = insTypeR | ||
case OpcodeTypeI: | ||
insTypeI := &InstructionTypeI{} | ||
insTypeI.Immediate = insData & 0xFFFF | ||
insTypeI.TargetRegister = (insData >> 16) & 0b11111 | ||
insTypeI.SourceRegister = (insData >> 21) & 0b11111 | ||
f, ok := FunctionTypeIMap[opcode] | ||
if !ok { | ||
return nil, errors.New("unsupported opcode") | ||
} | ||
insTypeI.Function = f | ||
|
||
ins.TypeI = insTypeI | ||
} | ||
|
||
return ins, nil | ||
} | ||
|
||
func (cpu *CPU) Execute(ins *Instruction) error { | ||
var err error | ||
switch ins.OpcodeType { | ||
case OpcodeTypeR: | ||
r := ins.TypeR | ||
err = r.Function(cpu, r.SourceRegister, r.TargetRegister, r.DestinationRegister) | ||
case OpcodeTypeI: | ||
i := ins.TypeI | ||
err = i.Function(cpu, i.SourceRegister, i.TargetRegister, i.Immediate) | ||
} | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package mips | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
) | ||
|
||
// R Type Instructions | ||
type FunctionTypeR func(cpu *CPU, rs int, rt int, rd int) error | ||
|
||
func Add(cpu *CPU, rs int, rt int, rd int) error { | ||
|
||
cpu.RegFile[rd] = cpu.RegFile[rs] + cpu.RegFile[rt] | ||
|
||
return nil | ||
} | ||
|
||
func And(cpu *CPU, rs int, rt int, rd int) error { | ||
fmt.Printf("(\"and\" not implemented)\n") | ||
return errors.New("not implemented: and") | ||
} | ||
|
||
func Slt(cpu *CPU, rs int, rt int, rd int) error { | ||
fmt.Printf("(\"slt\" not implemented)\n") | ||
return errors.New("not implemented: slt") | ||
} | ||
|
||
func Sub(cpu *CPU, rs int, rt int, rd int) error { | ||
fmt.Printf("(\"sub\" not implemented)\n") | ||
return errors.New("not implemented: sub") | ||
} | ||
|
||
func Or(cpu *CPU, rs int, rt int, rd int) error { | ||
|
||
cpu.RegFile[rd] = cpu.RegFile[rs] | cpu.RegFile[rt] | ||
|
||
return nil | ||
} | ||
|
||
// I Type Instruction | ||
type FunctionTypeI func(cpu *CPU, rs int, rt int, imm int) error | ||
|
||
func Addi(cpu *CPU, rs int, rt int, imm int) error { | ||
|
||
cpu.RegFile[rt] = cpu.RegFile[rs] + int32(int16(imm)) | ||
|
||
return nil | ||
} | ||
|
||
func Andi(cpu *CPU, rs int, rt int, imm int) error { | ||
fmt.Printf("(\"andi\" not implemented)\n") | ||
return errors.New("not implemented: andi") | ||
} | ||
|
||
func Lw(cpu *CPU, rs int, rt int, imm int) error { | ||
|
||
value := int32(cpu.Memory[int(int16(imm))+int(cpu.RegFile[rs])]) | ||
cpu.RegFile[rt] = value | ||
|
||
return nil | ||
} | ||
|
||
func Ori(cpu *CPU, rs int, rt int, imm int) error { | ||
fmt.Printf("(\"ori\" not implemented)\n") | ||
return errors.New("not implemented: ori") | ||
} | ||
|
||
func Slti(cpu *CPU, rs int, rt int, imm int) error { | ||
|
||
if cpu.RegFile[rs] < int32(int16(imm)) { | ||
cpu.RegFile[rt] = 1 | ||
} else { | ||
cpu.RegFile[rt] = 0 | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func Sw(cpu *CPU, rs int, rt int, imm int) error { | ||
|
||
cpu.Memory[int(int16(imm))+int(cpu.RegFile[rs])] = int(cpu.RegFile[rt]) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package mips | ||
|
||
var FunctionTypeRMap = map[int]FunctionTypeR{ | ||
0b100000: Add, | ||
0b100010: Sub, | ||
0b100101: Or, | ||
0b100100: And, | ||
0b101010: Slt, | ||
} | ||
|
||
var FunctionTypeIMap = map[int]FunctionTypeI{ | ||
0b101011: Sw, | ||
0b100011: Lw, | ||
0b001000: Addi, | ||
0b001010: Slti, | ||
0b001100: Andi, | ||
0b001101: Ori, | ||
} | ||
|
||
type Instruction struct { | ||
Opcode int | ||
OpcodeType OpcodeType | ||
TypeR *InstructionTypeR | ||
TypeI *InstructionTypeI | ||
} | ||
|
||
type InstructionTypeR struct { | ||
SourceRegister int | ||
TargetRegister int | ||
DestinationRegister int | ||
FuncCode int | ||
|
||
Function func(cpu *CPU, rs int, rt int, rd int) error | ||
} | ||
|
||
type InstructionTypeI struct { | ||
SourceRegister int | ||
TargetRegister int | ||
Immediate int | ||
|
||
Function func(cpu *CPU, rs int, rt int, imm int) error | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package mips | ||
|
||
import ( | ||
"bufio" | ||
"fmt" | ||
"log" | ||
"os" | ||
"strconv" | ||
) | ||
|
||
type Memory map[int]int // map[PC]Data | ||
|
||
func NewMemory() Memory { | ||
mem := Memory{} | ||
mem.loadMemoryFromFile() | ||
return mem | ||
} | ||
|
||
func (mem Memory) loadMemoryFromFile() { | ||
file, err := os.Open("./memory_state1.txt") | ||
if err != nil { | ||
log.Fatalf("failed to open") | ||
|
||
} | ||
defer file.Close() | ||
scanner := bufio.NewScanner(file) | ||
i := 0 | ||
for scanner.Scan() { | ||
val, err := strconv.ParseInt(scanner.Text(), 2, 64) | ||
if err != nil { | ||
log.Fatal("cannot parse memory state from file") | ||
} | ||
mem[i] = int(val) | ||
fmt.Printf("mem: %b\n", mem[i]) | ||
i += 4 | ||
} | ||
if err := scanner.Err(); err != nil { | ||
log.Fatal(err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package mips | ||
|
||
import "errors" | ||
|
||
type OpcodeType byte | ||
|
||
var ErrInvalidOpcode = errors.New("invalid opcode") | ||
|
||
const ( | ||
OpcodeTypeInvalid OpcodeType = iota | ||
OpcodeTypeR | ||
OpcodeTypeI | ||
) | ||
|
||
func getOpcodeType(opcode int) (OpcodeType, error) { | ||
if opcode == 0 { | ||
return OpcodeTypeR, nil | ||
} | ||
if _, ok := FunctionTypeIMap[opcode]; ok { | ||
return OpcodeTypeI, nil | ||
} | ||
return OpcodeTypeInvalid, ErrInvalidOpcode | ||
} |