mirror of
https://github.com/badvision/jace.git
synced 2024-12-27 04:29:35 +00:00
refactor(extract class): CPU.java
This commit is contained in:
parent
200660f04d
commit
b28ad184e7
@ -1,46 +1,38 @@
|
||||
/**
|
||||
* Copyright 2024 Brendan Robert
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
package jace.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import jace.config.ConfigurableField;
|
||||
|
||||
/**
|
||||
* CPU is a vague abstraction of a CPU. It is defined as something which can be
|
||||
* debugged or traced. It has a program counter which can be incremented or
|
||||
* change. Most importantly, it is a device which does something on every clock tick.
|
||||
* changed. Most importantly, it is a device which does something on every clock tick.
|
||||
* Subclasses should implement "executeOpcode" rather than override the tick method.
|
||||
* Created on January 4, 2007, 7:27 PM
|
||||
*
|
||||
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
||||
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
||||
*/
|
||||
public abstract class CPU extends Device {
|
||||
private static final Logger LOG = Logger.getLogger(CPU.class.getName());
|
||||
private Debugger debugger = null;
|
||||
|
||||
@ConfigurableField(name = "Enable trace to STDOUT", shortName = "trace")
|
||||
public boolean trace = false;
|
||||
|
||||
@ConfigurableField(name = "Trace length", shortName = "traceSize", description = "Number of most recent trace lines to keep for debugging errors. Zero == disabled")
|
||||
public int traceLength = 0;
|
||||
|
||||
private final TraceLog traceLog;
|
||||
|
||||
public CPU() {
|
||||
traceLog = new TraceLog();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortName() {
|
||||
return "cpu";
|
||||
}
|
||||
private Debugger debugger = null;
|
||||
@ConfigurableField(name = "Enable trace to STDOUT", shortName = "trace")
|
||||
public boolean trace = false;
|
||||
|
||||
public boolean isTraceEnabled() {
|
||||
return trace;
|
||||
@ -49,33 +41,22 @@ public abstract class CPU extends Device {
|
||||
public void setTraceEnabled(boolean t) {
|
||||
trace = t;
|
||||
}
|
||||
@ConfigurableField(name = "Trace length", shortName = "traceSize", description = "Number of most recent trace lines to keep for debugging errors. Zero == disabled")
|
||||
public int traceLength = 0;
|
||||
private ArrayList<String> traceLog = new ArrayList<>();
|
||||
|
||||
public boolean isLogEnabled() {
|
||||
return (traceLength > 0);
|
||||
}
|
||||
|
||||
public void log(String line) {
|
||||
if (!isLogEnabled()) {
|
||||
return;
|
||||
if (isLogEnabled()) {
|
||||
traceLog.log(line, traceLength);
|
||||
}
|
||||
while (traceLog.size() >= traceLength) {
|
||||
traceLog.remove(0);
|
||||
}
|
||||
traceLog.add(line);
|
||||
}
|
||||
|
||||
|
||||
public void dumpTrace() {
|
||||
whileSuspended(()->{
|
||||
ArrayList<String> newLog = new ArrayList<>();
|
||||
ArrayList<String> oldLog = traceLog;
|
||||
traceLog = newLog;
|
||||
whileSuspended(() -> {
|
||||
LOG.log(Level.INFO, "Most recent {0} instructions:", traceLength);
|
||||
oldLog.forEach(LOG::info);
|
||||
oldLog.clear();
|
||||
});
|
||||
traceLog.dumpAndClear(LOG);
|
||||
});
|
||||
}
|
||||
|
||||
public void setDebug(Debugger d) {
|
||||
@ -87,6 +68,7 @@ public abstract class CPU extends Device {
|
||||
debugger = null;
|
||||
resume();
|
||||
}
|
||||
|
||||
//@ConfigurableField(name="Program Counter")
|
||||
public int programCounter = 0;
|
||||
|
||||
@ -112,16 +94,13 @@ public abstract class CPU extends Device {
|
||||
try {
|
||||
if (debugger != null) {
|
||||
if (!debugger.isActive() && debugger.hasBreakpoints()) {
|
||||
if (debugger.getBreakpoints().contains(getProgramCounter())){
|
||||
if (debugger.getBreakpoints().contains(getProgramCounter())) {
|
||||
debugger.setActive(true);
|
||||
}
|
||||
}
|
||||
if (debugger.isActive()) {
|
||||
debugger.updateStatus();
|
||||
if (!debugger.takeStep()) {
|
||||
// If the debugger is active and we aren't ready for the next step, sleep and exit
|
||||
// Without the sleep, this would constitute a very rapid-fire loop and would eat
|
||||
// an unnecessary amount of CPU.
|
||||
Thread.onSpinWait();
|
||||
return;
|
||||
}
|
||||
@ -132,10 +111,6 @@ public abstract class CPU extends Device {
|
||||
}
|
||||
executeOpcode();
|
||||
}
|
||||
/*
|
||||
* Execute the current opcode at the current program counter
|
||||
*@return number of cycles to wait until next command can be executed
|
||||
*/
|
||||
|
||||
protected abstract void executeOpcode();
|
||||
|
||||
@ -153,19 +128,23 @@ public abstract class CPU extends Device {
|
||||
|
||||
boolean singleTraceEnabled = false;
|
||||
public String lastTrace = "START";
|
||||
|
||||
public void performSingleTrace() {
|
||||
singleTraceEnabled = true;
|
||||
}
|
||||
|
||||
public boolean isSingleTraceEnabled() {
|
||||
return singleTraceEnabled;
|
||||
}
|
||||
|
||||
public String getLastTrace() {
|
||||
return lastTrace;
|
||||
}
|
||||
|
||||
public void captureSingleTrace(String trace) {
|
||||
lastTrace = trace;
|
||||
singleTraceEnabled = false;
|
||||
}
|
||||
|
||||
abstract public void clearState();
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public class Media {
|
||||
try (InputStream oggStream = getClass().getResourceAsStream(resourcePath)) {
|
||||
oggFile = oggStream.readAllBytes();
|
||||
}
|
||||
|
||||
|
||||
ByteBuffer oggBuffer = null;
|
||||
STBVorbisInfo info = null;
|
||||
ShortBuffer tempSampleBuffer = null;
|
||||
@ -97,7 +97,7 @@ public class Media {
|
||||
return "VORBIS_seek_without_length";
|
||||
case STBVorbis.VORBIS_unexpected_eof:
|
||||
return "VORBIS_unexpected_eof";
|
||||
case STBVorbis.VORBIS_seek_invalid:
|
||||
case STBVorbis.VORBIS_seek_invalid:
|
||||
return "VORBIS_seek_invalid";
|
||||
case STBVorbis.VORBIS_invalid_setup:
|
||||
return "VORBIS_invalid_setup";
|
||||
@ -175,7 +175,7 @@ public class Media {
|
||||
|
||||
public float getTotalDuration() {
|
||||
return totalDuration;
|
||||
}
|
||||
}
|
||||
|
||||
public int getTotalSamples() {
|
||||
return totalSamples;
|
||||
|
30
src/main/java/jace/core/TraceLog.java
Normal file
30
src/main/java/jace/core/TraceLog.java
Normal file
@ -0,0 +1,30 @@
|
||||
package jace.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* TraceLog manages the trace log functionality for recording recent instructions or events.
|
||||
* It is used in conjunction with the CPU class to provide traceable debugging output.
|
||||
*/
|
||||
public class TraceLog {
|
||||
private ArrayList<String> logEntries;
|
||||
|
||||
public TraceLog() {
|
||||
this.logEntries = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void log(String line, int maxEntries) {
|
||||
while (logEntries.size() >= maxEntries) {
|
||||
logEntries.remove(0);
|
||||
}
|
||||
logEntries.add(line);
|
||||
}
|
||||
|
||||
public void dumpAndClear(Logger logger) {
|
||||
ArrayList<String> oldLog = logEntries;
|
||||
logEntries = new ArrayList<>();
|
||||
oldLog.forEach(logger::info);
|
||||
oldLog.clear();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user