Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement core1 #112

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
190cba8
Implement TBMAN
mingpepe Nov 28, 2022
de3601f
Implement REF/SYS CTRL & SELECT for clock
mingpepe Nov 28, 2022
e7a222c
Define enum for cores
mingpepe Dec 12, 2022
dfbeaf0
Add API for peripheral to read from core
mingpepe Dec 12, 2022
aca3a9c
Define onSEV event to wakeup another core
mingpepe Dec 12, 2022
1b660e3
Define onBreak event for GDB
mingpepe Dec 12, 2022
c64c141
Implement read/write via core for ppb
mingpepe Dec 12, 2022
d5a1074
Implement FIFO registers in SIO
mingpepe Dec 12, 2022
a31e8fc
Define 2 cores in rp2040
mingpepe Dec 12, 2022
dc29d0c
Register onSEV event for each core
mingpepe Dec 12, 2022
efb7820
Implement NMI_MASK for syscfg
mingpepe Dec 12, 2022
dcc32ab
Modify debugger to debug only on core0
mingpepe Dec 12, 2022
26fb63f
Update unit test
mingpepe Dec 12, 2022
9b54d9d
Update test-utils
mingpepe Dec 12, 2022
b1b4560
Update demo code
mingpepe Dec 12, 2022
d12a4b5
Merge branch 'master' into core1
mingpepe Dec 12, 2022
4a0cf99
Let each core has its divider
mingpepe Dec 13, 2022
10ec3e6
Let each core has its interpolator
mingpepe Dec 13, 2022
fd563cd
Move fifo related logic to each core
mingpepe Dec 13, 2022
c9ab5ea
Do no need to pass core info to each core
mingpepe Dec 13, 2022
6f2da85
Add core info to warning message
mingpepe Dec 13, 2022
278bda7
Execute core0 and core1 interleaving
mingpepe Jan 30, 2023
26f77aa
Merge branch 'master' into core1
mingpepe Feb 6, 2023
1290137
Fix wrong merge
mingpepe Feb 6, 2023
9b55ad5
Run lint
mingpepe Feb 6, 2023
9bb7e7a
Fix error by lint
mingpepe Feb 6, 2023
23bf9d3
Rename variable
mingpepe Mar 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion demo/emulator-run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ mcu.uart[0].onByte = (value) => {
process.stdout.write(new Uint8Array([value]));
};

mcu.core.PC = 0x10000000;
mcu.core0.PC = 0x10000000;
mcu.core1.PC = 0x10000000;
mcu.execute();
3 changes: 2 additions & 1 deletion demo/micropython-run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@ process.stdin.on('data', (chunk) => {
}
});

mcu.core.PC = 0x10000000;
mcu.core0.PC = 0x10000000;
mcu.core1.PC = 0x10000000;
mcu.execute();
4 changes: 4 additions & 0 deletions src/core.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum Core {
Core0,
Core1,
}
15 changes: 12 additions & 3 deletions src/cortex-m0-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ export class CortexM0Core {
SHPR2 = 0;
SHPR3 = 0;

public onSEV?: () => void;
public onBreak?: (code: number) => void;

stopped = true;

constructor(readonly rp2040: RP2040) {
this.SP = 0xfffffffc;
this.bankedSP = 0xfffffffc;
Expand Down Expand Up @@ -718,7 +723,8 @@ export class CortexM0Core {
else if (opcode >> 8 === 0b10111110) {
const imm8 = opcode & 0xff;
this.breakRewind = 2;
this.rp2040.onBreak(imm8);
this.stopped = true;
this.onBreak?.(imm8);
}
// BL
else if (opcode >> 11 === 0b11110 && opcode2 >> 14 === 0b11 && ((opcode2 >> 12) & 0x1) == 1) {
Expand Down Expand Up @@ -1137,6 +1143,7 @@ export class CortexM0Core {
// SEV
else if (opcode === 0b1011111101000000) {
this.logger.info(LOG_NAME, 'SEV');
this.onSEV?.();
}
// STMIA
else if (opcode >> 11 === 0b11000) {
Expand Down Expand Up @@ -1285,14 +1292,16 @@ export class CortexM0Core {
else if (opcode >> 8 == 0b11011110) {
const imm8 = opcode & 0xff;
this.breakRewind = 2;
this.rp2040.onBreak(imm8);
this.stopped = true;
this.onBreak?.(imm8);
}
// UDF (Encoding T2)
else if (opcode >> 4 === 0b111101111111 && opcode2 >> 12 === 0b1010) {
const imm4 = opcode & 0xf;
const imm12 = opcode2 & 0xfff;
this.breakRewind = 4;
this.rp2040.onBreak((imm4 << 12) | imm12);
this.stopped = true;
this.onBreak?.((imm4 << 12) | imm12);
this.PC += 2;
}
// UXTB
Expand Down
11 changes: 6 additions & 5 deletions src/gdb/gdb-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { SYSM_CONTROL, SYSM_MSP, SYSM_PRIMASK, SYSM_PSP } from '../cortex-m0-cor
import { RP2040 } from '../rp2040';
import { ConsoleLogger, Logger, LogLevel } from '../utils/logging';
import { GDBConnection } from './gdb-connection';
import { Core } from '../core';
import {
decodeHexBuf,
encodeHexBuf,
Expand Down Expand Up @@ -86,7 +87,7 @@ export class GDBServer {

processGDBMessage(cmd: string) {
const { rp2040 } = this;
const { core } = rp2040;
const { core0: core } = rp2040;
if (cmd === 'Hg0') {
return gdbMessage('OK');
}
Expand Down Expand Up @@ -128,7 +129,7 @@ export class GDBServer {
return gdbMessage('vCont;c;C;s;S');
}
if (cmd.startsWith('vCont;c')) {
if (!rp2040.executing) {
if (!rp2040.executing(Core.Core0)) {
rp2040.execute();
}
return;
Expand All @@ -145,7 +146,7 @@ export class GDBServer {
break;

case 'c':
if (!rp2040.executing) {
if (!rp2040.executing(Core.Core0)) {
rp2040.execute();
}
return gdbMessage('OK');
Expand Down Expand Up @@ -260,9 +261,9 @@ export class GDBServer {

addConnection(connection: GDBConnection) {
this.connections.add(connection);
this.rp2040.onBreak = () => {
this.rp2040.core0.onBreak = () => {
this.rp2040.stop();
this.rp2040.core.PC -= this.rp2040.core.breakRewind;
this.rp2040.core0.PC -= this.rp2040.core0.breakRewind;
for (const connection of this.connections) {
connection.onBreakpoint();
}
Expand Down
16 changes: 8 additions & 8 deletions src/instructions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -978,22 +978,22 @@ describe('Cortex-M0+ Instruction Set', () => {
it('should execute a `udf 1` instruction', () => {
const breakMock = jest.fn();
const rp2040 = new RP2040();
rp2040.core.PC = 0x20000000;
rp2040.core0.PC = 0x20000000;
rp2040.writeUint16(0x20000000, opcodeUDF(0x1));
rp2040.onBreak = breakMock;
rp2040.core0.onBreak = breakMock;
rp2040.step();
expect(rp2040.core.PC).toEqual(0x20000002);
expect(rp2040.core0.PC).toEqual(0x20000002);
expect(breakMock).toHaveBeenCalledWith(1);
});

it('should execute a `udf.w #0` (T2 encoding) instruction', () => {
const breakMock = jest.fn();
const rp2040 = new RP2040();
rp2040.core.PC = 0x20000000;
rp2040.core0.PC = 0x20000000;
rp2040.writeUint32(0x20000000, opcodeUDF2(0));
rp2040.onBreak = breakMock;
rp2040.core0.onBreak = breakMock;
rp2040.step();
expect(rp2040.core.PC).toEqual(0x20000004);
expect(rp2040.core0.PC).toEqual(0x20000004);
expect(breakMock).toHaveBeenCalledWith(0);
});

Expand Down Expand Up @@ -1431,13 +1431,13 @@ describe('Cortex-M0+ Instruction Set', () => {

await cpu.singleStep();
if (cpu instanceof RP2040TestDriver) {
expect(cpu.rp2040.core.pendingSVCall).toEqual(true);
expect(cpu.rp2040.core0.pendingSVCall).toEqual(true);
}

await cpu.singleStep(); // SVCall handler should run here
const registers2 = await cpu.readRegisters();
if (cpu instanceof RP2040TestDriver) {
expect(cpu.rp2040.core.pendingSVCall).toEqual(false);
expect(cpu.rp2040.core0.pendingSVCall).toEqual(false);
}
expect(registers2.pc).toEqual(SVCALL_HANDLER + 2);
expect(registers2.r0).toEqual(0x55);
Expand Down
12 changes: 12 additions & 0 deletions src/peripherals/peripheral.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { RP2040 } from '../rp2040';
import { Core } from '../core';

const ATOMIC_NORMAL = 0;
const ATOMIC_XOR = 1;
Expand All @@ -21,7 +22,9 @@ export function atomicUpdate(currentValue: number, atomicType: number, newValue:

export interface Peripheral {
readUint32(offset: number): number;
readUint32ViaCore(offset: number, core: Core): number;
writeUint32(offset: number, value: number): void;
writeUint32ViaCore(offset: number, value: number, core: Core): void;
writeUint32Atomic(offset: number, value: number, atomicType: number): void;
}

Expand All @@ -38,10 +41,19 @@ export class BasePeripheral implements Peripheral {
return 0xffffffff;
}

readUint32ViaCore(offset: number, core: Core) {
this.warn(`Unimplemented peripheral readvia ${core} from ${offset.toString(16)}`);
return 0xffffffff;
}

writeUint32(offset: number, value: number) {
this.warn(`Unimplemented peripheral write to ${offset.toString(16)}: ${value}`);
}

writeUint32ViaCore(offset: number, value: number, core: Core) {
this.warn(`Unimplemented peripheral write via ${core} to ${offset.toString(16)}: ${value}`);
}

writeUint32Atomic(offset: number, value: number, atomicType: number) {
this.rawWriteValue = value;
const newValue =
Expand Down
13 changes: 7 additions & 6 deletions src/peripherals/ppb.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { IClockTimer } from '../clock/clock';
import { MAX_HARDWARE_IRQ } from '../irq';
import { BasePeripheral, Peripheral } from './peripheral';
import { Core } from '../core'

export const CPUID = 0xd00;
export const ICSR = 0xd04;
Expand Down Expand Up @@ -53,9 +54,9 @@ export class RPPPB extends BasePeripheral implements Peripheral {
systickReload = 0;
systickTimer: IClockTimer | null = null;

readUint32(offset: number) {
readUint32ViaCore(offset: number, _core: Core) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please call it coreIndex (or similar) instead of _core (same for writeUint32ViaCore)

const { rp2040 } = this;
const { core } = rp2040;
const core = _core == Core.Core0 ? rp2040.core0 : rp2040.core1;

switch (offset) {
case CPUID:
Expand Down Expand Up @@ -132,12 +133,12 @@ export class RPPPB extends BasePeripheral implements Peripheral {
case SYST_CALIB:
return 0x0000270f;
}
return super.readUint32(offset);
return super.readUint32ViaCore(offset, _core);
}

writeUint32(offset: number, value: number) {
writeUint32ViaCore(offset: number, value: number, _core: Core) {
const { rp2040 } = this;
const { core } = rp2040;
const core = _core == Core.Core0 ? rp2040.core0 : rp2040.core1;

const hardwareInterruptMask = (1 << MAX_HARDWARE_IRQ) - 1;

Expand Down Expand Up @@ -246,7 +247,7 @@ export class RPPPB extends BasePeripheral implements Peripheral {
return;

default:
super.writeUint32(offset, value);
super.writeUint32ViaCore(offset, value, _core);
}
}
}
9 changes: 7 additions & 2 deletions src/peripherals/syscfg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,21 @@ export class RP2040SysCfg extends BasePeripheral implements Peripheral {
readUint32(offset: number) {
switch (offset) {
case PROC0_NMI_MASK:
return this.rp2040.core.interruptNMIMask;
return this.rp2040.core0.interruptNMIMask;
case PROC1_NMI_MASK:
return this.rp2040.core1.interruptNMIMask;
}
return super.readUint32(offset);
}

writeUint32(offset: number, value: number) {
switch (offset) {
case PROC0_NMI_MASK:
this.rp2040.core.interruptNMIMask = value;
this.rp2040.core0.interruptNMIMask = value;
break;
case PROC1_NMI_MASK:
this.rp2040.core1.interruptNMIMask = value;
break;

default:
super.writeUint32(offset, value);
Expand Down
8 changes: 4 additions & 4 deletions src/peripherals/timer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,16 @@ describe('RPTimer', () => {
expect(rp2040.readUint32(ARMED)).toEqual(0);
expect(rp2040.readUint32(INTR)).toEqual(0x8);
expect(rp2040.readUint32(INTS)).toEqual(0);
expect(rp2040.core.pendingInterrupts).toBe(0);
expect(rp2040.core0.pendingInterrupts).toBe(0);
// Enable the interrupts for all alarms
rp2040.writeUint32(INTE, 0xff);
expect(rp2040.readUint32(INTS)).toEqual(0x8);
expect(rp2040.core.pendingInterrupts).toBe(0x8);
expect(rp2040.core.interruptsUpdated).toEqual(true);
expect(rp2040.core0.pendingInterrupts).toBe(0x8);
expect(rp2040.core0.interruptsUpdated).toEqual(true);
// Clear the alarm's interrupt
rp2040.writeUint32(INTR_CLEAR, 0x8);
expect(rp2040.readUint32(INTS)).toEqual(0);
expect(rp2040.core.pendingInterrupts).toBe(0);
expect(rp2040.core0.pendingInterrupts).toBe(0);
});

it('should generate an interrupt if INTF is 1 even when the INTE bit is 0', () => {
Expand Down
Loading