mirror of
https://github.com/livingcomputermuseum/UniBone.git
synced 2026-02-27 09:09:33 +00:00
Connected CPU20 to INTR,INIT,Power ON/OFF.
PRU INTR routing still do to.
This commit is contained in:
@@ -94,14 +94,14 @@ char *unibus_c::control2text(uint8_t control) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* pulse INIT cycle for 50 milliseconds ... source?
|
||||
/* pulse INIT cycle for some milliseconds
|
||||
*/
|
||||
void unibus_c::init(void) {
|
||||
void unibus_c::init(unsigned pulsewidth_ms) {
|
||||
timeout_c timeout;
|
||||
mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_INIT;
|
||||
mailbox->initializationsignal.val = 1;
|
||||
mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET);
|
||||
timeout.wait_ms(50);
|
||||
timeout.wait_ms(pulsewidth_ms);
|
||||
mailbox->initializationsignal.id = INITIALIZATIONSIGNAL_INIT;
|
||||
mailbox->initializationsignal.val = 0;
|
||||
mailbox_execute(ARM2PRU_INITALIZATIONSIGNAL_SET);
|
||||
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
static char *control2text(uint8_t control);
|
||||
static char *data2text(unsigned val);
|
||||
|
||||
void init(void);
|
||||
void init(unsigned pulsewidth_ms);
|
||||
static void set_arbitration_mode(enum arbitration_mode_enum arbitration_mode);
|
||||
|
||||
void powercycle(void);
|
||||
|
||||
@@ -84,33 +84,6 @@ bool cpu_c::on_param_changed(parameter_c *param) {
|
||||
return device_c::on_param_changed(param); // more actions (for enable)
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
// functions to be used by Angelos CPU emulator
|
||||
// Result: 1 = OK, 0 = bus timeout
|
||||
int cpu_dato(unsigned addr, unsigned data) {
|
||||
uint16_t wordbuffer = (uint16_t) data;
|
||||
|
||||
unibusadapter->cpu_DATA_transfer(the_cpu->data_transfer_request, UNIBUS_CONTROL_DATO, addr, &wordbuffer);
|
||||
return the_cpu->data_transfer_request.success ;
|
||||
}
|
||||
|
||||
int cpu_datob(unsigned addr, unsigned data) {
|
||||
uint16_t wordbuffer = (uint16_t) data;
|
||||
// TODO DATOB als 1 byte-DMA !
|
||||
unibusadapter->cpu_DATA_transfer(the_cpu->data_transfer_request, UNIBUS_CONTROL_DATOB, addr, &wordbuffer);
|
||||
return the_cpu->data_transfer_request.success ;
|
||||
}
|
||||
|
||||
int cpu_dati(unsigned addr, unsigned *data) {
|
||||
uint16_t wordbuffer;
|
||||
unibusadapter->cpu_DATA_transfer(the_cpu->data_transfer_request, UNIBUS_CONTROL_DATI, addr, &wordbuffer);
|
||||
*data = wordbuffer;
|
||||
// printf("DATI; ba=%o, data=%o\n", addr, *data) ;
|
||||
|
||||
return the_cpu->data_transfer_request.success ;
|
||||
}
|
||||
}
|
||||
|
||||
// background worker.
|
||||
void cpu_c::worker(unsigned instance) {
|
||||
UNUSED(instance); // only one
|
||||
@@ -128,27 +101,27 @@ void cpu_c::worker(unsigned instance) {
|
||||
|
||||
if (runmode.value != (ka11.state != 0))
|
||||
ka11.state = runmode.value;
|
||||
condstep(&ka11);
|
||||
ka11_condstep(&ka11);
|
||||
if (runmode.value != (ka11.state != 0))
|
||||
runmode.value = ka11.state != 0;
|
||||
|
||||
if (init.value) {
|
||||
// user wants CPU reset
|
||||
reset(&ka11);
|
||||
ka11_reset(&ka11);
|
||||
init.value = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (runmode.value) {
|
||||
// simulate a fetch
|
||||
nxm = !cpu_dati(pc, &opcode);
|
||||
nxm = !unibone_dati(pc, &opcode);
|
||||
if (nxm) {
|
||||
printf("Bus timeout at PC = %06o. HALT.\n", pc);
|
||||
runmode.value = false;
|
||||
}
|
||||
pc = (pc + 2) % 0100; // loop around
|
||||
// set LEDS
|
||||
nxm = !cpu_dato(dr, pc & 0xf);
|
||||
nxm = !unibone_dato(dr, pc & 0xf);
|
||||
if (nxm) {
|
||||
printf("Bus timeout at DR = %06o. HALT.\n", dr);
|
||||
runmode.value = false;
|
||||
@@ -173,17 +146,76 @@ void cpu_c::on_after_register_access(unibusdevice_register_t *device_reg,
|
||||
UNUSED(unibus_control);
|
||||
}
|
||||
|
||||
// TODO
|
||||
void cpu_c::on_power_changed(void) {
|
||||
if (power_down) { // power-on defaults
|
||||
INFO("CPU: ACLO failed");
|
||||
ka11_pwrdown(&the_cpu->ka11);
|
||||
// ACLO failed.
|
||||
// CPU traps to vector 24 and has 2ms time to execute code
|
||||
} else {
|
||||
INFO("CPU: DCLO restored");
|
||||
ka11_pwrup(&the_cpu->ka11);
|
||||
// DCLO restored
|
||||
// CPU loads PC and PSW from vector 24
|
||||
}
|
||||
}
|
||||
|
||||
// UNIBUS INIT: clear all registers
|
||||
void cpu_c::on_init_changed(void) {
|
||||
// write all registers to "reset-values"
|
||||
if (init_asserted) {
|
||||
reset_unibus_registers();
|
||||
INFO("cpu::on_init()");
|
||||
}
|
||||
// a CPU does not react to INIT ... else its own RESET would reset it.
|
||||
|
||||
}
|
||||
|
||||
// TODO
|
||||
// CPU received interrupt vector from UNIBUS
|
||||
void cpu_c::on_interrupt(uint16_t vector) {
|
||||
// CPU sequence:
|
||||
// push PSW to stack
|
||||
// push PC to stack
|
||||
// PC := *vector
|
||||
// PSW := *(vector+2)
|
||||
ka11_setintr(&the_cpu->ka11, vector);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
// functions to be used by Angelos CPU emulator
|
||||
// Result: 1 = OK, 0 = bus timeout
|
||||
int unibone_dato(unsigned addr, unsigned data) {
|
||||
uint16_t wordbuffer = (uint16_t) data;
|
||||
|
||||
unibusadapter->cpu_DATA_transfer(the_cpu->data_transfer_request, UNIBUS_CONTROL_DATO, addr,
|
||||
&wordbuffer);
|
||||
return the_cpu->data_transfer_request.success;
|
||||
}
|
||||
|
||||
int unibone_datob(unsigned addr, unsigned data) {
|
||||
uint16_t wordbuffer = (uint16_t) data;
|
||||
// TODO DATOB als 1 byte-DMA !
|
||||
unibusadapter->cpu_DATA_transfer(the_cpu->data_transfer_request, UNIBUS_CONTROL_DATOB, addr,
|
||||
&wordbuffer);
|
||||
return the_cpu->data_transfer_request.success;
|
||||
}
|
||||
|
||||
int unibone_dati(unsigned addr, unsigned *data) {
|
||||
uint16_t wordbuffer;
|
||||
unibusadapter->cpu_DATA_transfer(the_cpu->data_transfer_request, UNIBUS_CONTROL_DATI, addr,
|
||||
&wordbuffer);
|
||||
*data = wordbuffer;
|
||||
// printf("DATI; ba=%o, data=%o\n", addr, *data) ;
|
||||
|
||||
return the_cpu->data_transfer_request.success;
|
||||
}
|
||||
|
||||
// CPU has changed the arbitration level, just forward
|
||||
void unibone_prioritylevelchange(uint8_t level) {
|
||||
mailbox->arbitrator.cpu_priority_level = level;
|
||||
}
|
||||
|
||||
// TODO
|
||||
// CPU executes RESET opcode -> pulses INIT line
|
||||
void unibone_bus_init(unsigned pulsewidth_ms) {
|
||||
unibus->init(pulsewidth_ms);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,9 @@ public:
|
||||
|
||||
void on_power_changed(void) override;
|
||||
void on_init_changed(void) override;
|
||||
void on_interrupt(uint16_t vector) ;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
#include "11.h"
|
||||
#include "ka11.h"
|
||||
|
||||
int cpu_dato(unsigned addr, unsigned data);
|
||||
int cpu_datob(unsigned addr, unsigned data);
|
||||
int cpu_dati(unsigned addr, unsigned *data);
|
||||
int unibone_dato(unsigned addr, unsigned data);
|
||||
int unibone_datob(unsigned addr, unsigned data);
|
||||
int unibone_dati(unsigned addr, unsigned *data);
|
||||
void unibone_prioritylevelchange(uint8_t level);
|
||||
void unibone_bus_init(unsigned pulsewidth_ms) ;
|
||||
|
||||
|
||||
int
|
||||
dati_bus(Bus *bus)
|
||||
{
|
||||
unsigned int data;
|
||||
if(!cpu_dati(bus->addr, &data))
|
||||
if(!unibone_dati(bus->addr, &data))
|
||||
return 1;
|
||||
bus->data = data;
|
||||
return 0;
|
||||
@@ -18,15 +21,20 @@ dati_bus(Bus *bus)
|
||||
int
|
||||
dato_bus(Bus *bus)
|
||||
{
|
||||
return !cpu_dato(bus->addr, bus->data);
|
||||
return !unibone_dato(bus->addr, bus->data);
|
||||
}
|
||||
|
||||
int
|
||||
datob_bus(Bus *bus)
|
||||
{
|
||||
return !cpu_datob(bus->addr, bus->data);
|
||||
return !unibone_datob(bus->addr, bus->data);
|
||||
}
|
||||
|
||||
void
|
||||
levelchange(word psw)
|
||||
{
|
||||
unibone_prioritylevelchange(psw>>5);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -42,11 +50,12 @@ enum {
|
||||
|
||||
enum {
|
||||
TRAP_STACK = 1,
|
||||
TRAP_PWR = 2, // can't happen
|
||||
TRAP_PWR = 2,
|
||||
TRAP_BR7 = 4,
|
||||
TRAP_BR6 = 010,
|
||||
TRAP_BR5 = 040,
|
||||
TRAP_BR4 = 0100,
|
||||
TRAP_BRX = 0200, // for unibone
|
||||
TRAP_CSTOP = 01000 // can't happen?
|
||||
};
|
||||
|
||||
@@ -107,7 +116,7 @@ printstate(KA11 *cpu)
|
||||
}
|
||||
|
||||
void
|
||||
reset(KA11 *cpu)
|
||||
ka11_reset(KA11 *cpu)
|
||||
{
|
||||
Busdev *bd;
|
||||
|
||||
@@ -171,6 +180,7 @@ trace("dato %06o %06o %d\n", cpu->ba, cpu->bus->data, b);
|
||||
/* writes 0 for the odd byte.
|
||||
I think this is correct. */
|
||||
cpu->psw = cpu->bus->data;
|
||||
levelchange(cpu->psw);
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
@@ -546,7 +556,7 @@ step(KA11 *cpu)
|
||||
SVC;
|
||||
case 3: TR(BPT); TRAP(014);
|
||||
case 4: TR(IOT); TRAP(020);
|
||||
case 5: TR(RESET); reset(cpu); SVC;
|
||||
case 5: TR(RESET); ka11_reset(cpu); unibone_bus_init(10) ; SVC;
|
||||
}
|
||||
|
||||
// All other instructions should be reserved now
|
||||
@@ -567,6 +577,7 @@ trap:
|
||||
PUSH; OUT(SP, PC);
|
||||
INA(TV, PC);
|
||||
INA(TV+2, PSW);
|
||||
levelchange(PSW);
|
||||
/* no trace trap after a trap */
|
||||
oldpsw = PSW;
|
||||
|
||||
@@ -586,6 +597,9 @@ service:
|
||||
}else if(cpu->traps & TRAP_PWR){
|
||||
cpu->traps &= ~TRAP_PWR;
|
||||
TRAP(024);
|
||||
}else if(cpu->traps & TRAP_BRX){
|
||||
cpu->traps &= ~TRAP_BRX;
|
||||
TRAP(cpu->trapvec);
|
||||
}else if(c < 7 && cpu->traps & TRAP_BR7){
|
||||
cpu->traps &= ~TRAP_BR7;
|
||||
TRAP(cpu->br[3].bg(cpu->br[3].dev));
|
||||
@@ -605,7 +619,31 @@ service:
|
||||
}
|
||||
|
||||
void
|
||||
condstep(KA11 *cpu)
|
||||
ka11_setintr(KA11 *cpu, unsigned vec)
|
||||
{
|
||||
cpu->traps |= TRAP_BRX;
|
||||
cpu->trapvec = vec;
|
||||
}
|
||||
|
||||
void
|
||||
ka11_pwrdown(KA11 *cpu)
|
||||
{
|
||||
cpu->traps |= TRAP_PWR;
|
||||
}
|
||||
|
||||
void
|
||||
ka11_pwrup(KA11 *cpu)
|
||||
{
|
||||
INA(024, PC);
|
||||
INA(024+2, PSW);
|
||||
return ;
|
||||
be:
|
||||
trace("BE\n");
|
||||
cpu->be++ ;
|
||||
}
|
||||
|
||||
void
|
||||
ka11_condstep(KA11 *cpu)
|
||||
{
|
||||
if((cpu->state == STATE_RUNNING) ||
|
||||
(cpu->state == STATE_WAITING && cpu->traps)){
|
||||
@@ -621,7 +659,7 @@ run(KA11 *cpu)
|
||||
while(cpu->state != STATE_HALTED){
|
||||
svc(cpu, cpu->bus);
|
||||
|
||||
condstep(cpu);
|
||||
ka11_condstep(cpu);
|
||||
}
|
||||
|
||||
printstate(cpu);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// 11/20 cpu - TODO
|
||||
// Interface of 11/20 PCU emulator to UniBone
|
||||
typedef struct KA11 KA11;
|
||||
struct KA11
|
||||
{
|
||||
@@ -16,9 +16,14 @@ struct KA11
|
||||
int (*bg)(void *dev);
|
||||
void *dev;
|
||||
} br[4];
|
||||
word trapvec; // for unibone
|
||||
|
||||
word sw;
|
||||
};
|
||||
//void run(KA11 *cpu);
|
||||
void reset(KA11 *cpu);
|
||||
void condstep(KA11 *cpu);
|
||||
|
||||
void ka11_reset(KA11 *cpu);
|
||||
void ka11_setintr(KA11 *cpu, unsigned vec);
|
||||
void ka11_pwrdown(KA11 *cpu);
|
||||
void ka11_pwrup(KA11 *cpu);
|
||||
void ka11_condstep(KA11 *cpu);
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ void application_c::menu_device_exercisers(void) {
|
||||
if (!strcasecmp(s_opcode, "q")) {
|
||||
ready = true;
|
||||
} else if (!strcasecmp(s_opcode, "init")) {
|
||||
unibus->init();
|
||||
unibus->init(50);
|
||||
} else if (!strcasecmp(s_opcode, "pwr")) {
|
||||
unibus->powercycle();
|
||||
} else if (!strcasecmp(s_opcode, "dbg") && n_fields == 2) {
|
||||
|
||||
@@ -140,7 +140,7 @@ void application_c::menu_devices(bool with_CPU) {
|
||||
|
||||
// without PDP-11 CPU no INIT after power ON was generated.
|
||||
// Devices may trash the bus lines.
|
||||
unibus->init();
|
||||
unibus->init(50);
|
||||
|
||||
unibusadapter->enabled.set(true);
|
||||
|
||||
@@ -262,7 +262,7 @@ void application_c::menu_devices(bool with_CPU) {
|
||||
if (!strcasecmp(s_opcode, "q")) {
|
||||
ready = true;
|
||||
} else if (!strcasecmp(s_opcode, "init")) {
|
||||
unibus->init();
|
||||
unibus->init(50);
|
||||
} else if (!strcasecmp(s_opcode, "pwr")) {
|
||||
unibus->powercycle();
|
||||
} else if (!strcasecmp(s_opcode, "dbg") && n_fields == 2) {
|
||||
|
||||
@@ -155,7 +155,7 @@ void application_c::menu_masterslave(enum unibus_c::arbitration_mode_enum arbitr
|
||||
else
|
||||
printf("%s\n", fileErrorText("Error opening command file \"%s\"!", s_param[0]));
|
||||
} else if (!strcasecmp(s_opcode, "init")) {
|
||||
unibus->init();
|
||||
unibus->init(50);
|
||||
} else if (!strcasecmp(s_opcode, "i")) {
|
||||
iopageregisters_print_tables();
|
||||
} else if (!strcasecmp(s_opcode, "pwr")) {
|
||||
|
||||
Reference in New Issue
Block a user