1use std::fmt::Write;
4
5use base::prelude::*;
6use std::time::Duration;
7
8use crate::diagnostics::CurrentInstructionDiagnostics;
9
10use super::super::context::Context;
11use super::super::event::InputEvent;
12use super::super::io::{InputFlagRaised, TransferFailed, Unit, UnitStatus};
13use super::super::*;
14
15#[derive(Debug)]
16pub(crate) struct TrapCircuit {
17 mode: Unsigned12Bit,
18 set_metabits_disabled: bool,
19}
20
21impl TrapCircuit {
22 const TRAP_ON_MARKED_INSTRUCTION: Unsigned12Bit = Unsigned12Bit::MAX.and(0o000_001_u16);
25
26 const TRAP_ON_DEFERRED_ADDRESS: Unsigned12Bit = Unsigned12Bit::MAX.and(0o000_002_u16);
30
31 const TRAP_ON_OPERAND: Unsigned12Bit = Unsigned12Bit::MAX.and(0o000_004_u16);
35
36 const TRAP_ON_CHANGED_SEQUENCE: Unsigned12Bit = Unsigned12Bit::MAX.and(0o000_010_u16);
41
42 const SET_METABITS_OF_INSTRUCTIONS: Unsigned12Bit = Unsigned12Bit::MAX.and(0o000_100_u16);
45
46 const SET_METABITS_OF_DEFERRED_ADDRESSES: Unsigned12Bit = Unsigned12Bit::MAX.and(0o000_200_u16);
48
49 const SET_METABITS_OF_OPERANDS: Unsigned12Bit = Unsigned12Bit::MAX.and(0o000_400_u16);
51
52 pub(crate) const fn new() -> TrapCircuit {
53 TrapCircuit {
54 mode: Unsigned12Bit::ZERO,
55 set_metabits_disabled: false,
56 }
57 }
58
59 pub(crate) fn is_set_metabits_disabled(&self) -> bool {
62 self.set_metabits_disabled
63 }
64
65 pub(crate) fn set_metabits_disabled(&mut self, disable: bool) {
68 self.set_metabits_disabled = disable;
69 }
70
71 pub(crate) fn set_metabits_of_instructions(&self) -> bool {
74 !self.is_set_metabits_disabled() && self.mode & Self::SET_METABITS_OF_INSTRUCTIONS != 0
75 }
76
77 pub(crate) fn set_metabits_of_deferred_addresses(&self) -> bool {
80 !self.is_set_metabits_disabled()
81 && self.mode & Self::SET_METABITS_OF_DEFERRED_ADDRESSES != 0
82 }
83
84 pub(crate) fn set_metabits_of_operands(&self) -> bool {
87 !self.is_set_metabits_disabled() && self.mode & Self::SET_METABITS_OF_OPERANDS != 0
88 }
89
90 pub(crate) fn trap_on_marked_instruction(&self) -> bool {
93 self.mode & Self::TRAP_ON_MARKED_INSTRUCTION != 0
94 }
95
96 pub(crate) fn trap_on_deferred_address(&self) -> bool {
99 self.mode & Self::TRAP_ON_DEFERRED_ADDRESS != 0
100 }
101
102 pub(crate) fn trap_on_operand(&self) -> bool {
105 self.mode & Self::TRAP_ON_OPERAND != 0
106 }
107
108 pub(crate) fn trap_on_changed_sequence(&self) -> bool {
113 self.mode & Self::TRAP_ON_CHANGED_SEQUENCE != 0
114 }
115}
116
117impl Unit for TrapCircuit {
118 fn poll(&mut self, ctx: &Context) -> UnitStatus {
119 UnitStatus {
120 special: Unsigned12Bit::ZERO,
121 change_flag: None,
122 buffer_available_to_cpu: false,
123 inability: false,
124 missed_data: false,
125 mode: self.mode,
126 poll_after: ctx.simulated_time + Duration::from_secs(60),
128 is_input_unit: true,
129 }
130 }
131
132 fn connect(&mut self, _ctx: &Context, mode: Unsigned12Bit) {
133 self.mode = mode;
134 }
135
136 fn transfer_mode(&self) -> TransferMode {
137 TransferMode::Exchange
138 }
139
140 fn read(
145 &mut self,
146 _ctx: &Context,
147 _diags: &CurrentInstructionDiagnostics,
148 ) -> Result<MaskedWord, TransferFailed> {
149 Ok(MaskedWord {
152 bits: Unsigned36Bit::ZERO,
153 mask: Unsigned36Bit::ZERO,
154 })
155 }
156
157 fn write(
160 &mut self,
161 _ctx: &Context,
162 _source: Unsigned36Bit,
163 _diags: &CurrentInstructionDiagnostics,
164 ) -> Result<Option<OutputEvent>, TransferFailed> {
165 unreachable!()
166 }
167
168 fn name(&self) -> String {
169 "trap circuit".to_string()
170 }
171
172 fn disconnect(&mut self, _ctx: &Context) {
173 }
175
176 fn on_input_event(
177 &mut self,
178 _ctx: &Context,
179 _event: InputEvent,
180 ) -> Result<InputFlagRaised, InputEventError> {
181 Ok(InputFlagRaised::No)
183 }
184
185 fn text_info(&self, _ctx: &Context) -> String {
186 const STRING_WRITE_SUCCESS: &str = "write! calls on a String should always succeed";
187 let mut result = String::new();
188
189 if self.is_set_metabits_disabled() {
190 result.push_str("Set-metabits is disabled. ");
191 } else {
192 let mut metabit_setting_text: Vec<&str> = Vec::new();
193 if self.set_metabits_of_instructions() {
194 metabit_setting_text.push("instructions");
195 }
196 if self.set_metabits_of_deferred_addresses() {
197 metabit_setting_text.push("deferred addresses");
198 }
199 if self.set_metabits_of_operands() {
200 metabit_setting_text.push("operands");
201 }
202 if metabit_setting_text.is_empty() {
203 result.push_str("No metabits will be set. ");
204 } else {
205 write!(
206 result,
207 "Setting metabits for {}. ",
208 metabit_setting_text.join(", ")
209 )
210 .expect(STRING_WRITE_SUCCESS);
211 }
212 }
213 let mut trap_on_text: Vec<&str> = Vec::new();
214 if self.trap_on_marked_instruction() {
215 trap_on_text.push("marked instruction");
216 }
217 if self.trap_on_deferred_address() {
218 trap_on_text.push("deferred address");
219 }
220 if self.trap_on_deferred_address() {
221 trap_on_text.push("operand");
222 }
223 if self.trap_on_changed_sequence() {
224 trap_on_text.push("sequence change");
225 }
226 if trap_on_text.is_empty() {
227 result.push_str("No traps are active. ");
228 } else {
229 write!(result, "Trap on {}. ", trap_on_text.join(", ")).expect(STRING_WRITE_SUCCESS);
230 }
231 result
232 }
233}