mirror of
https://github.com/simon987/Much-Assembly-Required.git
synced 2025-04-24 13:05:51 +00:00
CPU execution time costs energy #16
This commit is contained in:
parent
8701007ad9
commit
c703dec3cf
@ -29,6 +29,8 @@ public class GameServer implements Runnable {
|
|||||||
|
|
||||||
private SocketServer socketServer;
|
private SocketServer socketServer;
|
||||||
|
|
||||||
|
private int maxExecutionTime;
|
||||||
|
|
||||||
public GameServer() {
|
public GameServer() {
|
||||||
|
|
||||||
this.config = new ServerConfiguration(new File("config.properties"));
|
this.config = new ServerConfiguration(new File("config.properties"));
|
||||||
@ -36,6 +38,8 @@ public class GameServer implements Runnable {
|
|||||||
gameUniverse = new GameUniverse(config);
|
gameUniverse = new GameUniverse(config);
|
||||||
pluginManager = new PluginManager();
|
pluginManager = new PluginManager();
|
||||||
|
|
||||||
|
maxExecutionTime = config.getInt("user_timeout");
|
||||||
|
|
||||||
//Load all plugins in plugins folder, if it doesn't exist, create it
|
//Load all plugins in plugins folder, if it doesn't exist, create it
|
||||||
File pluginDir = new File("plugins/");
|
File pluginDir = new File("plugins/");
|
||||||
File[] pluginDirListing = pluginDir.listFiles();
|
File[] pluginDirListing = pluginDir.listFiles();
|
||||||
@ -109,8 +113,13 @@ public class GameServer implements Runnable {
|
|||||||
|
|
||||||
if(user.getCpu() != null){
|
if(user.getCpu() != null){
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
int timeout = Math.min(user.getControlledUnit().getEnergy(), maxExecutionTime);
|
||||||
|
|
||||||
user.getCpu().reset();
|
user.getCpu().reset();
|
||||||
user.getCpu().execute();
|
int cost = user.getCpu().execute(timeout);
|
||||||
|
user.getControlledUnit().spendEnergy(cost);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogManager.LOGGER.severe("Error executing " + user.getUsername() + "'s code");
|
LogManager.LOGGER.severe("Error executing " + user.getUsername() + "'s code");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -253,6 +253,8 @@ public class Assembler {
|
|||||||
|
|
||||||
} else if (tokens[0].toUpperCase().equals(".DATA")) {
|
} else if (tokens[0].toUpperCase().equals(".DATA")) {
|
||||||
|
|
||||||
|
LogManager.LOGGER.fine("DEBUG: .data @" + currentLine);
|
||||||
|
|
||||||
result.defineSegment(Segment.DATA, currentLine, currentOffset);
|
result.defineSegment(Segment.DATA, currentLine, currentOffset);
|
||||||
throw new PseudoInstructionException(currentLine);
|
throw new PseudoInstructionException(currentLine);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package net.simon987.server.assembly;
|
|||||||
import net.simon987.server.ServerConfiguration;
|
import net.simon987.server.ServerConfiguration;
|
||||||
import net.simon987.server.assembly.exception.AssemblyException;
|
import net.simon987.server.assembly.exception.AssemblyException;
|
||||||
import net.simon987.server.assembly.exception.DuplicateSegmentException;
|
import net.simon987.server.assembly.exception.DuplicateSegmentException;
|
||||||
|
import net.simon987.server.logging.LogManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -29,7 +30,7 @@ public class AssemblyResult {
|
|||||||
/**
|
/**
|
||||||
* Offset of the code segment
|
* Offset of the code segment
|
||||||
*/
|
*/
|
||||||
private int codeSegmentOffset;
|
public int codeSegmentOffset;
|
||||||
/**
|
/**
|
||||||
* Line of the code segment definition (for editor icons)
|
* Line of the code segment definition (for editor icons)
|
||||||
*/
|
*/
|
||||||
@ -77,6 +78,10 @@ public class AssemblyResult {
|
|||||||
if (!codeSegmentSet) {
|
if (!codeSegmentSet) {
|
||||||
codeSegmentOffset = origin + currentOffset;
|
codeSegmentOffset = origin + currentOffset;
|
||||||
codeSegmentLine = currentLine;
|
codeSegmentLine = currentLine;
|
||||||
|
|
||||||
|
LogManager.LOGGER.fine("DEBUG: .text offset @" + codeSegmentOffset);
|
||||||
|
|
||||||
|
|
||||||
codeSegmentSet = true;
|
codeSegmentSet = true;
|
||||||
} else {
|
} else {
|
||||||
throw new DuplicateSegmentException(currentLine);
|
throw new DuplicateSegmentException(currentLine);
|
||||||
@ -87,6 +92,9 @@ public class AssemblyResult {
|
|||||||
if (!dataSegmentSet) {
|
if (!dataSegmentSet) {
|
||||||
dataSegmentOffset = origin + currentOffset;
|
dataSegmentOffset = origin + currentOffset;
|
||||||
dataSegmentLine = currentLine;
|
dataSegmentLine = currentLine;
|
||||||
|
|
||||||
|
LogManager.LOGGER.fine("DEBUG: .data offset @" + dataSegmentOffset);
|
||||||
|
|
||||||
dataSegmentSet = true;
|
dataSegmentSet = true;
|
||||||
} else {
|
} else {
|
||||||
throw new DuplicateSegmentException(currentLine);
|
throw new DuplicateSegmentException(currentLine);
|
||||||
|
@ -60,10 +60,11 @@ public class CPU implements JSONSerialisable{
|
|||||||
|
|
||||||
private ServerConfiguration config;
|
private ServerConfiguration config;
|
||||||
|
|
||||||
private long timeout;
|
|
||||||
|
|
||||||
private int registerSetSize;
|
private int registerSetSize;
|
||||||
|
|
||||||
|
private static final char EXECUTION_COST_ADDR = 0x0300;
|
||||||
|
private static final char EXECUTED_INS_ADDR = 0x0301;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new CPU
|
* Creates a new CPU
|
||||||
*/
|
*/
|
||||||
@ -74,8 +75,6 @@ public class CPU implements JSONSerialisable{
|
|||||||
attachedHardware = new HashMap<>();
|
attachedHardware = new HashMap<>();
|
||||||
codeSegmentOffset = config.getInt("org_offset");
|
codeSegmentOffset = config.getInt("org_offset");
|
||||||
|
|
||||||
timeout = config.getInt("user_timeout");
|
|
||||||
|
|
||||||
instructionSet.add(new JmpInstruction(this));
|
instructionSet.add(new JmpInstruction(this));
|
||||||
instructionSet.add(new JnzInstruction(this));
|
instructionSet.add(new JnzInstruction(this));
|
||||||
instructionSet.add(new JzInstruction(this));
|
instructionSet.add(new JzInstruction(this));
|
||||||
@ -116,7 +115,7 @@ public class CPU implements JSONSerialisable{
|
|||||||
ip = codeSegmentOffset;
|
ip = codeSegmentOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void execute() {
|
public int execute(int timeout) {
|
||||||
|
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
@ -128,10 +127,16 @@ public class CPU implements JSONSerialisable{
|
|||||||
while (!status.isBreakFlag()) {
|
while (!status.isBreakFlag()) {
|
||||||
counter++;
|
counter++;
|
||||||
|
|
||||||
if(counter % 1000 == 0){
|
if (counter % 10000 == 0) {
|
||||||
if (System.currentTimeMillis() >= (startTime + timeout)) {
|
if (System.currentTimeMillis() >= (startTime + timeout)) {
|
||||||
LogManager.LOGGER.fine("CPU Timeout " + this + " after " + counter + "instructions (" + timeout + "ms): " + (double) counter / ((double) timeout / 1000) / 1000000 + "MHz");
|
LogManager.LOGGER.fine("CPU Timeout " + this + " after " + counter + "instructions (" + timeout + "ms): " + (double) counter / ((double) timeout / 1000) / 1000000 + "MHz");
|
||||||
return;
|
|
||||||
|
//Write execution cost and instruction count to memory
|
||||||
|
memory.set(EXECUTION_COST_ADDR, timeout);
|
||||||
|
memory.set(EXECUTED_INS_ADDR, Util.getHigherWord(counter));
|
||||||
|
memory.set(EXECUTED_INS_ADDR, Util.getLowerWord(counter));
|
||||||
|
|
||||||
|
return timeout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,8 +156,17 @@ public class CPU implements JSONSerialisable{
|
|||||||
executeInstruction(instruction, source, destination);
|
executeInstruction(instruction, source, destination);
|
||||||
// LogManager.LOGGER.info(instruction.getMnemonic());
|
// LogManager.LOGGER.info(instruction.getMnemonic());
|
||||||
}
|
}
|
||||||
double elapsed = (System.currentTimeMillis() - startTime);
|
int elapsed = (int) (System.currentTimeMillis() - startTime);
|
||||||
|
|
||||||
LogManager.LOGGER.fine(counter + " instruction in " + elapsed + "ms : " + (double) counter / (elapsed / 1000) / 1000000 + "MHz");
|
LogManager.LOGGER.fine(counter + " instruction in " + elapsed + "ms : " + (double) counter / (elapsed / 1000) / 1000000 + "MHz");
|
||||||
|
|
||||||
|
|
||||||
|
//Write execution cost and instruction count to memory
|
||||||
|
memory.set(EXECUTION_COST_ADDR, elapsed);
|
||||||
|
memory.set(EXECUTED_INS_ADDR, Util.getHigherWord(counter));
|
||||||
|
memory.set(EXECUTED_INS_ADDR, Util.getLowerWord(counter));
|
||||||
|
|
||||||
|
return elapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void executeInstruction(Instruction instruction, int source, int destination) {
|
public void executeInstruction(Instruction instruction, int source, int destination) {
|
||||||
|
@ -42,14 +42,14 @@ public class Memory implements Target, JSONSerialisable {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int get(int address) {
|
public int get(int address) {
|
||||||
address = (char)address * 2; //Because our Memory is only divisible by 16bits
|
address = address * 2; //Because our Memory is only divisible by 16bits
|
||||||
|
|
||||||
if (address < 0 || address + 2 > bytes.length) {
|
if (address + 2 > bytes.length) {
|
||||||
LogManager.LOGGER.info("DEBUG: Trying to get memory out of bounds " + address);
|
LogManager.LOGGER.info("DEBUG: Trying to get memory out of bounds " + address);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (((bytes[address] & 0xFF) << 8) | (bytes[address + 1] & 0xFF));
|
return ((bytes[address] & 0xFF) << 8) | (bytes[address + 1] & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,7 +60,7 @@ public class Memory implements Target, JSONSerialisable {
|
|||||||
offset = (char)offset * 2;
|
offset = (char)offset * 2;
|
||||||
|
|
||||||
|
|
||||||
if (offset + count > this.bytes.length || count < 0 || offset < 0 || srcOffset >= bytes.length) {
|
if (offset + count > this.bytes.length || srcOffset >= bytes.length || count < 0 || offset < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,12 +80,12 @@ public class Memory implements Target, JSONSerialisable {
|
|||||||
address = (char)address * 2;
|
address = (char)address * 2;
|
||||||
|
|
||||||
|
|
||||||
if (address < 0 || address + 2 > bytes.length) {
|
if (address + 2 > bytes.length) {
|
||||||
LogManager.LOGGER.info("DEBUG: Trying to set memory out of bounds: " + address);
|
LogManager.LOGGER.info("DEBUG: Trying to set memory out of bounds: " + address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes[address] = (byte) ((value >> 8) & 0xFF);
|
bytes[address] = (byte) ((value >> 8));
|
||||||
bytes[address + 1] = (byte) (value & 0xFF);
|
bytes[address + 1] = (byte) (value & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,4 +17,8 @@ public interface ControllableUnit {
|
|||||||
|
|
||||||
Memory getFloppyData();
|
Memory getFloppyData();
|
||||||
|
|
||||||
|
boolean spendEnergy(int energy);
|
||||||
|
|
||||||
|
int getEnergy();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ public class GameUniverse implements JSONSerialisable{
|
|||||||
|
|
||||||
//Write assembled code to mem
|
//Write assembled code to mem
|
||||||
user.getCpu().getMemory().write((short) ar.origin, ar.bytes, 0, ar.bytes.length);
|
user.getCpu().getMemory().write((short) ar.origin, ar.bytes, 0, ar.bytes.length);
|
||||||
user.getCpu().setCodeSegmentOffset(ar.origin);
|
user.getCpu().setCodeSegmentOffset(ar.codeSegmentOffset);
|
||||||
|
|
||||||
//Init
|
//Init
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ public class CodeUploadHandler implements MessageHandler {
|
|||||||
|
|
||||||
//Write assembled code to mem
|
//Write assembled code to mem
|
||||||
user.getUser().getCpu().getMemory().write((char) ar.origin, ar.bytes, 0, ar.bytes.length);
|
user.getUser().getCpu().getMemory().write((char) ar.origin, ar.bytes, 0, ar.bytes.length);
|
||||||
user.getUser().getCpu().setCodeSegmentOffset(ar.origin);
|
user.getUser().getCpu().setCodeSegmentOffset(ar.codeSegmentOffset);
|
||||||
|
|
||||||
JSONObject response = new JSONObject();
|
JSONObject response = new JSONObject();
|
||||||
response.put("t", "codeResponse");
|
response.put("t", "codeResponse");
|
||||||
|
@ -60,4 +60,6 @@ wg_minCopperCount=0
|
|||||||
wg_maxCopperCount=2
|
wg_maxCopperCount=2
|
||||||
# ----------------------------------------------
|
# ----------------------------------------------
|
||||||
# Maximum execution time of user code in ms
|
# Maximum execution time of user code in ms
|
||||||
user_timeout=40
|
user_timeout=500
|
||||||
|
# Free CPU execution time in ms
|
||||||
|
user_free_execution_time=2
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user