Compare commits

..

2 commits

Author SHA1 Message Date
Imbus
422344097b Word abstract -> interface 2024-04-21 22:26:03 +02:00
Imbus
1bdb35a899 Instruction abstract -> interface 2024-04-21 22:17:49 +02:00
20 changed files with 72 additions and 168 deletions

22
.gitignore vendored
View file

@ -1,4 +1,3 @@
.vscode
.gradle .gradle
**/build/ **/build/
!src/**/build/ !src/**/build/
@ -20,24 +19,3 @@ gradle-app.setting
.project .project
# JDT-specific (Eclipse Java Development Tools) # JDT-specific (Eclipse Java Development Tools)
.classpath .classpath
# Compiled class file
*.class
# Log file
*.log
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
*.minisig
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*

View file

@ -52,17 +52,14 @@ classDiagram
Computer --> ProgramCounter Computer --> ProgramCounter
Program <-- ArrayList Program <-- ArrayList
Program : +toString() Program : +toString()
Memory --|> LongMemory Memory <|-- LongMemory
Word --|> LongWord Word <|-- LongWord
``` ```
```mermaid ```mermaid
classDiagram classDiagram
class Operand {
+ Word getValue()
}
class Instruction { class Instruction {
+ void execute(Memory memory, ProgramCounter pc) + void execute(Memory memory, ProgramCounter pc)
# String opcode() # String opcode()
@ -76,9 +73,8 @@ classDiagram
class JumpEq class JumpEq
class Mul class Mul
class Print class Print
Instruction *-- Operand Instruction --|> Word
Operand <|-- Word Instruction --|> Address
Operand <|-- Address
Add --|> Instruction Add --|> Instruction
Copy --|> Instruction Copy --|> Instruction
Halt --|> Instruction Halt --|> Instruction

View file

@ -1,6 +1,6 @@
package hatelace; package hatelace;
public class Address implements Operand { public class Address {
int address; int address;
public Address(int address) { public Address(int address) {
@ -14,8 +14,4 @@ public class Address implements Operand {
public String toString() { public String toString() {
return Integer.toString(address); return Integer.toString(address);
} }
public Word getWord(Memory memory) {
return memory.read(this);
}
} }

View file

@ -1,11 +1,8 @@
package hatelace; package hatelace;
public abstract class Instruction { public interface Instruction {
public abstract void execute(Memory memory, ProgramCounter pc); void execute(Memory memory, ProgramCounter pc);
String opcode();
protected abstract String opcode(); Object[] operands();
String toString();
protected abstract Object[] operands();
public abstract String toString();
} }

View file

@ -1,5 +0,0 @@
package hatelace;
public interface Operand {
Word getWord(Memory memory);
}

View file

@ -1,11 +1,11 @@
package hatelace; package hatelace;
public abstract class Word implements Operand { public interface Word {
public abstract <T> T getValue(); <T> T getValue();
public abstract Word add(Word other); Word add(Word other);
public abstract Word subtract(Word other); Word subtract(Word other);
public abstract Word multiply(Word other); Word multiply(Word other);
public abstract Word divide(Word other); Word divide(Word other);
public abstract String toString(); String toString();
public abstract boolean equals(Object other); boolean equals(Object other);
} }

View file

@ -2,31 +2,32 @@ package hatelace.instructions;
import hatelace.*; import hatelace.*;
public class Add extends Instruction { public class Add implements Instruction {
private Address src;
private Word imm;
private Address dest; private Address dest;
private Operand o1, o2;
/** Add immediate value to memory address. */ /** Add immediate value to memory address. */
public Add(Operand o1, Operand o2, Address dest) { public Add(Address src, Word imm, Address dest) {
this.o1 = o1; this.src = src;
this.o2 = o2; this.imm = imm;
this.dest = dest; this.dest = dest;
} }
public void execute(Memory memory, ProgramCounter PC) { public void execute(Memory memory, ProgramCounter PC) {
memory.write(this.dest, this.o1.getWord(memory).add(this.o2.getWord(memory))); memory.write(this.dest, memory.read(this.src).add(this.imm));
PC.incPC(); PC.incPC();
} }
protected String opcode() { public String opcode() {
return "ADD"; return "ADD";
} }
public String toString() { public String toString() {
return String.format("%s [%s] %s [%s]", this.opcode(), this.o1, this.o2, this.dest); return String.format("%s [%s] %s [%s]", this.opcode(), this.src, this.imm, this.dest);
} }
protected Object[] operands() { public Object[] operands() {
return new Object[] { this.o1, this.o2, this.dest }; return new Object[] { this.src, this.imm, this.dest };
} }
} }

View file

@ -2,30 +2,30 @@ package hatelace.instructions;
import hatelace.*; import hatelace.*;
public class Copy extends Instruction { public class Copy implements Instruction {
private Operand src; private Word imm;
private Address dest; private Address dest;
/** Copy immediate value to memory address. */ /** Copy immediate value to memory address. */
public Copy(Operand src, Address dest) { public Copy(Word imm, Address dest) {
this.src = src; this.imm = imm;
this.dest = dest; this.dest = dest;
} }
public void execute(Memory memory, ProgramCounter PC) { public void execute(Memory memory, ProgramCounter PC) {
memory.write(this.dest, this.src.getWord(memory)); memory.write(this.dest, this.imm);
PC.incPC(); PC.incPC();
} }
protected String opcode() { public String opcode() {
return "CPY"; return "CPY";
} }
protected Object[] operands() { public Object[] operands() {
return new Object[] {this.src, this.dest}; return new Object[] {this.imm, this.dest};
} }
public String toString() { public String toString() {
return String.format("%s %s [%s]", this.opcode(), this.src, this.dest); return String.format("%s %s [%s]", this.opcode(), this.imm, this.dest);
} }
} }

View file

@ -2,7 +2,7 @@ package hatelace.instructions;
import hatelace.*; import hatelace.*;
public class Halt extends Instruction { public class Halt implements Instruction {
/** Halts the CPU */ /** Halts the CPU */
public Halt(){}; public Halt(){};
@ -10,11 +10,11 @@ public class Halt extends Instruction {
PC.halt(); PC.halt();
} }
protected String opcode() { public String opcode() {
return "HLT"; return "HLT";
} }
protected Object[] operands() { public Object[] operands() {
return new Object[] {}; return new Object[] {};
} }

View file

@ -2,7 +2,7 @@ package hatelace.instructions;
import hatelace.*; import hatelace.*;
public class Jump extends Instruction { public class Jump implements Instruction {
private int index; private int index;
/** Unconditional jump, non-relative */ /** Unconditional jump, non-relative */
@ -14,11 +14,11 @@ public class Jump extends Instruction {
PC.setPC(this.index); PC.setPC(this.index);
} }
protected String opcode() { public String opcode() {
return "JMP"; return "JMP";
} }
protected Object[] operands() { public Object[] operands() {
return new Object[] {this.index}; return new Object[] {this.index};
} }

View file

@ -2,35 +2,35 @@ package hatelace.instructions;
import hatelace.*; import hatelace.*;
public class JumpEq extends Instruction { public class JumpEq implements Instruction {
private int index; private int index;
private Operand o1; private Address src;
private Operand o2; private Word imm;
/** Conditional jump */ /** Conditional jump */
public JumpEq(int index, Operand o1, Operand o2) { public JumpEq(int index, Address src, Word imm) {
this.index = index; this.index = index;
this.o1 = o1; this.src = src;
this.o2 = o2; this.imm = imm;
} }
public void execute(Memory memory, ProgramCounter PC) { public void execute(Memory memory, ProgramCounter PC) {
if (this.o1.getWord(memory).equals(this.o2.getWord(memory))) { if (this.imm.equals(memory.read(this.src))) {
PC.setPC(this.index); PC.setPC(this.index);
} else { } else {
PC.incPC(); PC.incPC();
} }
} }
protected String opcode() { public String opcode() {
return "JEQ"; return "JEQ";
} }
protected Object[] operands() { public Object[] operands() {
return new Object[] {this.index, this.o1, this.o2}; return new Object[] {this.index, this.src, this.imm};
} }
public String toString() { public String toString() {
return String.format("%s %s [%s] %s", this.opcode(), this.index, this.o1, this.o2); return String.format("%s %s [%s] %s", this.opcode(), this.index, this.src, this.imm);
} }
} }

View file

@ -2,32 +2,32 @@ package hatelace.instructions;
import hatelace.*; import hatelace.*;
public class Mul extends Instruction { public class Mul implements Instruction {
private Operand o1; private Address src1;
private Operand o2; private Address src2;
private Address dest; private Address dest;
/** Multiply contents of two addresses and store the result in a third memory address. */ /** Multiply contents of two addresses and store the result in a third memory address. */
public Mul(Operand o1, Operand o2, Address dest) { public Mul(Address src1, Address src2, Address dest) {
this.o1 = o1; this.src1 = src1;
this.o2 = o2; this.src2 = src2;
this.dest = dest; this.dest = dest;
} }
public void execute(Memory memory, ProgramCounter PC) { public void execute(Memory memory, ProgramCounter PC) {
memory.write(this.dest, this.o1.getWord(memory).multiply(this.o2.getWord(memory))); memory.write(this.dest, memory.read(this.src1).multiply(memory.read(this.src2)));
PC.incPC(); PC.incPC();
} }
protected String opcode() { public String opcode() {
return "MUL"; return "MUL";
} }
protected Object[] operands() { public Object[] operands() {
return new Object[] { this.o1, this.o2, this.dest }; return new Object[] { this.src1, this.src2, this.dest };
} }
public String toString() { public String toString() {
return String.format("%s [%s] [%s] [%s]", this.opcode(), this.o1, this.o2, this.dest); return String.format("%s [%s] [%s] [%s]", this.opcode(), this.src1, this.src2, this.dest);
} }
} }

View file

@ -2,7 +2,7 @@ package hatelace.instructions;
import hatelace.*; import hatelace.*;
public class Print extends Instruction { public class Print implements Instruction {
private Address address; private Address address;
/** Print content of memory address */ /** Print content of memory address */
@ -15,11 +15,11 @@ public class Print extends Instruction {
PC.incPC(); PC.incPC();
} }
protected String opcode() { public String opcode() {
return "PRT"; return "PRT";
} }
protected Object[] operands() { public Object[] operands() {
return new Object[] { this.address }; return new Object[] { this.address };
} }

View file

@ -1,9 +1,8 @@
package hatelace.memtypes; package hatelace.memtypes;
import hatelace.Memory;
import hatelace.Word; import hatelace.Word;
public class IntWord extends Word { public class IntWord implements Word {
private Integer value; private Integer value;
public IntWord(Integer value) { public IntWord(Integer value) {
@ -16,11 +15,6 @@ public class IntWord extends Word {
return value; return value;
} }
@Override
public Word getWord(Memory memory) {
return this;
}
public Word add(Word other) { public Word add(Word other) {
return new IntWord(value + (Integer) other.getValue()); return new IntWord(value + (Integer) other.getValue());
} }

View file

@ -1,9 +1,8 @@
package hatelace.memtypes; package hatelace.memtypes;
import hatelace.Memory;
import hatelace.Word; import hatelace.Word;
public class LongWord extends Word { public class LongWord implements Word {
private Long value; private Long value;
public LongWord(Long value) { public LongWord(Long value) {
@ -16,11 +15,6 @@ public class LongWord extends Word {
return value; return value;
} }
@Override
public Word getWord(Memory memory) {
return this;
}
public Word add(Word other) { public Word add(Word other) {
return new LongWord(value + (Long) other.getValue()); return new LongWord(value + (Long) other.getValue());
} }

View file

@ -1,15 +0,0 @@
1. En interface som alla typer av instruktioner kan ha gemensam borde inte vara helt fel. Vilket i sin tur betyder en klass för varje instruktion där ett instruktions interface implementeras.
2. Man ärver lämplig collection, ex arraylist. Detta är kass design, då komposition är tydligare.
3. "Program" och självaste "datorn" borde vara olika paket, paketet "program" rör program som skall köra på datorn, "datorn" har de klasser som är datorn som t.ex. memory och programCounter osv.
4. Varje instruktion skulle kunna representeras som ett kommando, och datorn skulle utföra dessa kommandon utan att behöva veta exakt vad varje instruktion innebär. På så sätt separeras ansvar, och det blir enklare att lägga till eller ändra instruktioner i framtiden.
5. Designmönstret Template Method kan vara användbart för att undvika duplicerad kod i likartade klasser, särskilt för de instruktionsklasser som ingår i programmet (t.ex. Copy, JumpEq, Mul, Add, Print, Halt). Eftersom dessa instruktionsklasser kan ha vissa gemensamma delar i hur de utför sin uppgift, kan ett template method-mönster användas för att abstrahera och återanvända gemensam kod.
6. För att hantera olika sorters operander på ett enhetligt sätt med hjälp av Strategy-mönstret i en datormodell skulle man kunna implementera olika strategier för hur operander ska hanteras. Operander kan vara antingen konstanter eller adresser, och olika instruktioner kräver olika typer av operander.
7. Additionen bör nog utföras i LongWord.
8.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 20 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 25 KiB

View file

@ -1,8 +1,3 @@
GITHASH := $(shell git rev-parse --short HEAD)$(shell git diff-index --quiet HEAD || echo "-dirty")
TARNAME := hatelace-imbus_$(GITHASH).tar.gz
DIRNAME := hatelace
run: run:
./gradlew run ./gradlew run
@ -11,35 +6,11 @@ watch:
build: build:
./gradlew build ./gradlew build
ls -lh app/build/libs/*.jar
clean: clean:
./gradlew clean ./gradlew clean
rm -f *.tar.gz *.tar.gz.minisig *.zip *.jpg
test: test:
./gradlew test ./gradlew test
$(TARNAME): .PHONY: run build clean
git archive --format=tar --prefix=$(DIRNAME)/ HEAD > intermediate.tar
tar -f intermediate.tar --delete $(DIRNAME)/doc
gzip -9 -c intermediate.tar > $(TARNAME)
rm intermediate.tar
$(TARNAME).minisig: $(TARNAME)
minisign -Sm $(TARNAME)
tar: $(TARNAME)
tar -tvf $(TARNAME)
sign: $(TARNAME).minisig
publish: $(TARNAME) $(TARNAME).minisig
@git diff-index --quiet HEAD || (echo "git is dirty, commit changes first"; exit 1)
ssh server mkdir -p /public/$(DIRNAME)
rsync -avz $(TARNAME).minisig server:/public/$(DIRNAME)/$(TARNAME).minisig
rsync -avz $(TARNAME) server:/public/$(DIRNAME)/$(TARNAME)
ssh server ln -sf /public/$(DIRNAME)/$(TARNAME).minisig /public/$(DIRNAME)/latest.tar.gz.minisig
ssh server ln -sf /public/$(DIRNAME)/$(TARNAME) /public/$(DIRNAME)/latest.tar.gz
.PHONY: run watch build clean test archive sign publish