cpu/control/
timing.rs

1//! Instruction and event timing.
2//!
3//! This module deals with the relationship between actual time and the
4//! time taken by events in the simulator.
5//!
6//! In the physical TX-2 machine, the operator has some control over
7//! the execution speed of the computer, and eventually we will
8//! accomodate this control, but for now this is not implemented.
9
10use super::memory::*;
11use base::instruction::Opcode;
12use base::prelude::*;
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
15enum MemoryType {
16    S,
17    T,
18    V,
19}
20
21fn address_to_memory_type(addr: &Address) -> MemoryType {
22    let addr: u32 = u32::from(addr);
23    if addr < T_MEMORY_START {
24        MemoryType::S
25    } else if addr < V_MEMORY_START {
26        MemoryType::T
27    } else {
28        MemoryType::V
29    }
30}
31
32/// These figures are taken, approximately, from section 7-8 of the
33/// User Handbook.
34pub(crate) fn estimate_instruction_ns(
35    inst_from: Address,
36    op: u8,
37    defer_from: Option<Address>,
38    operand_from: Option<Address>,
39) -> u64 {
40    // Units of tenths are tenths of microseconds
41    let inst_loaded_from = address_to_memory_type(&inst_from);
42    let mut tenths: u64 = if inst_loaded_from == MemoryType::S {
43        80
44    } else {
45        60
46    };
47    // instruction from : add 20 for T or 40 for S memory
48    tenths += match inst_loaded_from {
49        MemoryType::V | MemoryType::T => 0,
50        MemoryType::S => 20,
51    };
52    if let Ok(opcode) = Opcode::try_from(op) {
53        tenths += match opcode {
54            Opcode::Opr => 72,
55            Opcode::Jmp => 56,
56            Opcode::Jpx => 76,
57            Opcode::Jnx => 76,
58            Opcode::Aux => 116,
59            Opcode::Rsx => 108,
60            Opcode::Skx => 80,
61            Opcode::Exx => 112,
62            Opcode::Adx => 84,
63            Opcode::Dpx => 100,
64            Opcode::Skm => 96,
65            Opcode::Lde => 68,
66            Opcode::Spf => 88,
67            Opcode::Spg => 96,
68            Opcode::Lda => 64,
69            Opcode::Ldb => 68,
70            Opcode::Ldc => 68,
71            Opcode::Ldd => 68,
72            Opcode::Ste => 68,
73            Opcode::Flf => 68,
74            Opcode::Flg => 84,
75            Opcode::Sta => 68,
76            Opcode::Stb => 68,
77            Opcode::Stc => 68,
78            Opcode::Std => 68,
79            Opcode::Ite => 64,
80            Opcode::Ita => 68,
81            Opcode::Una => 48,
82            Opcode::Sed => 80,
83            Opcode::Jov => 60,
84            Opcode::Jpa => 60,
85            Opcode::Jna => 60,
86            Opcode::Exa => 48,
87            Opcode::Ins => 68,
88            Opcode::Com => 68,
89            Opcode::Tsd => 76,
90            Opcode::Cya => 382,
91            Opcode::Cyb => 1060,
92            Opcode::Cab => 1072,
93            Opcode::Noa => 68,
94            Opcode::Dsa => 52,
95            Opcode::Nab => 320,
96            Opcode::Add => 68,
97            Opcode::Sca => 1060,
98            Opcode::Scb => 1044,
99            Opcode::Sab => 1072,
100            Opcode::Tly => 68,
101            Opcode::Div => 770,
102            Opcode::Mul => 100,
103            Opcode::Sub => 68,
104        }
105    }
106    if operand_from == Some(inst_from) || defer_from == Some(inst_from) {
107        tenths += 20;
108    }
109    if operand_from == defer_from {
110        tenths += 20;
111    }
112
113    // Convert from tenths of a microsecond to nanoseconds.
114    tenths * 100
115}