-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(sio): implement Integer Divider (#37)
Implemented according to section 2.3.1.5 of the RP2040 datasheet and verified against the silicone. All adds the RESET_BASE peripheral (RP2040 datasheet section 2.14) to reduce the amount of "unimplemented peripheral" read/write warnings.
- Loading branch information
Showing
7 changed files
with
246 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { BasePeripheral, Peripheral } from './peripheral'; | ||
|
||
const RESET = 0x0; //Reset control. | ||
const WDSEL = 0x4; //Watchdog select. | ||
const RESET_DONE = 0x8; //Reset Done | ||
|
||
export class RPReset extends BasePeripheral implements Peripheral { | ||
private reset: number = 0; | ||
private wdsel: number = 0; | ||
private reset_done: number = 0x1ffffff; | ||
|
||
readUint32(offset: number) { | ||
switch (offset) { | ||
case RESET: | ||
return this.reset; | ||
case WDSEL: | ||
return this.wdsel; | ||
case RESET_DONE: | ||
return this.reset_done; | ||
} | ||
return super.readUint32(offset); | ||
} | ||
|
||
writeUint32(offset: number, value: number) { | ||
switch (offset) { | ||
case RESET: | ||
this.reset = value & 0x1ffffff; | ||
break; | ||
case WDSEL: | ||
this.wdsel = value & 0x1ffffff; | ||
break; | ||
default: | ||
super.writeUint32(offset, value); | ||
break; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import { RP2040, SIO_START_ADDRESS } from './rp2040'; | ||
import { GDBClient } from './utils/gdbclient'; | ||
import { ICortexTestDriver } from './utils/test-driver'; | ||
import { GDBTestDriver } from './utils/test-driver-gdb'; | ||
import { RP2040TestDriver } from './utils/test-driver-rp2040'; | ||
|
||
//Hardware Divider registers absolute address | ||
const SIO_DIV_UDIVIDEND = SIO_START_ADDRESS + 0x060; // Divider unsigned dividend | ||
const SIO_DIV_UDIVISOR = SIO_START_ADDRESS + 0x064; // Divider unsigned divisor | ||
const SIO_DIV_SDIVIDEND = SIO_START_ADDRESS + 0x068; // Divider signed dividend | ||
const SIO_DIV_SDIVISOR = SIO_START_ADDRESS + 0x06c; // Divider signed divisor | ||
const SIO_DIV_QUOTIENT = SIO_START_ADDRESS + 0x070; // Divider result quotient | ||
const SIO_DIV_REMAINDER = SIO_START_ADDRESS + 0x074; //Divider result remainder | ||
const SIO_DIV_CSR = SIO_START_ADDRESS + 0x078; | ||
|
||
describe('RPSIO', () => { | ||
let cpu: ICortexTestDriver; | ||
|
||
beforeEach(async () => { | ||
// if (process.env.TEST_GDB_SERVER) { | ||
if (false) { | ||
const client = new GDBClient(); | ||
await client.connect('127.0.0.1'); | ||
cpu = new GDBTestDriver(client); | ||
await cpu.init(); | ||
} else { | ||
cpu = new RP2040TestDriver(new RP2040()); | ||
} | ||
}); | ||
|
||
afterEach(async () => { | ||
await cpu.tearDown(); | ||
}); | ||
|
||
describe('Hardware Divider', () => { | ||
it('should perform a signed hardware divider 123456 / -321 = -384 REM 192', async () => { | ||
await cpu.writeUint32(SIO_DIV_SDIVIDEND, 123456); | ||
expect(await cpu.readInt32(SIO_DIV_SDIVIDEND)).toEqual(123456); | ||
await cpu.writeUint32(SIO_DIV_SDIVISOR, -321); | ||
expect(await cpu.readUint32(SIO_DIV_CSR)).toEqual(3); | ||
expect(await cpu.readInt32(SIO_DIV_SDIVISOR)).toEqual(-321); | ||
expect(await cpu.readInt32(SIO_DIV_REMAINDER)).toEqual(192); | ||
expect(await cpu.readInt32(SIO_DIV_QUOTIENT)).toEqual(-384); | ||
expect(await cpu.readUint32(SIO_DIV_CSR)).toEqual(1); | ||
}); | ||
|
||
it('should perform a signed hardware divider -3000 / 2 = -1500 REM 0', async () => { | ||
await cpu.writeUint32(SIO_DIV_SDIVIDEND, -3000); | ||
expect(await cpu.readInt32(SIO_DIV_SDIVIDEND)).toEqual(-3000); | ||
await cpu.writeUint32(SIO_DIV_SDIVISOR, 2); | ||
expect(await cpu.readUint32(SIO_DIV_CSR)).toEqual(3); | ||
expect(await cpu.readInt32(SIO_DIV_SDIVISOR)).toEqual(2); | ||
expect(await cpu.readInt32(SIO_DIV_REMAINDER)).toEqual(0); | ||
expect(await cpu.readInt32(SIO_DIV_QUOTIENT)).toEqual(-1500); | ||
expect(await cpu.readUint32(SIO_DIV_CSR)).toEqual(1); | ||
}); | ||
|
||
it('should perform an unsigned hardware divider 123456 / 321 = 384 REM 192', async () => { | ||
await cpu.writeUint32(SIO_DIV_UDIVIDEND, 123456); | ||
await cpu.writeUint32(SIO_DIV_UDIVISOR, 321); | ||
expect(await cpu.readUint32(SIO_DIV_CSR)).toEqual(3); | ||
expect(await cpu.readUint32(SIO_DIV_REMAINDER)).toEqual(192); | ||
expect(await cpu.readUint32(SIO_DIV_QUOTIENT)).toEqual(384); | ||
expect(await cpu.readUint32(SIO_DIV_CSR)).toEqual(1); | ||
}); | ||
|
||
it('should perform a division, store the result, do another division then restore the previously stored result ', async () => { | ||
await cpu.writeUint32(SIO_DIV_SDIVIDEND, 123456); | ||
await cpu.writeUint32(SIO_DIV_SDIVISOR, -321); | ||
const remainder = await cpu.readInt32(SIO_DIV_REMAINDER); | ||
const quotient = await cpu.readInt32(SIO_DIV_QUOTIENT); | ||
expect(remainder).toEqual(192); | ||
expect(quotient).toEqual(-384); | ||
await cpu.writeUint32(SIO_DIV_UDIVIDEND, 123); | ||
await cpu.writeUint32(SIO_DIV_UDIVISOR, 7); | ||
expect(await cpu.readUint32(SIO_DIV_REMAINDER)).toEqual(4); | ||
expect(await cpu.readUint32(SIO_DIV_QUOTIENT)).toEqual(17); | ||
await cpu.writeUint32(SIO_DIV_REMAINDER, remainder); | ||
await cpu.writeUint32(SIO_DIV_QUOTIENT, quotient); | ||
expect(await cpu.readUint32(SIO_DIV_CSR)).toEqual(3); | ||
expect(await cpu.readInt32(SIO_DIV_REMAINDER)).toEqual(192); | ||
expect(await cpu.readInt32(SIO_DIV_QUOTIENT)).toEqual(-384); | ||
}); | ||
|
||
it('should perform an unsigned division by zero 123456 / 0 = 0xffffffff REM 123456', async () => { | ||
await cpu.writeUint32(SIO_DIV_UDIVIDEND, 123456); | ||
await cpu.writeUint32(SIO_DIV_UDIVISOR, 0); | ||
expect(await cpu.readUint32(SIO_DIV_REMAINDER)).toEqual(123456); | ||
expect(await cpu.readUint32(SIO_DIV_QUOTIENT)).toEqual(0xffffffff); | ||
}); | ||
|
||
it('should perform an unsigned division by zero 0x80000000 / 0 = 0xffffffff REM 0x80000000', async () => { | ||
await cpu.writeUint32(SIO_DIV_UDIVIDEND, 0x80000000); | ||
await cpu.writeUint32(SIO_DIV_UDIVISOR, 0); | ||
expect(await cpu.readUint32(SIO_DIV_REMAINDER)).toEqual(0x80000000); | ||
expect(await cpu.readUint32(SIO_DIV_QUOTIENT)).toEqual(0xffffffff); | ||
}); | ||
|
||
it('should perform a signed division by zero 3000 / 0 = -1 REM 3000', async () => { | ||
await cpu.writeUint32(SIO_DIV_SDIVIDEND, 3000); | ||
await cpu.writeUint32(SIO_DIV_SDIVISOR, 0); | ||
expect(await cpu.readInt32(SIO_DIV_REMAINDER)).toEqual(3000); | ||
expect(await cpu.readInt32(SIO_DIV_QUOTIENT)).toEqual(-1); | ||
}); | ||
|
||
it('should perform a signed division by zero -3000 / 0 = 1 REM -3000', async () => { | ||
await cpu.writeUint32(SIO_DIV_SDIVIDEND, -3000); | ||
await cpu.writeUint32(SIO_DIV_SDIVISOR, 0); | ||
expect(await cpu.readInt32(SIO_DIV_REMAINDER)).toEqual(-3000); | ||
expect(await cpu.readInt32(SIO_DIV_QUOTIENT)).toEqual(1); | ||
}); | ||
|
||
it('should perform a signed division 0x80000000 / 2 = 0xc0000000 REM 0', async () => { | ||
await cpu.writeUint32(SIO_DIV_SDIVIDEND, 0x80000000); | ||
await cpu.writeUint32(SIO_DIV_SDIVISOR, 2); | ||
expect(await cpu.readUint32(SIO_DIV_REMAINDER)).toEqual(0); | ||
expect(await cpu.readUint32(SIO_DIV_QUOTIENT)).toEqual(0xc0000000); | ||
}); | ||
|
||
it('should perform an unsigned division 0x80000000 / 2 = 0x40000000 REM 0', async () => { | ||
await cpu.writeUint32(SIO_DIV_UDIVIDEND, 0x80000000); | ||
await cpu.writeUint32(SIO_DIV_UDIVISOR, 2); | ||
expect(await cpu.readUint32(SIO_DIV_REMAINDER)).toEqual(0); | ||
expect(await cpu.readUint32(SIO_DIV_QUOTIENT)).toEqual(0x40000000); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters