VAX: Fix Interval Timers

- Properly set the Interval Register when a running timer is stopped
- Peoperly clear timer interrupt pending when CSR is updated
- Properly handle the case when the timer is started with the interval
   register is 0.
- Properly stop the running timer when it is restarted or adjusted
   with a new interval value.
- Better debug info
This commit is contained in:
Mark Pizzolato 2018-01-07 13:46:07 -08:00
parent fc25cf54fa
commit ee4c33ead2

View file

@ -294,6 +294,7 @@ int32 ssc_rd (int32 pa);
void ssc_wr (int32 pa, int32 val, int32 lnt); void ssc_wr (int32 pa, int32 val, int32 lnt);
int32 tmr_tir_rd (int32 tmr); int32 tmr_tir_rd (int32 tmr);
void tmr_csr_wr (int32 tmr, int32 val); void tmr_csr_wr (int32 tmr, int32 val);
int32 tmr_csr_rd (int32 tmr);
void tmr_sched (int32 tmr); void tmr_sched (int32 tmr);
void tmr_incr (int32 tmr, uint32 inc); void tmr_incr (int32 tmr, uint32 inc);
int32 tmr0_inta (void); int32 tmr0_inta (void);
@ -1309,9 +1310,7 @@ switch (rg) {
return txcs_rd (); return txcs_rd ();
case 0x40: /* T0CSR */ case 0x40: /* T0CSR */
sim_debug (DBG_REGR, &sysd_dev, "tmr_csr_rd(tmr=%d) - 0x%X", 0, tmr_csr[0]); return tmr_csr_rd (0);
sim_debug_bits_hdr (DBG_REGR, &sysd_dev, " ", tmr_csr_bits, tmr_csr[0], tmr_csr[0], 1);
return tmr_csr[0];
case 0x41: /* T0INT */ case 0x41: /* T0INT */
return tmr_tir_rd (0); return tmr_tir_rd (0);
@ -1325,9 +1324,7 @@ switch (rg) {
return tmr_tivr[0]; return tmr_tivr[0];
case 0x44: /* T1CSR */ case 0x44: /* T1CSR */
sim_debug (DBG_REGR, &sysd_dev, "tmr_csr_rd(tmr=%d) - 0x%X\n", 1, tmr_csr[1]); return tmr_csr_rd (1);
sim_debug_bits_hdr (DBG_REGR, &sysd_dev, "tmr_csr_rd(tmr=1)", tmr_csr_bits, tmr_csr[1], tmr_csr[1], 1);
return tmr_csr[1];
case 0x45: /* T1INT */ case 0x45: /* T1INT */
return tmr_tir_rd (1); return tmr_tir_rd (1);
@ -1512,6 +1509,13 @@ sim_debug (DBG_REGR, &sysd_dev, "tmr_tir_rd(tmr=%d) - 0x%X\n", tmr, tmr_tir[tmr]
return tmr_tir[tmr]; return tmr_tir[tmr];
} }
int32 tmr_csr_rd (int32 tmr)
{
sim_debug (DBG_REGR, &sysd_dev, "tmr_csr_rd(tmr=%d) - 0x%X", tmr, tmr_csr[tmr]);
sim_debug_bits_hdr (DBG_REGR, &sysd_dev, " ", tmr_csr_bits, tmr_csr[tmr], tmr_csr[tmr], 1);
return tmr_csr[tmr];
}
void tmr_csr_wr (int32 tmr, int32 val) void tmr_csr_wr (int32 tmr, int32 val)
{ {
int32 before_tmr_csr; int32 before_tmr_csr;
@ -1520,20 +1524,23 @@ if ((tmr < 0) || (tmr > 1))
return; return;
before_tmr_csr = tmr_csr[tmr]; before_tmr_csr = tmr_csr[tmr];
sim_debug (DBG_REGW, &sysd_dev, "tmr_csr_wr(tmr=%d) - 0x%X", tmr, val); sim_debug (DBG_REGW, &sysd_dev, "tmr_csr_wr(tmr=%d) - Writing 0x%X", tmr, val);
sim_debug_bits_hdr (DBG_REGW, &sysd_dev, " ", tmr_csr_bits, val, val, 1); sim_debug_bits_hdr (DBG_REGW, &sysd_dev, " ", tmr_csr_bits, val, val, 1);
if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */ if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */
sim_cancel (&sysd_unit[tmr]); /* cancel timer */
if (tmr_csr[tmr] & TMR_CSR_RUN) /* run 1 -> 0? */ if (tmr_csr[tmr] & TMR_CSR_RUN) /* run 1 -> 0? */
tmr_tir[tmr] = tmr_tir_rd (tmr); /* update itr */ tmr_tir[tmr] = tmr_tir_rd (tmr); /* update itr */
sim_cancel (&sysd_unit[tmr]); /* cancel timer */
} }
tmr_csr[tmr] = tmr_csr[tmr] & ~(val & TMR_CSR_W1C); /* W1C csr */ tmr_csr[tmr] = tmr_csr[tmr] & ~(val & TMR_CSR_W1C); /* W1C csr */
tmr_csr[tmr] = (tmr_csr[tmr] & ~TMR_CSR_RW) | /* new r/w */ tmr_csr[tmr] = (tmr_csr[tmr] & ~TMR_CSR_RW) | /* new r/w */
(val & TMR_CSR_RW); (val & TMR_CSR_RW);
sim_debug_bits_hdr (DBG_REGW, &sysd_dev, "tmr_csr_wr() - Result", tmr_csr_bits, before_tmr_csr, tmr_csr[tmr], 1); sim_debug (DBG_REGW, &sysd_dev, "tmr_csr_wr(tmr=%d) - ", tmr);
if (val & TMR_CSR_XFR) /* xfr set? */ sim_debug_bits_hdr (DBG_REGW, &sysd_dev, "Result", tmr_csr_bits, before_tmr_csr, tmr_csr[tmr], 1);
if (val & TMR_CSR_XFR) { /* xfr set? */
tmr_tir[tmr] = tmr_tnir[tmr]; tmr_tir[tmr] = tmr_tnir[tmr];
sim_debug (DBG_REGW, &sysd_dev, "tmr_csr_wr(tmr=%d) - XFR set TIR=0x%X\n", tmr, tmr_tir[tmr]);
}
if (val & TMR_CSR_RUN) { /* run? */ if (val & TMR_CSR_RUN) { /* run? */
if (val & TMR_CSR_XFR) /* new tir? */ if (val & TMR_CSR_XFR) /* new tir? */
sim_cancel (&sysd_unit[tmr]); /* stop prev */ sim_cancel (&sysd_unit[tmr]); /* stop prev */
@ -1546,8 +1553,8 @@ else
if (tmr_tir[tmr] == 0) /* if ovflo, */ if (tmr_tir[tmr] == 0) /* if ovflo, */
tmr_tir[tmr] = tmr_tnir[tmr]; /* reload tir */ tmr_tir[tmr] = tmr_tnir[tmr]; /* reload tir */
} }
if ((tmr_csr[tmr] & (TMR_CSR_DON | TMR_CSR_IE)) != /* update int */ if ((before_tmr_csr & (TMR_CSR_DON | TMR_CSR_IE)) &&
(TMR_CSR_DON | TMR_CSR_IE)) { ((tmr_csr[tmr] & (TMR_CSR_DON | TMR_CSR_IE)) == 0)) {/* update int */
sim_debug (DBG_INT, &sysd_dev, "tmr_csr_wr(tmr=%d) - CLR_INT\n", tmr); sim_debug (DBG_INT, &sysd_dev, "tmr_csr_wr(tmr=%d) - CLR_INT\n", tmr);
if (tmr) if (tmr)
CLR_INT (TMR1); CLR_INT (TMR1);
@ -1586,7 +1593,7 @@ if (new_tir < tmr_tir[tmr]) { /* ovflo? */
tmr_sched (tmr); /* reactivate */ tmr_sched (tmr); /* reactivate */
} }
if (tmr_csr[tmr] & TMR_CSR_IE) { /* set int req */ if (tmr_csr[tmr] & TMR_CSR_IE) { /* set int req */
sim_debug (DBG_INT, &sysd_dev, "tmr_csr_wr(tmr=%d) - SET_INT\n", tmr); sim_debug (DBG_INT, &sysd_dev, "tmr_incr(tmr=%d) - SET_INT\n", tmr);
if (tmr) if (tmr)
SET_INT (TMR1); SET_INT (TMR1);
else else
@ -1605,27 +1612,33 @@ else {
void tmr_sched (int32 tmr) void tmr_sched (int32 tmr)
{ {
uint32 usecs_sched = tmr_tir[tmr] ? (~tmr_tir[tmr] + 1) : 0xFFFFFFFF; uint32 usecs_sched = tmr_tir[tmr] ? (~tmr_tir[tmr] + 1) : 0xFFFFFFFF;
double usecs_sched_d = tmr_tir[tmr] ? (double)(~tmr_tir[tmr] + 1) : (1.0 + (double)0xFFFFFFFFu);
sim_cancel (&sysd_unit[tmr]); /* Make sure not active */
if (sysd_unit[tmr].usecs_remaining != 0.0)
sim_debug (DBG_SCHD, &sysd_dev, "tmr_sched(tmr=%d) - BUG - usecs remaining = %.0f usecs\n", tmr, sysd_unit[tmr].usecs_remaining);
if ((ADDR_IS_ROM(fault_PC)) && /* running from ROM and */ if ((ADDR_IS_ROM(fault_PC)) && /* running from ROM and */
(usecs_sched < TMR_INC)) { /* short delay? */ (usecs_sched < TMR_INC)) { /* short delay? */
tmr_inst[tmr] = TRUE; /* wait for instructions */ tmr_inst[tmr] = TRUE; /* wait for instructions */
sim_debug (DBG_SCHD, &sysd_dev, "tmr_sched(tmr=%d) - after %u instructions\n", tmr, usecs_sched);
sim_activate (&sysd_unit[tmr], usecs_sched); sim_activate (&sysd_unit[tmr], usecs_sched);
sim_debug (DBG_SCHD, &sysd_dev, "tmr_sched(tmr=%d) - after %u instructions - activate after: %.0f usecs\n", tmr, usecs_sched, sim_activate_time_usecs (&sysd_unit[tmr]));
} }
else { else {
tmr_inst[tmr] = FALSE; tmr_inst[tmr] = FALSE;
sim_debug (DBG_SCHD, &sysd_dev, "tmr_sched(tmr=%d) - after %u usecs\n", tmr, usecs_sched); sim_activate_after_d (&sysd_unit[tmr], usecs_sched_d);
sim_activate_after (&sysd_unit[tmr], usecs_sched); sim_debug (DBG_SCHD, &sysd_dev, "tmr_sched(tmr=%d) - after %.0f usecs - activate after: %.0f usecs\n", tmr, usecs_sched_d, sim_activate_time_usecs (&sysd_unit[tmr]));
} }
} }
int32 tmr0_inta (void) int32 tmr0_inta (void)
{ {
sim_debug (DBG_INT, &sysd_dev, "tmr0_inta() - Int Ack - Vector=0x%X\n", tmr_tivr[0]);
return tmr_tivr[0]; return tmr_tivr[0];
} }
int32 tmr1_inta (void) int32 tmr1_inta (void)
{ {
sim_debug (DBG_INT, &sysd_dev, "tmr1_inta() - Int Ack - Vector=0x%X\n", tmr_tivr[1]);
return tmr_tivr[1]; return tmr_tivr[1];
} }