BESM6: Convert to simh calibrated clocks and idling
This commit is contained in:
parent
aa60cc72ad
commit
db44518808
7 changed files with 52 additions and 82 deletions
|
@ -53,18 +53,15 @@
|
||||||
#include "besm6_defs.h"
|
#include "besm6_defs.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#undef SOFT_CLOCK
|
|
||||||
|
|
||||||
t_value memory [MEMSIZE];
|
t_value memory [MEMSIZE];
|
||||||
uint32 PC, RK, Aex, M [NREGS], RAU, RUU;
|
uint32 PC, RK, Aex, M [NREGS], RAU, RUU;
|
||||||
t_value ACC, RMR, GRP, MGRP;
|
t_value ACC, RMR, GRP, MGRP;
|
||||||
uint32 PRP, MPRP;
|
uint32 PRP, MPRP;
|
||||||
uint32 READY, READY2; /* ready flags of various devices */
|
uint32 READY, READY2; /* ready flags of various devices */
|
||||||
|
int32 tmr_poll = CLK_DELAY; /* pgm timer poll */
|
||||||
|
|
||||||
extern const char *scp_errors[];
|
extern const char *scp_errors[];
|
||||||
|
|
||||||
|
@ -133,6 +130,8 @@ REG cpu_reg[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
MTAB cpu_mod[] = {
|
MTAB cpu_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "IDLE", "IDLE", &sim_set_idle, &sim_show_idle, NULL, "Display idle detection mode" },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOIDLE", &sim_clr_idle, NULL, NULL, "Disables idle detection" },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -311,33 +310,6 @@ t_stat cpu_deposit (t_value val, t_addr addr, UNIT *uptr, int32 sw)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Функция вызывается каждые 4 миллисекунды реального времени.
|
|
||||||
*/
|
|
||||||
static void cpu_sigalarm (int signum)
|
|
||||||
{
|
|
||||||
static unsigned counter;
|
|
||||||
|
|
||||||
++counter;
|
|
||||||
|
|
||||||
#ifndef SOFT_CLOCK
|
|
||||||
/* В 9-й части частота таймера 250 Гц (4 мс). */
|
|
||||||
GRP |= GRP_TIMER;
|
|
||||||
|
|
||||||
/* Медленный таймер: должен быть 16 Гц.
|
|
||||||
* Но от него почему-то зависит вывод на терминалы,
|
|
||||||
* поэтому ускорим. */
|
|
||||||
if ((counter & 3) == 0) {
|
|
||||||
GRP |= GRP_SLOW_CLK;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Перерисовка панели каждые 64 миллисекунды. */
|
|
||||||
if ((counter & 15) == 0) {
|
|
||||||
redraw_panel = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset routine
|
* Reset routine
|
||||||
*/
|
*/
|
||||||
|
@ -367,19 +339,6 @@ t_stat cpu_reset (DEVICE *dptr)
|
||||||
sim_brk_types = SWMASK ('E') | SWMASK('R') | SWMASK('W');
|
sim_brk_types = SWMASK ('E') | SWMASK('R') | SWMASK('W');
|
||||||
sim_brk_dflt = SWMASK ('E');
|
sim_brk_dflt = SWMASK ('E');
|
||||||
|
|
||||||
struct itimerval itv;
|
|
||||||
|
|
||||||
/* Чтобы ход часов в ДИСПАКе соответствал реальному времени,
|
|
||||||
* используем сигналы от системного таймера. */
|
|
||||||
signal (SIGALRM, cpu_sigalarm);
|
|
||||||
itv.it_interval.tv_sec = 0;
|
|
||||||
itv.it_interval.tv_usec = 4000;
|
|
||||||
itv.it_value.tv_sec = 0;
|
|
||||||
itv.it_value.tv_usec = 4000;
|
|
||||||
if (setitimer (ITIMER_REAL, &itv, 0) < 0) {
|
|
||||||
perror ("setitimer");
|
|
||||||
return SCPE_TIMER;
|
|
||||||
}
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -807,9 +766,9 @@ void cpu_one_inst ()
|
||||||
corr_stack = 0;
|
corr_stack = 0;
|
||||||
word = mmu_fetch (PC);
|
word = mmu_fetch (PC);
|
||||||
if (RUU & RUU_RIGHT_INSTR)
|
if (RUU & RUU_RIGHT_INSTR)
|
||||||
RK = word; /* get right instruction */
|
RK = (uint32)word; /* get right instruction */
|
||||||
else
|
else
|
||||||
RK = word >> 24; /* get left instruction */
|
RK = (uint32)(word >> 24);/* get left instruction */
|
||||||
|
|
||||||
RK &= BITS(24);
|
RK &= BITS(24);
|
||||||
|
|
||||||
|
@ -1475,11 +1434,7 @@ void cpu_one_inst ()
|
||||||
|
|
||||||
/* Если периферия простаивает, освобождаем процессор
|
/* Если периферия простаивает, освобождаем процессор
|
||||||
* до следующего тика таймера. */
|
* до следующего тика таймера. */
|
||||||
if (vt_is_idle() &&
|
sim_idle (0, TRUE);
|
||||||
printer_is_idle() && fs_is_idle()) {
|
|
||||||
check_initial_setup ();
|
|
||||||
pause ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1739,43 +1694,56 @@ t_stat sim_instr (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t_stat slow_clk (UNIT * this)
|
|
||||||
{
|
|
||||||
/*besm6_debug ("*** таймер 80 мсек");*/
|
|
||||||
GRP |= GRP_SLOW_CLK;
|
|
||||||
return sim_activate (this, MSEC*125/2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* В 9-й части частота таймера 250 Гц (4 мс),
|
* В 9-й части частота таймера 250 Гц (4 мс),
|
||||||
* в жизни - 50 Гц (20 мс).
|
* в жизни - 50 Гц (20 мс).
|
||||||
*/
|
*/
|
||||||
t_stat fast_clk (UNIT * this)
|
t_stat fast_clk (UNIT * this)
|
||||||
{
|
{
|
||||||
|
static unsigned counter;
|
||||||
|
|
||||||
|
++counter;
|
||||||
|
|
||||||
/*besm6_debug ("*** таймер 20 мсек");*/
|
/*besm6_debug ("*** таймер 20 мсек");*/
|
||||||
GRP |= GRP_TIMER;
|
GRP |= GRP_TIMER;
|
||||||
return sim_activate (this, 20*MSEC);
|
|
||||||
|
/* Медленный таймер: должен быть 16 Гц.
|
||||||
|
* Но от него почему-то зависит вывод на терминалы,
|
||||||
|
* поэтому ускорим. */
|
||||||
|
if ((counter & 3) == 0) {
|
||||||
|
/*besm6_debug ("*** таймер 80 мсек");*/
|
||||||
|
GRP |= GRP_SLOW_CLK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Перерисовка панели каждые 64 миллисекунды. */
|
||||||
|
if ((counter & 15) == 0) {
|
||||||
|
redraw_panel = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmr_poll = sim_rtcn_calb (CLK_TPS, 0); /* calibrate clock */
|
||||||
|
return sim_activate_after (this, 1000000/CLK_TPS); /* reactivate unit */
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIT clocks[] = {
|
UNIT clocks[] = {
|
||||||
{ UDATA(slow_clk, 0, 0) }, /* 10 р, 16 Гц */
|
{ UDATA(fast_clk, 0, 0), CLK_DELAY }, /* 40 р, 50 Гц */
|
||||||
{ UDATA(fast_clk, 0, 0) }, /* 40 р, 50 Гц */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
t_stat clk_reset (DEVICE * dev)
|
t_stat clk_reset (DEVICE * dev)
|
||||||
{
|
{
|
||||||
|
sim_register_clock_unit (&clocks[0]);
|
||||||
|
|
||||||
/* Схема автозапуска включается по нереализованной кнопке "МР" */
|
/* Схема автозапуска включается по нереализованной кнопке "МР" */
|
||||||
#ifdef SOFT_CLOCK
|
|
||||||
sim_activate (&clocks[0], MSEC*125/2);
|
if (!sim_is_running) { /* RESET (not IORESET)? */
|
||||||
return sim_activate (&clocks[1], 20*MSEC);
|
tmr_poll = sim_rtcn_init (clocks[0].wait, 0); /* init timer */
|
||||||
#else
|
sim_activate (&clocks[0], tmr_poll); /* activate unit */
|
||||||
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEVICE clock_dev = {
|
DEVICE clock_dev = {
|
||||||
"CLK", clocks, NULL, NULL,
|
"CLK", clocks, NULL, NULL,
|
||||||
2, 0, 0, 0, 0, 0,
|
1, 0, 0, 0, 0, 0,
|
||||||
NULL, NULL, &clk_reset,
|
NULL, NULL, &clk_reset,
|
||||||
NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL,
|
||||||
DEV_DEBUG
|
DEV_DEBUG
|
||||||
|
|
|
@ -121,8 +121,10 @@ enum {
|
||||||
/*
|
/*
|
||||||
* Считаем, что моделируеммая машина имеет опорную частоту 10 МГц.
|
* Считаем, что моделируеммая машина имеет опорную частоту 10 МГц.
|
||||||
*/
|
*/
|
||||||
#define USEC 10 /* одна микросекунда - десять тактов */
|
#define USEC 1 /* одна микросекунда - десять тактов */
|
||||||
#define MSEC (1000*USEC) /* одна миллисекунда */
|
#define MSEC (1000*USEC) /* одна миллисекунда */
|
||||||
|
#define CLK_TPS 250 /* Fast Clock Ticks Per Second (every 4ms) */
|
||||||
|
#define CLK_DELAY 4000 /* Uncalibrated instructions per clock tick */
|
||||||
|
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
extern t_value memory [MEMSIZE];
|
extern t_value memory [MEMSIZE];
|
||||||
|
|
|
@ -519,7 +519,7 @@ void disk_ctl (int ctlr, uint32 cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ждём события от устройства. */
|
/* Ждём события от устройства. */
|
||||||
sim_activate (u, 20*USEC); /* Ускорим для отладки. */
|
sim_activate_after (u, 20*USEC); /* Ускорим для отладки. */
|
||||||
|
|
||||||
} else if (cmd & BBIT(11)) {
|
} else if (cmd & BBIT(11)) {
|
||||||
/* Выбора номера устройства и занесение в регистр маски КМД.
|
/* Выбора номера устройства и занесение в регистр маски КМД.
|
||||||
|
@ -614,7 +614,7 @@ void disk_ctl (int ctlr, uint32 cmd)
|
||||||
disk_read_header (u);
|
disk_read_header (u);
|
||||||
|
|
||||||
/* Ждём события от устройства. */
|
/* Ждём события от устройства. */
|
||||||
sim_activate (u, 20*USEC); /* Ускорим для отладки. */
|
sim_activate_after (u, 20*USEC); /* Ускорим для отладки. */
|
||||||
break;
|
break;
|
||||||
case 010: /* гашение PC */
|
case 010: /* гашение PC */
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
@ -346,8 +346,8 @@ void drum (int ctlr, uint32 cmd)
|
||||||
/* Ждём события от устройства.
|
/* Ждём события от устройства.
|
||||||
* Согласно данным из книжки Мазного Г.Л.,
|
* Согласно данным из книжки Мазного Г.Л.,
|
||||||
* даём 20 мсек на обмен, или 200 тыс.тактов. */
|
* даём 20 мсек на обмен, или 200 тыс.тактов. */
|
||||||
/*sim_activate (u, 20*MSEC);*/
|
/*sim_activate_after (u, 20*MSEC);*/
|
||||||
sim_activate (u, 20*USEC); /* Ускорим для отладки. */
|
sim_activate_after (u, 20*USEC); /* Ускорим для отладки. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -159,7 +159,7 @@ void printer_control (int num, uint32 cmd)
|
||||||
dev->feed = LINEFEED_SYNC;
|
dev->feed = LINEFEED_SYNC;
|
||||||
READY &= ~(PRN1_LINEFEED >> num);
|
READY &= ~(PRN1_LINEFEED >> num);
|
||||||
if (dev->rampup)
|
if (dev->rampup)
|
||||||
sim_activate (u, dev->rampup);
|
sim_activate_after (u, dev->rampup);
|
||||||
dev->rampup = 0;
|
dev->rampup = 0;
|
||||||
break;
|
break;
|
||||||
case 10: /* motor and ribbon off */
|
case 10: /* motor and ribbon off */
|
||||||
|
@ -208,7 +208,7 @@ t_stat printer_event (UNIT *u)
|
||||||
GRP |= GRP_PRN1_SYNC >> num;
|
GRP |= GRP_PRN1_SYNC >> num;
|
||||||
++dev->curchar;
|
++dev->curchar;
|
||||||
/* For next char */
|
/* For next char */
|
||||||
sim_activate (u, 1400*USEC);
|
sim_activate_after (u, 1400*USEC);
|
||||||
if (dev->feed && --dev->feed == 0) {
|
if (dev->feed && --dev->feed == 0) {
|
||||||
READY |= PRN1_LINEFEED >> num;
|
READY |= PRN1_LINEFEED >> num;
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ t_stat printer_event (UNIT *u)
|
||||||
if (printer_dev.dctrl)
|
if (printer_dev.dctrl)
|
||||||
besm6_debug(">>> АЦПУ%d 'ноль'", num);
|
besm6_debug(">>> АЦПУ%d 'ноль'", num);
|
||||||
/* For first sync after "zero" */
|
/* For first sync after "zero" */
|
||||||
sim_activate (u, 1000*USEC);
|
sim_activate_after (u, 1000*USEC);
|
||||||
}
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -334,9 +334,9 @@ offset_gost_write (int num, FILE *fout)
|
||||||
*/
|
*/
|
||||||
int printer_is_idle ()
|
int printer_is_idle ()
|
||||||
{
|
{
|
||||||
if ((printer_unit[0].flags & UNIT_ATT) && acpu[0].rampup == 0)
|
if (sim_is_active(&printer_unit[0]))
|
||||||
return 0;
|
return 0;
|
||||||
if ((printer_unit[1].flags & UNIT_ATT) && acpu[1].rampup == 0)
|
if (sim_is_active(&printer_unit[1]))
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
* authorization from Leonid Broukhis and Serge Vakulenko.
|
* authorization from Leonid Broukhis and Serge Vakulenko.
|
||||||
*/
|
*/
|
||||||
#include "besm6_defs.h"
|
#include "besm6_defs.h"
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
t_stat fs_event (UNIT *u);
|
t_stat fs_event (UNIT *u);
|
||||||
t_stat uvvk_event (UNIT *u);
|
t_stat uvvk_event (UNIT *u);
|
||||||
|
@ -169,7 +168,7 @@ void fs_control (int num, uint32 cmd)
|
||||||
if (fs_state[num] == FS_IDLE)
|
if (fs_state[num] == FS_IDLE)
|
||||||
besm6_debug("<<< ФС1500-%d протяжка без мотора", num);
|
besm6_debug("<<< ФС1500-%d протяжка без мотора", num);
|
||||||
else if (fs_state[num] != FS_TAIL) {
|
else if (fs_state[num] != FS_TAIL) {
|
||||||
sim_activate (u, FS_RATE);
|
sim_activate_after (u, FS_RATE);
|
||||||
bytecnt++;
|
bytecnt++;
|
||||||
} else {
|
} else {
|
||||||
if (! isfifo[num]) {
|
if (! isfifo[num]) {
|
||||||
|
|
|
@ -82,9 +82,10 @@ void tt_print();
|
||||||
void consul_receive();
|
void consul_receive();
|
||||||
t_stat vt_clk(UNIT *);
|
t_stat vt_clk(UNIT *);
|
||||||
extern char *get_sim_sw (char *cptr);
|
extern char *get_sim_sw (char *cptr);
|
||||||
|
extern int32 tmr_poll; /* calibrated clock timer poll */
|
||||||
|
|
||||||
UNIT tty_unit [] = {
|
UNIT tty_unit [] = {
|
||||||
{ UDATA (vt_clk, UNIT_DIS, 0) }, /* fake unit, clock */
|
{ UDATA (vt_clk, UNIT_DIS|UNIT_IDLE, 0) }, /* fake unit, clock */
|
||||||
{ UDATA (NULL, UNIT_SEQ, 0) },
|
{ UDATA (NULL, UNIT_SEQ, 0) },
|
||||||
{ UDATA (NULL, UNIT_SEQ, 0) },
|
{ UDATA (NULL, UNIT_SEQ, 0) },
|
||||||
{ UDATA (NULL, UNIT_SEQ, 0) },
|
{ UDATA (NULL, UNIT_SEQ, 0) },
|
||||||
|
@ -160,7 +161,7 @@ t_stat tty_reset (DEVICE *dptr)
|
||||||
/* Готовность устройства в READY2 инверсная, а устройство всегда готово */
|
/* Готовность устройства в READY2 инверсная, а устройство всегда готово */
|
||||||
/* Провоцируем передачу */
|
/* Провоцируем передачу */
|
||||||
PRP |= CONS_CAN_PRINT[0] | CONS_CAN_PRINT[1];
|
PRP |= CONS_CAN_PRINT[0] | CONS_CAN_PRINT[1];
|
||||||
return sim_activate (tty_unit, 1000*MSEC/300);
|
return sim_clock_coschedule (tty_unit, 5*tmr_poll);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 19 р ГРП, 300 Гц */
|
/* 19 р ГРП, 300 Гц */
|
||||||
|
@ -223,7 +224,7 @@ t_stat vt_clk (UNIT * this)
|
||||||
/* Опрашиваем сокеты на передачу. */
|
/* Опрашиваем сокеты на передачу. */
|
||||||
tmxr_poll_tx (&tty_desc);
|
tmxr_poll_tx (&tty_desc);
|
||||||
|
|
||||||
return sim_activate (this, 1000*MSEC/300);
|
return sim_clock_coschedule (this, 5*tmr_poll);
|
||||||
}
|
}
|
||||||
|
|
||||||
t_stat tty_setmode (UNIT *u, int32 val, char *cptr, void *desc)
|
t_stat tty_setmode (UNIT *u, int32 val, char *cptr, void *desc)
|
||||||
|
|
Loading…
Add table
Reference in a new issue