From b0bfa13e366aef0b4451be5d97cd22610860309f Mon Sep 17 00:00:00 2001 From: maziac Date: Mon, 23 Mar 2020 17:21:16 +0100 Subject: [PATCH] ZEsarUX: automatic loading enabled again. --- CHANGELOG.md | 8 +- src/debugadapter.ts | 5 +- src/remotes/cpuhistory.ts | 60 ++++++------ src/remotes/stephistory.ts | 9 +- src/remotes/zesarux/zesaruxremote.ts | 107 +++++++++++---------- src/remotes/zxsimulator/zxmemory.ts | 1 - src/remotes/zxsimulator/zxsimcpuhistory.ts | 20 +++- src/remotes/zxsimulator/zxsimremote.ts | 2 +- src/settings.ts | 27 +++++- 9 files changed, 138 insertions(+), 101 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1412b9a3..f8a1dd78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,12 @@ # Changelog # 0.13.4 -- Fix: Internal simulator: Write watchpoint was indicated as read watchpoint. -- Fix: Internal simulator: corrected "LD (IX/IY+d),n". +- Internal simulator + - Fix: Write-watchpoint was indicated as read-watchpoint. + - Fix: corrected "LD (IX/IY+d),n". + - Performance improvement +- ZEsarUX: automatic loading enabled again. But added launch.json parameters to wait before and after loading ("debug_wait_before" and "debug_wait_after" in ms). +- Visual update corrected after MovePcToCursor. # 0.13.3 - PC jumps to correct location after state restore. diff --git a/src/debugadapter.ts b/src/debugadapter.ts index 7b492f93..ace84095 100644 --- a/src/debugadapter.ts +++ b/src/debugadapter.ts @@ -2229,9 +2229,8 @@ Notes: // Now change Program Counter Remote.setProgramCounter(addr) .then(() => { - // line is not updated. See https://github.com/Microsoft/vscode/issues/51716 - //this.sendEvent(new StoppedEvent('PC-change', EmulDebugAdapter.THREAD_ID)); - this.sendEventContinued(); + Remote.clearCallStack(); + //this.sendEventContinued(); this.sendEvent(new StoppedEvent('PC-change', DebugSessionClass.THREAD_ID)); // Handle decorations StepHistory?.emitHistory(); diff --git a/src/remotes/cpuhistory.ts b/src/remotes/cpuhistory.ts index 5cf3dabb..42131800 100644 --- a/src/remotes/cpuhistory.ts +++ b/src/remotes/cpuhistory.ts @@ -65,6 +65,8 @@ export class CpuHistoryClass extends StepHistoryClass{ /// The virtual stack used during reverse debugging. protected reverseDbgStack: RefList; + // Mirror of the settings historySpotCount. + protected spotCount: number; /** * Sets the static CpuHistory singleton. @@ -81,6 +83,7 @@ export class CpuHistoryClass extends StepHistoryClass{ */ public init() { super.init(); + this.spotCount=Settings.launch.history.spotCount; } @@ -89,12 +92,10 @@ export class CpuHistoryClass extends StepHistoryClass{ */ public clear() { (async () => { - const release=await this.historyMutex.acquire(); this.history.length=0; this.historyIndex=-1; this.revDbgHistory.length=0; this.reverseDbgStack=undefined as any; - release(); })(); } @@ -106,7 +107,9 @@ export class CpuHistoryClass extends StepHistoryClass{ * @param index The index to retrieve. Starts at 0. * @returns A string with the registers. */ + // TODO: Maybe change to use index AND length to obtain several items at once. protected async getRemoteHistoryIndex(index: number): Promise { + assert(false); return undefined; } @@ -127,27 +130,14 @@ export class CpuHistoryClass extends StepHistoryClass{ */ protected async emitHistorySpot(): Promise { // Check if history spot is enabled - const count=Settings.launch.history.spotCount; + const count=this.spotCount; if (count<=0) return; // Otherwise calculate addresses. - // Make sure that this.history is not changed in between - const release=await this.historyMutex.acquire(); - // Check how many history entries need to be retrieved from the remote. let index=this.getHistoryIndex()+1; - let endHistory=index+count; - while (endHistory>this.history.length) { - if (this.history.length>this.maxSize) - break; - // Retrieve items - const line=await this.getRemoteHistoryIndex(this.history.length); - if (!line) - break; - this.history.push(line); - } // Get start index let startIndex=index-count; @@ -164,8 +154,6 @@ export class CpuHistoryClass extends StepHistoryClass{ addresses.push(pc); } - release(); - // Emit code coverage event this.emit('historySpot', startIndex, addresses); } @@ -174,21 +162,33 @@ export class CpuHistoryClass extends StepHistoryClass{ /** * Retrieves the registers at the previous instruction from the Remote's cpu history. * Is async. - * @returns A string with the registers or undefined if at the end of the history. + * @returns Data with the registers or undefined if at the end of the history. */ public async getPrevRegistersAsync(): Promise { - const release=await this.historyMutex.acquire(); - let currentLine= await super.getPrevRegistersAsync(); - if(!currentLine) - { - const index = this.historyIndex + 1; - currentLine = await this.getRemoteHistoryIndex(index); - if(currentLine) { - this.historyIndex = index; - this.history.push(currentLine); - } + // Check if, for the history spot, it is necessary to acquire more items + let count=this.spotCount; + if (count<1) + count=1; // Get at least one item + let index=this.historyIndex+1; + const len=this.history.length-index; + const additionalItems=count-len; + const endIndex=index+additionalItems; + for (let i=index; i=this.history.length) + return undefined; + + // Return an item + const currentLine=this.history[index]; + this.historyIndex=index; return currentLine; } diff --git a/src/remotes/stephistory.ts b/src/remotes/stephistory.ts index fcc7058f..4cde2f03 100644 --- a/src/remotes/stephistory.ts +++ b/src/remotes/stephistory.ts @@ -9,8 +9,6 @@ import {RefList} from '../reflist'; import {Remote} from './remotefactory'; import {Utility} from '../misc/utility'; import {Settings} from '../settings'; -import {Mutex} from 'async-mutex'; - /** @@ -51,9 +49,6 @@ export class StepHistoryClass extends EventEmitter { // The current history index. protected historyIndex=-1; - // A mutext to coordinate access to the histroy array. - protected historyMutex=new Mutex(); - // The maximum size of the history array. protected maxSize=0; @@ -145,9 +140,8 @@ export class StepHistoryClass extends EventEmitter { * @param line One line of history. * @param exchange true if the element should be exchanged rather than added. */ - public async pushHistoryInfo(line: HistoryInstructionInfo, exchange = false): Promise { + public pushHistoryInfo(line: HistoryInstructionInfo, exchange = false) { assert(line); - const release=await this.historyMutex.acquire(); if (exchange&&this.history.length>0) { // Exchange this.history[0]=line; @@ -158,7 +152,6 @@ export class StepHistoryClass extends EventEmitter { if (this.history.length>this.maxSize) this.history.pop(); } - release(); } diff --git a/src/remotes/zesarux/zesaruxremote.ts b/src/remotes/zesarux/zesaruxremote.ts index be4d7537..3a168dc9 100644 --- a/src/remotes/zesarux/zesaruxremote.ts +++ b/src/remotes/zesarux/zesaruxremote.ts @@ -167,7 +167,7 @@ export class ZesaruxRemote extends RemoteBase { const err = new Error('ZEsarUX terminated the connection!'); this.emit('error', err); }); - zSocket.on('connected', () => { + zSocket.on('connected', async () => { if(this.terminating) return; @@ -208,64 +208,69 @@ export class ZesaruxRemote extends RemoteBase { this.zesaruxConnected(); // Wait for previous command to finish - zSocket.executeWhenQueueIsEmpty().then(() => { - var debug_settings = (Settings.launch.skipInterrupt) ? 32 : 0; - zSocket.send('set-debug-settings ' + debug_settings); - - // Reset the cpu before loading. - if(Settings.launch.resetOnLaunch) - zSocket.send('hard-reset-cpu'); - - // Enter step-mode (stop) - zSocket.send('enter-cpu-step'); - - // Load sna or tap file - // TODO: Re-enable: - //const loadPath = Settings.launch.load; - //if (loadPath) - // zSocket.send('smartload ' + Settings.launch.load); - - // Load obj file(s) unit - for(let loadObj of Settings.launch.loadObjs) { - if(loadObj.path) { - // Convert start address - const start = Labels.getNumberFromString(loadObj.start); - if(isNaN(start)) - throw Error("Cannot evaluate 'loadObjs[].start' (" + loadObj.start + ")."); - zSocket.send('load-binary ' + loadObj.path + ' ' + start + ' 0'); // 0 = load entire file - } + await zSocket.executeWhenQueueIsEmpty(); + + var debug_settings = (Settings.launch.skipInterrupt) ? 32 : 0; + zSocket.send('set-debug-settings ' + debug_settings); + + // Reset the cpu before loading. + if(Settings.launch.resetOnLaunch) + zSocket.send('hard-reset-cpu'); + + // Enter step-mode (stop) + zSocket.send('enter-cpu-step'); + + // Load sna, nex or tap file + const loadPath = Settings.launch.load; + if (loadPath) { + const waitBeforeMs=Settings.launch.debug_wait_before; + await Utility.timeout(waitBeforeMs); // TODO: Remove + zSocket.send('smartload '+Settings.launch.load); + const waitAfterMs=Settings.launch.debug_wait_after; + await Utility.timeout(waitAfterMs); // TODO: Remove + } + + // Load obj file(s) unit + for(let loadObj of Settings.launch.loadObjs) { + if(loadObj.path) { + // Convert start address + const start = Labels.getNumberFromString(loadObj.start); + if(isNaN(start)) + throw Error("Cannot evaluate 'loadObjs[].start' (" + loadObj.start + ")."); + zSocket.send('load-binary ' + loadObj.path + ' ' + start + ' 0'); // 0 = load entire file } + } - // Set Program Counter to execAddress - if(Settings.launch.execAddress) { - const execAddress = Labels.getNumberFromString(Settings.launch.execAddress); - if(isNaN(execAddress)) { - error = new Error("Cannot evaluate 'execAddress' (" + Settings.launch.execAddress + ")."); - return; - } - // Set PC - this.setProgramCounter(execAddress); + // Set Program Counter to execAddress + if(Settings.launch.execAddress) { + const execAddress = Labels.getNumberFromString(Settings.launch.execAddress); + if(isNaN(execAddress)) { + error = new Error("Cannot evaluate 'execAddress' (" + Settings.launch.execAddress + ")."); + return; } + // Set PC + this.setProgramCounter(execAddress); + } - // Initialize breakpoints - this.initBreakpoints(); + // Initialize breakpoints + this.initBreakpoints(); - // Code coverage - if(Settings.launch.history.codeCoverageEnabled) { - zSocket.send('cpu-code-coverage enabled yes', () => {}, true); // suppress any error - zSocket.send('cpu-code-coverage clear'); - } - else - zSocket.send('cpu-code-coverage enabled no', () => {}, true); // suppress any error + // Code coverage + if(Settings.launch.history.codeCoverageEnabled) { + zSocket.send('cpu-code-coverage enabled yes', () => {}, true); // suppress any error + zSocket.send('cpu-code-coverage clear'); + } + else + zSocket.send('cpu-code-coverage enabled no', () => {}, true); // suppress any error - // Reverse debugging. - CpuHistory.init(); + // Reverse debugging. + CpuHistory.init(); + + // Enable extended stack + zSocket.send('extended-stack enabled no', () => {}, true); // bug in ZEsarUX + zSocket.send('extended-stack enabled yes'); - // Enable extended stack - zSocket.send('extended-stack enabled no', () => {}, true); // bug in ZEsarUX - zSocket.send('extended-stack enabled yes'); - }); zSocket.executeWhenQueueIsEmpty().then(() => { // Check for console.error diff --git a/src/remotes/zxsimulator/zxmemory.ts b/src/remotes/zxsimulator/zxmemory.ts index 0e5e4f00..a26d86ab 100644 --- a/src/remotes/zxsimulator/zxmemory.ts +++ b/src/remotes/zxsimulator/zxmemory.ts @@ -4,7 +4,6 @@ import * as fs from 'fs'; import {ImageConvert} from '../../imageconvert'; import {Utility} from '../../misc/utility'; import {MemBuffer} from '../../misc/membuffer'; -import {start} from 'repl'; /** diff --git a/src/remotes/zxsimulator/zxsimcpuhistory.ts b/src/remotes/zxsimulator/zxsimcpuhistory.ts index 0c335ca0..ef235610 100644 --- a/src/remotes/zxsimulator/zxsimcpuhistory.ts +++ b/src/remotes/zxsimulator/zxsimcpuhistory.ts @@ -1,5 +1,6 @@ //import * as assert from 'assert'; import {CpuHistoryClass} from '../cpuhistory'; +import {HistoryInstructionInfo} from '../decodehistinfo'; @@ -14,13 +15,28 @@ export class ZxSimCpuHistory extends CpuHistoryClass { */ public clear() { (async () => { - const release=await this.historyMutex.acquire(); this.historyIndex=-1; this.revDbgHistory.length=0; this.reverseDbgStack=undefined as any; - release(); })(); } + + /** + * Retrieves the registers at the previous instruction from the Remote's cpu history. + * Is async. + * @returns Data with the registers or undefined if at the end of the history. + */ + public async getPrevRegistersAsync(): Promise { + // Check if item available + let index=this.historyIndex+1; + if (index>=this.history.length) + return undefined; + + // Return an item + const currentLine=this.history[index]; + this.historyIndex=index; + return currentLine; + } } diff --git a/src/remotes/zxsimulator/zxsimremote.ts b/src/remotes/zxsimulator/zxsimremote.ts index 5f99dfb7..53d46cb9 100644 --- a/src/remotes/zxsimulator/zxsimremote.ts +++ b/src/remotes/zxsimulator/zxsimremote.ts @@ -331,7 +331,7 @@ export class ZxSimulatorRemote extends DzrpRemote { const exchange=(pc==this.previouslyStoredPCHistory); this.previouslyStoredPCHistory=pc; // Store - await CpuHistory.pushHistoryInfo(hist, exchange); + CpuHistory.pushHistoryInfo(hist, exchange); } diff --git a/src/settings.ts b/src/settings.ts index bd5c4164..7bb76b74 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -102,7 +102,7 @@ export interface SerialType { * See also package.json. * The configuration parameters for the zesarux debugger. */ -export interface SettingsParameters extends DebugProtocol.LaunchRequestArguments { +export interface SettingsParameters extends DebugProtocol.LaunchRequestArguments { /// The remote type: zesarux or zxnext. remoteType: string; @@ -192,6 +192,11 @@ export interface SettingsParameters extends DebugProtocol.LaunchRequestArguments /// The timeout for any unit test in seconds. unitTestTimeout: number; + + + // TODO: REMOVE + debug_wait_before: number, + debug_wait_after: number } @@ -200,6 +205,9 @@ export interface SettingsParameters extends DebugProtocol.LaunchRequestArguments /// I.e. the parameters in launch.json. export class Settings { + // Maximum number for history spot count. + protected static MAX_HISTORY_SPOT_COUNT=20; + /// the representation of the launch.json public static launch: SettingsParameters; @@ -243,6 +251,10 @@ export class Settings { tabSize: undefined, socketTimeout: undefined, unitTestTimeout: undefined, + + // TODO: REMOVE + debug_wait_before: undefined, + debug_wait_after: undefined, } } @@ -347,7 +359,9 @@ export class Settings { // Short history if(Settings.launch.history.spotCount == undefined) - Settings.launch.history.spotCount = 10; + Settings.launch.history.spotCount=10; + if (Settings.launch.history.spotCount>Settings.MAX_HISTORY_SPOT_COUNT) + Settings.launch.history.spotCount=Settings.MAX_HISTORY_SPOT_COUNT; if(Settings.launch.history.spotCount > Settings.launch.history.reverseDebugInstructionCount) Settings.launch.history.spotCount = Settings.launch.history.reverseDebugInstructionCount; if(Settings.launch.history.spotCount > 100) @@ -432,7 +446,14 @@ export class Settings { } if(!Settings.launch.unitTestTimeout) - Settings.launch.unitTestTimeout = 1; ///< 1000 ms + Settings.launch.unitTestTimeout=1; ///< 1000 ms + + + // TODO: REMOVE + if (Settings.launch.debug_wait_before==undefined) + Settings.launch.debug_wait_before=0; + if (Settings.launch.debug_wait_after==undefined) + Settings.launch.debug_wait_after=0; }