refactor(extract class): CPU.java

This commit is contained in:
Vaibhavkumar Patel 2024-11-29 13:52:36 -04:00
parent 200660f04d
commit b28ad184e7
3 changed files with 61 additions and 52 deletions

View File

@ -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();
}
}

View File

@ -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;

View 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();
}
}