BESM6: Schedule the serial line timer by instruction count when I/O is pending, and by wallclock time otherwise. This achieves a good TTY output rate even when the CPU is busy with a user process.
This commit is contained in:
parent
aa16857edc
commit
bd260dd523
6 changed files with 22 additions and 34 deletions
|
@ -708,6 +708,12 @@ void check_initial_setup ()
|
||||||
/* 7 р. яч. ЗАНЯТА - разр любые приказы */
|
/* 7 р. яч. ЗАНЯТА - разр любые приказы */
|
||||||
const t_value ALL_REQS_ENABLED = 1 << 6;
|
const t_value ALL_REQS_ENABLED = 1 << 6;
|
||||||
|
|
||||||
|
if (!vt_is_idle()) {
|
||||||
|
/* Avoid sending setup requests while the OS
|
||||||
|
* is still printing boot-up messages.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ((memory[TAKEN] & SETUP_REQS_ENABLED) == 0 ||
|
if ((memory[TAKEN] & SETUP_REQS_ENABLED) == 0 ||
|
||||||
(memory[TAKEN] & ALL_REQS_ENABLED) != 0 ||
|
(memory[TAKEN] & ALL_REQS_ENABLED) != 0 ||
|
||||||
(MGRP & GRP_PANEL_REQ) == 0) {
|
(MGRP & GRP_PANEL_REQ) == 0) {
|
||||||
|
@ -1427,15 +1433,8 @@ void cpu_one_inst ()
|
||||||
|
|
||||||
/* Не находимся ли мы в цикле "ЖДУ" диспака? */
|
/* Не находимся ли мы в цикле "ЖДУ" диспака? */
|
||||||
if (RUU == 047 && PC == 04440 && RK == 067704440) {
|
if (RUU == 047 && PC == 04440 && RK == 067704440) {
|
||||||
/* Если периферия простаивает, освобождаем процессор
|
check_initial_setup ();
|
||||||
* до следующего тика таймера. */
|
sim_idle(0, TRUE);
|
||||||
if (vt_is_idle()) {
|
|
||||||
check_initial_setup ();
|
|
||||||
sim_idle (0, TRUE);
|
|
||||||
} else if (sim_activate_time(tty_unit) > 1000*MSEC/300) {
|
|
||||||
/* Insert a TTY interrupt if a regular one is too far away */
|
|
||||||
sim_activate_abs(tty_unit, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,7 @@ enum {
|
||||||
|
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
extern UNIT tty_unit[];
|
extern UNIT tty_unit[];
|
||||||
|
extern UNIT clocks[];
|
||||||
extern t_value memory [MEMSIZE];
|
extern t_value memory [MEMSIZE];
|
||||||
extern t_value pult [8];
|
extern t_value pult [8];
|
||||||
extern uint32 PC, RAU, RUU;
|
extern uint32 PC, RAU, RUU;
|
||||||
|
@ -326,7 +327,6 @@ int disk_errors (void);
|
||||||
*/
|
*/
|
||||||
void printer_control (int num, uint32 cmd);
|
void printer_control (int num, uint32 cmd);
|
||||||
void printer_hammer (int num, int pos, uint32 mask);
|
void printer_hammer (int num, int pos, uint32 mask);
|
||||||
int printer_is_idle (void);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Терминалы (телетайпы, видеотоны, "Консулы").
|
* Терминалы (телетайпы, видеотоны, "Консулы").
|
||||||
|
@ -344,7 +344,6 @@ int vt_is_idle (void);
|
||||||
*/
|
*/
|
||||||
void fs_control (int num, uint32 cmd);
|
void fs_control (int num, uint32 cmd);
|
||||||
int fs_read (int num);
|
int fs_read (int num);
|
||||||
int fs_is_idle (void);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Отладочная выдача.
|
* Отладочная выдача.
|
||||||
|
|
|
@ -317,15 +317,3 @@ offset_gost_write (int num, FILE *fout)
|
||||||
memset(dev->line, 0, sizeof (dev->line));
|
memset(dev->line, 0, sizeof (dev->line));
|
||||||
dev->length = dev->strikes = 0;
|
dev->length = dev->strikes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Выясняем, остановлены ли АЦПУ. Нужно для входа в "спящий" режим.
|
|
||||||
*/
|
|
||||||
int printer_is_idle ()
|
|
||||||
{
|
|
||||||
if (sim_is_active(&printer_unit[0]))
|
|
||||||
return 0;
|
|
||||||
if (sim_is_active(&printer_unit[1]))
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
|
@ -279,11 +279,6 @@ int fs_read(int num) {
|
||||||
return FS[num];
|
return FS[num];
|
||||||
}
|
}
|
||||||
|
|
||||||
int fs_is_idle (void)
|
|
||||||
{
|
|
||||||
return fs_state[0] == FS_IDLE && fs_state[1] == FS_IDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char
|
unsigned char
|
||||||
unicode_to_gost (unsigned short val)
|
unicode_to_gost (unsigned short val)
|
||||||
{
|
{
|
||||||
|
|
|
@ -238,12 +238,19 @@ t_stat vt_clk (UNIT * this)
|
||||||
|
|
||||||
/* Polling sockets for transmission. */
|
/* Polling sockets for transmission. */
|
||||||
tmxr_poll_tx (&tty_desc);
|
tmxr_poll_tx (&tty_desc);
|
||||||
|
/* If the TTY system is not idle, schedule the next interrupt
|
||||||
/* We'll get a guaranteed interrupt rate of 250 Hz (wallclock)
|
* by instruction count using the target interrupt rate of 300 Hz;
|
||||||
* plus additional interrupts during the idle loop for speedup
|
* otherwise we can wait for a roughly equivalent wallclock time period,
|
||||||
* (see besm6_cpu.c).
|
* e.g. until the next 250 Hz wallclock interrupt, but making sure
|
||||||
|
* that the model time interval between GRP_SERIAL interrupts
|
||||||
|
* is never less than expected.
|
||||||
|
* Using sim_activate_after() would be more straightforward (no need for a check
|
||||||
|
* as the host is faster than the target), but likely less efficient for idling.
|
||||||
*/
|
*/
|
||||||
return sim_clock_coschedule (this, tmr_poll);
|
if (vt_is_idle() && sim_activate_time(clocks) > 1000*MSEC/300)
|
||||||
|
return sim_clock_coschedule (this, tmr_poll);
|
||||||
|
else
|
||||||
|
return sim_activate(this, 1000*MSEC/300);
|
||||||
}
|
}
|
||||||
|
|
||||||
t_stat tty_setmode (UNIT *u, int32 val, char *cptr, void *desc)
|
t_stat tty_setmode (UNIT *u, int32 val, char *cptr, void *desc)
|
||||||
|
|
|
@ -29,7 +29,7 @@ attach -e disk2 alt2048.bin
|
||||||
;
|
;
|
||||||
; Подключаем АЦПУ.
|
; Подключаем АЦПУ.
|
||||||
;
|
;
|
||||||
attach prn0 /dev/tty
|
attach prn0 output.txt
|
||||||
|
|
||||||
;
|
;
|
||||||
; Активируем операторский терминал,
|
; Активируем операторский терминал,
|
||||||
|
|
Loading…
Add table
Reference in a new issue