From 71fabd32abaabfb60d05e61092d6f173ec80ee4b Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Thu, 4 Jul 2024 16:13:48 +0200 Subject: [PATCH 001/126] full adder does not work --- examples/full_adder.rs | 49 ++++++++ src/components/full_adder.rs | 102 +++++++++++++++ src/components/mod.rs | 2 + src/gui_egui/components/full_adder.rs | 172 ++++++++++++++++++++++++++ src/gui_egui/components/mod.rs | 1 + src/gui_egui/editor.rs | 8 ++ 6 files changed, 334 insertions(+) create mode 100644 examples/full_adder.rs create mode 100644 src/components/full_adder.rs create mode 100644 src/gui_egui/components/full_adder.rs diff --git a/examples/full_adder.rs b/examples/full_adder.rs new file mode 100644 index 00000000..abbf123d --- /dev/null +++ b/examples/full_adder.rs @@ -0,0 +1,49 @@ +use std::path::PathBuf; +#[cfg(feature = "gui-egui")] +use syncrim::gui_egui::editor::Library; +use syncrim::{ + common::{ComponentStore, Input}, + components::*, + fern::fern_setup, +}; + +fn main() { + fern_setup(); + let cs = ComponentStore { + store: vec![ + FullAdd::rc_new( + "full_adder", + (200.0, 120.0), + Input::new("c1", "out"), + Input::new("c2", "out"), + ), + Constant::rc_new("c1", (60.0, 100.0), 3), + Constant::rc_new("c2", (60.0, 140.0), 4), + Wire::rc_new( + "w1", + vec![(110.0, 100.0), (180.0, 100.0)], + Input::new("c1", "out"), + ), + Wire::rc_new( + "w2", + vec![(110.0, 140.0), (180.0, 140.0)], + Input::new("c2", "out"), + ), + Wire::rc_new( + "w3", + vec![(220.0, 120.0), (260.0, 120.0)], + Input::new("sub", FULL_ADD_OUT_ID), + ), + Probe::rc_new("p1", (270.0, 120.0), Input::new("sub", FULL_ADD_OUT_ID)), + ], + }; + + let path = PathBuf::from("add.json"); + cs.save_file(&path); + + #[cfg(feature = "gui-egui")] + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + + #[cfg(feature = "gui-vizia")] + syncrim::gui_vizia::gui(cs, &path); +} diff --git a/src/components/full_adder.rs b/src/components/full_adder.rs new file mode 100644 index 00000000..7b052c4c --- /dev/null +++ b/src/components/full_adder.rs @@ -0,0 +1,102 @@ +// use std::fmt::Alignment; +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, + SignalValue, Simulator, +}; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::rc::Rc; + +pub const FULL_ADD_A_IN_ID: &str = "add_a_in"; +pub const FULL_ADD_B_IN_ID: &str = "add_b_in"; + +pub const FULL_ADD_OUT_ID: &str = "out"; + +#[derive(Serialize, Deserialize, Clone)] +pub struct FullAdd { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) a_in: Input, + pub(crate) b_in: Input, +} + +#[typetag::serde] +impl Component for FullAdd { + fn to_(&self) { + trace!("Full_Adder"); + } + #[cfg(feature = "gui-egui")] + fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + let dummy_input = Input::new("dummy", "out"); + Box::new(Rc::new(FullAdd { + id: "dummy".to_string(), + pos: (0.0, 0.0), + a_in: dummy_input.clone(), + b_in: dummy_input.clone(), + })) + } + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![ + &InputPort { + port_id: FULL_ADD_A_IN_ID.to_string(), + input: self.a_in.clone(), + }, + &InputPort { + port_id: FULL_ADD_B_IN_ID.to_string(), + input: self.b_in.clone(), + }, + ], + OutputType::Combinatorial, + vec![FULL_ADD_OUT_ID], + ), + ) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + FULL_ADD_A_IN_ID => self.a_in = new_input, + FULL_ADD_B_IN_ID => self.b_in = new_input, + _ => {} + } + } + + // propagate sign extension to output + // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get input values + let a: u32 = simulator.get_input_value(&self.a_in).try_into().unwrap(); + let b: u32 = simulator.get_input_value(&self.b_in).try_into().unwrap(); + + simulator.set_out_value( + &self.id, + FULL_ADD_OUT_ID, + SignalValue::Data(((a as i32) + (b as i32)) as u32), + ); + Ok(()) + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl FullAdd { + pub fn new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input) -> Self { + FullAdd { + id: id.to_string(), + pos, + a_in, + b_in, + } + } + + pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input) -> Rc { + Rc::new(FullAdd::new(id, pos, a_in, b_in)) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index 2121b0d2..e231db78 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,6 +1,7 @@ mod add; mod constant; mod cross; +mod full_adder; mod mem; mod mux; mod probe; @@ -15,6 +16,7 @@ mod wire; pub use add::*; pub use constant::*; pub use cross::*; +pub use full_adder::*; pub use mem::*; pub use mux::*; pub use probe::*; diff --git a/src/gui_egui/components/full_adder.rs b/src/gui_egui/components/full_adder.rs new file mode 100644 index 00000000..ead95beb --- /dev/null +++ b/src/gui_egui/components/full_adder.rs @@ -0,0 +1,172 @@ +use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::components::FullAdd; +use crate::gui_egui::component_ui::{ + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::offset_helper; +use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; + +#[typetag::serde] +impl EguiComponent for FullAdd { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + // 81x41 + // middle: 41x 21y (0 0) + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + // The shape + ui.painter().add(Shape::closed_line( + vec![ + oh((-40f32, 0f32), s, o), + oh((40f32, 0f32), s, o), + oh((40f32, 20f32), s, o), + oh((-40f32, 20f32), s, o), + ], + Stroke { + width: scale, + color: Color32::RED, + }, + )); + + let rect = Rect { + min: oh((-40f32, -20f32), s, o), + max: oh((40f32, 20f32), s, o), + }; + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + // todo: is this actually correct? + if let Some(s) = &simulator { + ui.label({ + let a_r: Result = + s.get_input_value(&self.a_in).try_into(); + let b_r: Result = + s.get_input_value(&self.b_in).try_into(); + let mut s: String = "".to_string(); + match a_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", a_r), + } + match b_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", b_r), + } + format!("{}", s) + }); + ui.label("Full Adder"); + } + }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let r_vec = FullAdd::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_drag_value(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.a_in, + crate::components::FULL_ADD_A_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.b_in, + crate::components::FULL_ADD_B_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown + }, + ); + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + crate::components::SEXT_IN_ID.to_string(), + Pos2::new(-40f32, 0f32) + own_pos, + ), + ( + crate::components::SEXT_OUT_ID.to_string(), + Pos2::new(40f32, 0f32) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + 20f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } +} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index 428041e6..fd8ccec7 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -1,6 +1,7 @@ mod add; mod constant; mod cross; +mod full_adder; mod mem; mod mux; mod probe; diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index a5a4d9fc..e9fc7634 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -133,6 +133,14 @@ impl Default for Library { pos: (0.0, 0.0), r_in: dummy_input.clone(), }), + Rc::new( + (FullAdd { + id: "dummy".to_string(), + pos: (0.0, 0.0), + a_in: dummy_input.clone(), + b_in: dummy_input.clone(), + }), + ), ]; Library(library) } From 1960e72af711fc929af475b45b9f6f0a135517c1 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Thu, 4 Jul 2024 16:34:04 +0200 Subject: [PATCH 002/126] issue resolved --- examples/full_adder.rs | 8 ++++++-- src/components/full_adder.rs | 6 +++--- src/gui_egui/components/full_adder.rs | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/examples/full_adder.rs b/examples/full_adder.rs index abbf123d..3c185583 100644 --- a/examples/full_adder.rs +++ b/examples/full_adder.rs @@ -32,9 +32,13 @@ fn main() { Wire::rc_new( "w3", vec![(220.0, 120.0), (260.0, 120.0)], - Input::new("sub", FULL_ADD_OUT_ID), + Input::new("full_adder", FULL_ADD_OUT_ID), + ), + Probe::rc_new( + "p1", + (270.0, 120.0), + Input::new("full_adder", FULL_ADD_OUT_ID), ), - Probe::rc_new("p1", (270.0, 120.0), Input::new("sub", FULL_ADD_OUT_ID)), ], }; diff --git a/src/components/full_adder.rs b/src/components/full_adder.rs index 7b052c4c..3936df67 100644 --- a/src/components/full_adder.rs +++ b/src/components/full_adder.rs @@ -10,8 +10,8 @@ use serde::{Deserialize, Serialize}; use std::any::Any; use std::rc::Rc; -pub const FULL_ADD_A_IN_ID: &str = "add_a_in"; -pub const FULL_ADD_B_IN_ID: &str = "add_b_in"; +pub const FULL_ADD_A_IN_ID: &str = "full_add_a_in"; +pub const FULL_ADD_B_IN_ID: &str = "full_add_b_in"; pub const FULL_ADD_OUT_ID: &str = "out"; @@ -26,7 +26,7 @@ pub struct FullAdd { #[typetag::serde] impl Component for FullAdd { fn to_(&self) { - trace!("Full_Adder"); + trace!("full_adder"); } #[cfg(feature = "gui-egui")] fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { diff --git a/src/gui_egui/components/full_adder.rs b/src/gui_egui/components/full_adder.rs index ead95beb..56df9bf5 100644 --- a/src/gui_egui/components/full_adder.rs +++ b/src/gui_egui/components/full_adder.rs @@ -68,7 +68,7 @@ impl EguiComponent for FullAdd { } format!("{}", s) }); - ui.label("Full Adder"); + ui.label("full_adder"); } }); match editor_mode { From efa9a000a1b41279108219f6b22375e8a64794e6 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Fri, 5 Jul 2024 14:34:21 +0200 Subject: [PATCH 003/126] now supports sub and ProbeEdit --- examples/full_adder.rs | 14 ++++++++++++-- src/components/full_adder.rs | 27 +++++++++++++++++++++++---- src/gui_egui/components/full_adder.rs | 13 +++++++++++++ src/gui_egui/editor.rs | 1 + 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/examples/full_adder.rs b/examples/full_adder.rs index 3c185583..da54cce2 100644 --- a/examples/full_adder.rs +++ b/examples/full_adder.rs @@ -16,9 +16,14 @@ fn main() { (200.0, 120.0), Input::new("c1", "out"), Input::new("c2", "out"), + Input::new("c3", "out"), ), - Constant::rc_new("c1", (60.0, 100.0), 3), - Constant::rc_new("c2", (60.0, 140.0), 4), + // Constant::rc_new("c1", (60.0, 100.0), 10), + // Constant::rc_new("c2", (60.0, 140.0), 5), + // Constant::rc_new("c3", (60.0, 180.0), 1), + ProbeEdit::rc_new("c1", (60.0, 100.0)), + ProbeEdit::rc_new("c2", (60.0, 140.0)), + ProbeEdit::rc_new("c3", (60.0, 180.0)), Wire::rc_new( "w1", vec![(110.0, 100.0), (180.0, 100.0)], @@ -31,6 +36,11 @@ fn main() { ), Wire::rc_new( "w3", + vec![(110.0, 180.0), (180.0, 180.0)], + Input::new("c3", "out"), + ), + Wire::rc_new( + "w4", vec![(220.0, 120.0), (260.0, 120.0)], Input::new("full_adder", FULL_ADD_OUT_ID), ), diff --git a/src/components/full_adder.rs b/src/components/full_adder.rs index 3936df67..7b4b93dd 100644 --- a/src/components/full_adder.rs +++ b/src/components/full_adder.rs @@ -12,6 +12,7 @@ use std::rc::Rc; pub const FULL_ADD_A_IN_ID: &str = "full_add_a_in"; pub const FULL_ADD_B_IN_ID: &str = "full_add_b_in"; +pub const FULL_ADD_SUB_IN_ID: &str = "full_add_sub_in"; pub const FULL_ADD_OUT_ID: &str = "out"; @@ -21,6 +22,7 @@ pub struct FullAdd { pub(crate) pos: (f32, f32), pub(crate) a_in: Input, pub(crate) b_in: Input, + pub(crate) sub_in: Input, } #[typetag::serde] @@ -36,6 +38,7 @@ impl Component for FullAdd { pos: (0.0, 0.0), a_in: dummy_input.clone(), b_in: dummy_input.clone(), + sub_in: dummy_input.clone(), })) } fn get_id_ports(&self) -> (Id, Ports) { @@ -51,6 +54,10 @@ impl Component for FullAdd { port_id: FULL_ADD_B_IN_ID.to_string(), input: self.b_in.clone(), }, + &InputPort { + port_id: FULL_ADD_SUB_IN_ID.to_string(), + input: self.sub_in.clone(), + }, ], OutputType::Combinatorial, vec![FULL_ADD_OUT_ID], @@ -62,6 +69,7 @@ impl Component for FullAdd { match target_port_id.as_str() { FULL_ADD_A_IN_ID => self.a_in = new_input, FULL_ADD_B_IN_ID => self.b_in = new_input, + FULL_ADD_SUB_IN_ID => self.sub_in = new_input, _ => {} } } @@ -72,11 +80,21 @@ impl Component for FullAdd { // get input values let a: u32 = simulator.get_input_value(&self.a_in).try_into().unwrap(); let b: u32 = simulator.get_input_value(&self.b_in).try_into().unwrap(); + let mut sub: u32 = simulator.get_input_value(&self.sub_in).try_into().unwrap(); + + if sub == 1 { + sub = 0xFFFFFFFF; + } else { + sub = 0x00000000; + } + + let j: u32 = a.wrapping_add(b ^ sub).wrapping_add(1 & sub); simulator.set_out_value( &self.id, FULL_ADD_OUT_ID, - SignalValue::Data(((a as i32) + (b as i32)) as u32), + SignalValue::Data(j), + //SignalValue::Data(((a as i32) + (b as i32)) as u32), ); Ok(()) } @@ -87,16 +105,17 @@ impl Component for FullAdd { } impl FullAdd { - pub fn new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input) -> Self { + pub fn new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input, sub_in: Input) -> Self { FullAdd { id: id.to_string(), pos, a_in, b_in, + sub_in, } } - pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input) -> Rc { - Rc::new(FullAdd::new(id, pos, a_in, b_in)) + pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input, sub_in: Input) -> Rc { + Rc::new(FullAdd::new(id, pos, a_in, b_in, sub_in)) } } diff --git a/src/gui_egui/components/full_adder.rs b/src/gui_egui/components/full_adder.rs index 56df9bf5..402bb37d 100644 --- a/src/gui_egui/components/full_adder.rs +++ b/src/gui_egui/components/full_adder.rs @@ -57,6 +57,8 @@ impl EguiComponent for FullAdd { s.get_input_value(&self.a_in).try_into(); let b_r: Result = s.get_input_value(&self.b_in).try_into(); + let sub_r: Result = + s.get_input_value(&self.sub_in).try_into(); let mut s: String = "".to_string(); match a_r { Ok(data) => s += &format!("{:#x}", data), @@ -66,6 +68,10 @@ impl EguiComponent for FullAdd { Ok(data) => s += &format!("{:#x}", data), _ => s += &format!("{:?}", b_r), } + match sub_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", sub_r), + } format!("{}", s) }); ui.label("full_adder"); @@ -135,6 +141,13 @@ impl EguiComponent for FullAdd { id_ports, self.id.clone(), ); + clicked_dropdown |= input_selector( + ui, + &mut self.sub_in, + crate::components::FULL_ADD_SUB_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); clicked_dropdown }, ); diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index e9fc7634..4d82d406 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -139,6 +139,7 @@ impl Default for Library { pos: (0.0, 0.0), a_in: dummy_input.clone(), b_in: dummy_input.clone(), + sub_in: dummy_input.clone(), }), ), ]; From 6a939c4ec5cb0c23c8e65e785db5232aa685b6f6 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Mon, 8 Jul 2024 13:21:24 +0200 Subject: [PATCH 004/126] made into not working alu --- src/components/full_adder.rs | 50 ++++++++++++++++++--------- src/gui_egui/components/full_adder.rs | 12 +++---- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/src/components/full_adder.rs b/src/components/full_adder.rs index 7b4b93dd..94be1205 100644 --- a/src/components/full_adder.rs +++ b/src/components/full_adder.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub const FULL_ADD_A_IN_ID: &str = "full_add_a_in"; pub const FULL_ADD_B_IN_ID: &str = "full_add_b_in"; -pub const FULL_ADD_SUB_IN_ID: &str = "full_add_sub_in"; +pub const FULL_ADD_OP_IN_ID: &str = "full_add_op_in"; pub const FULL_ADD_OUT_ID: &str = "out"; @@ -22,7 +22,7 @@ pub struct FullAdd { pub(crate) pos: (f32, f32), pub(crate) a_in: Input, pub(crate) b_in: Input, - pub(crate) sub_in: Input, + pub(crate) op_in: Input, } #[typetag::serde] @@ -38,7 +38,7 @@ impl Component for FullAdd { pos: (0.0, 0.0), a_in: dummy_input.clone(), b_in: dummy_input.clone(), - sub_in: dummy_input.clone(), + op_in: dummy_input.clone(), })) } fn get_id_ports(&self) -> (Id, Ports) { @@ -55,8 +55,8 @@ impl Component for FullAdd { input: self.b_in.clone(), }, &InputPort { - port_id: FULL_ADD_SUB_IN_ID.to_string(), - input: self.sub_in.clone(), + port_id: FULL_ADD_OP_IN_ID.to_string(), + input: self.op_in.clone(), }, ], OutputType::Combinatorial, @@ -69,7 +69,7 @@ impl Component for FullAdd { match target_port_id.as_str() { FULL_ADD_A_IN_ID => self.a_in = new_input, FULL_ADD_B_IN_ID => self.b_in = new_input, - FULL_ADD_SUB_IN_ID => self.sub_in = new_input, + FULL_ADD_OP_IN_ID => self.op_in = new_input, _ => {} } } @@ -80,15 +80,31 @@ impl Component for FullAdd { // get input values let a: u32 = simulator.get_input_value(&self.a_in).try_into().unwrap(); let b: u32 = simulator.get_input_value(&self.b_in).try_into().unwrap(); - let mut sub: u32 = simulator.get_input_value(&self.sub_in).try_into().unwrap(); + let op: u32 = simulator.get_input_value(&self.op_in).try_into().unwrap(); - if sub == 1 { - sub = 0xFFFFFFFF; - } else { - sub = 0x00000000; - } + const OPADDU: u32 = 1; + const OPADD: u32 = 0; + const OPSUB: u32 = 2; + const OPSUBU: u32 = 3; + const OPAND: u32 = 4; + const OPOR: u32 = 5; + const OPXOR: u32 = 6; + const OPNOR: u32 = 7; + const OPDONOTHING: u32 = 8; + const OPSLT: u32 = 10; + const OPSLTU: u32 = 11; + const OPSLL: u32 = 12; + const OPSRL: u32 = 13; + const OPSRA: u32 = 14; + const OPLUI: u32 = 15; + + // if op == 1 { + // op = 0xFFFFFFFF; + // } else { + // op = 0x00000000; + // } - let j: u32 = a.wrapping_add(b ^ sub).wrapping_add(1 & sub); + let j: u32 = a.wrapping_add(b ^ op).wrapping_add(1 & op); simulator.set_out_value( &self.id, @@ -105,17 +121,17 @@ impl Component for FullAdd { } impl FullAdd { - pub fn new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input, sub_in: Input) -> Self { + pub fn new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input, op_in: Input) -> Self { FullAdd { id: id.to_string(), pos, a_in, b_in, - sub_in, + op_in, } } - pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input, sub_in: Input) -> Rc { - Rc::new(FullAdd::new(id, pos, a_in, b_in, sub_in)) + pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input, op_in: Input) -> Rc { + Rc::new(FullAdd::new(id, pos, a_in, b_in, op_in)) } } diff --git a/src/gui_egui/components/full_adder.rs b/src/gui_egui/components/full_adder.rs index 402bb37d..072f1eb8 100644 --- a/src/gui_egui/components/full_adder.rs +++ b/src/gui_egui/components/full_adder.rs @@ -57,8 +57,8 @@ impl EguiComponent for FullAdd { s.get_input_value(&self.a_in).try_into(); let b_r: Result = s.get_input_value(&self.b_in).try_into(); - let sub_r: Result = - s.get_input_value(&self.sub_in).try_into(); + let op_r: Result = + s.get_input_value(&self.op_in).try_into(); let mut s: String = "".to_string(); match a_r { Ok(data) => s += &format!("{:#x}", data), @@ -68,9 +68,9 @@ impl EguiComponent for FullAdd { Ok(data) => s += &format!("{:#x}", data), _ => s += &format!("{:?}", b_r), } - match sub_r { + match op_r { Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", sub_r), + _ => s += &format!("{:?}", op_r), } format!("{}", s) }); @@ -143,8 +143,8 @@ impl EguiComponent for FullAdd { ); clicked_dropdown |= input_selector( ui, - &mut self.sub_in, - crate::components::FULL_ADD_SUB_IN_ID.to_string(), + &mut self.op_in, + crate::components::FULL_ADD_OP_IN_ID.to_string(), id_ports, self.id.clone(), ); From 10f3c6c0333ede47d8e894e8cfe09c0f278d1050 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Mon, 8 Jul 2024 15:00:46 +0200 Subject: [PATCH 005/126] added all functionality of alu except NOOP --- src/components/full_adder.rs | 39 +++++++++++++++++++++++++++++++++--- src/gui_egui/editor.rs | 2 +- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/components/full_adder.rs b/src/components/full_adder.rs index 94be1205..37107851 100644 --- a/src/components/full_adder.rs +++ b/src/components/full_adder.rs @@ -82,8 +82,8 @@ impl Component for FullAdd { let b: u32 = simulator.get_input_value(&self.b_in).try_into().unwrap(); let op: u32 = simulator.get_input_value(&self.op_in).try_into().unwrap(); - const OPADDU: u32 = 1; const OPADD: u32 = 0; + const OPADDU: u32 = 1; const OPSUB: u32 = 2; const OPSUBU: u32 = 3; const OPAND: u32 = 4; @@ -98,18 +98,51 @@ impl Component for FullAdd { const OPSRA: u32 = 14; const OPLUI: u32 = 15; + let output: u32; + + //pub const HEAT: &str = "heat".to_uppercase().as_str(); + // if op == 1 { // op = 0xFFFFFFFF; // } else { // op = 0x00000000; // } - let j: u32 = a.wrapping_add(b ^ op).wrapping_add(1 & op); + if op == OPADD { + output = a.wrapping_add(b); + } else if op == OPSUB { + output = a.wrapping_add(b ^ 0xffffffff).wrapping_add(1); + } else if op == OPAND { + output = (a & b); + } else if op == OPOR { + output = (a | b); + } else if op == OPXOR { + output = (a ^ b); + } else if op == OPNOR { + output = !(a | b); + } else if op == OPDONOTHING { + // output = + todo!("something sll r0 r0 0"); + } else if op == OPSLT { + output = (0 == a.wrapping_add(b ^ op).wrapping_add(1)) as u32; + } else if op == OPSLL { + output = (a << b); + } else if op == OPSRL { + output = (a >> b); + } else if op == OPSRA { + output = ((a as i32) >> b) as u32; + } else if op == OPLUI { + output = (b << 16); + } else { + output = 0xffffffff; + } + + //let j: u32 = a.wrapping_add(b ^ op).wrapping_add(1 & op); simulator.set_out_value( &self.id, FULL_ADD_OUT_ID, - SignalValue::Data(j), + SignalValue::Data(output), //SignalValue::Data(((a as i32) + (b as i32)) as u32), ); Ok(()) diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 4d82d406..2594ee7a 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -139,7 +139,7 @@ impl Default for Library { pos: (0.0, 0.0), a_in: dummy_input.clone(), b_in: dummy_input.clone(), - sub_in: dummy_input.clone(), + op_in: dummy_input.clone(), }), ), ]; From 1ab6c61365d43bab7142c1dbc6e70b40b23f12f2 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Mon, 8 Jul 2024 16:29:37 +0200 Subject: [PATCH 006/126] added pc+4 component --- examples/clk.rs | 40 +++++++++ src/components/clk.rs | 90 +++++++++++++++++++ src/components/mod.rs | 2 + src/gui_egui/components/clk.rs | 160 +++++++++++++++++++++++++++++++++ src/gui_egui/components/mod.rs | 1 + src/gui_egui/editor.rs | 5 ++ 6 files changed, 298 insertions(+) create mode 100644 examples/clk.rs create mode 100644 src/components/clk.rs create mode 100644 src/gui_egui/components/clk.rs diff --git a/examples/clk.rs b/examples/clk.rs new file mode 100644 index 00000000..0d2b92c0 --- /dev/null +++ b/examples/clk.rs @@ -0,0 +1,40 @@ +use std::path::PathBuf; +#[cfg(feature = "gui-egui")] +use syncrim::gui_egui::editor::Library; +use syncrim::{ + common::{ComponentStore, Input}, + components::*, + fern::fern_setup, +}; + +fn main() { + fern_setup(); + let cs = ComponentStore { + store: vec![ + MIPSCLK::rc_new("clk", (200.0, 120.0), Input::new("reg", "out")), + //Constant::rc_new("c1", (60.0, 100.0), 10), + // ProbeEdit::rc_new("c1", (60.0, 100.0)), + Register::rc_new("reg", (100.0, 140.0), Input::new("clk", "out")), + Probe::rc_new("p1", (270.0, 120.0), Input::new("clk", CLK_OUT_ID)), + // Wire::rc_new( + // "w1", + // vec![(110.0, 140.0), (180.0, 100.0)], + // Input::new("c1", "out"), + // ), + // Wire::rc_new( + // "w2", + // vec![(220.0, 120.0), (260.0, 120.0)], + // Input::new("clk", CLK_OUT_ID), + // ), + ], + }; + + let path = PathBuf::from("add.json"); + cs.save_file(&path); + + #[cfg(feature = "gui-egui")] + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + + #[cfg(feature = "gui-vizia")] + syncrim::gui_vizia::gui(cs, &path); +} diff --git a/src/components/clk.rs b/src/components/clk.rs new file mode 100644 index 00000000..bf03b4b2 --- /dev/null +++ b/src/components/clk.rs @@ -0,0 +1,90 @@ +// use std::fmt::Alignment; +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, + SignalValue, Simulator, +}; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::rc::Rc; + +pub const CLK_IN_ID: &str = "clk_in"; + +pub const CLK_OUT_ID: &str = "out"; + +#[derive(Serialize, Deserialize, Clone)] +pub struct MIPSCLK { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) clk_in: Input, +} + +#[typetag::serde] +impl Component for MIPSCLK { + fn to_(&self) { + trace!("pc+4"); + } + #[cfg(feature = "gui-egui")] + fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + let dummy_input = Input::new("dummy", "out"); + Box::new(Rc::new(MIPSCLK { + id: "dummy".to_string(), + pos: (0.0, 0.0), + clk_in: dummy_input.clone(), + })) + } + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![&InputPort { + port_id: CLK_IN_ID.to_string(), + input: self.clk_in.clone(), + }], + OutputType::Combinatorial, + vec![CLK_OUT_ID], + ), + ) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + CLK_A_IN_ID => self.clk_in = new_input, + _ => {} + } + } + + // propagate sign extension to output + // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get input values + let start_time: u32 = simulator.get_input_value(&self.clk_in).try_into().unwrap(); + + simulator.set_out_value( + &self.id, + CLK_OUT_ID, + SignalValue::Data(start_time.wrapping_add(4)), + ); + Ok(()) + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl MIPSCLK { + pub fn new(id: &str, pos: (f32, f32), clk_in: Input) -> Self { + MIPSCLK { + id: id.to_string(), + pos, + clk_in, + } + } + + pub fn rc_new(id: &str, pos: (f32, f32), clk_in: Input) -> Rc { + Rc::new(MIPSCLK::new(id, pos, clk_in)) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index e231db78..71e7290f 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,4 +1,5 @@ mod add; +mod clk; mod constant; mod cross; mod full_adder; @@ -14,6 +15,7 @@ mod sext; mod wire; pub use add::*; +pub use clk::*; pub use constant::*; pub use cross::*; pub use full_adder::*; diff --git a/src/gui_egui/components/clk.rs b/src/gui_egui/components/clk.rs new file mode 100644 index 00000000..eacc23f7 --- /dev/null +++ b/src/gui_egui/components/clk.rs @@ -0,0 +1,160 @@ +use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::components::MIPSCLK; +use crate::gui_egui::component_ui::{ + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::offset_helper; +use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; + +#[typetag::serde] +impl EguiComponent for MIPSCLK { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + // 81x41 + // middle: 41x 21y (0 0) + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + // The shape + ui.painter().add(Shape::closed_line( + vec![ + oh((-40f32, 0f32), s, o), + oh((40f32, 0f32), s, o), + oh((40f32, 20f32), s, o), + oh((-40f32, 20f32), s, o), + ], + Stroke { + width: scale, + color: Color32::RED, + }, + )); + + let rect = Rect { + min: oh((-40f32, -20f32), s, o), + max: oh((40f32, 20f32), s, o), + }; + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + // todo: is this actually correct? + if let Some(s) = &simulator { + ui.label({ + let clk_r: Result = + s.get_input_value(&self.clk_in).try_into(); + let mut s: String = "".to_string(); + + match clk_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", clk_r), + } + format!("{}", s) + }); + ui.label("pc+4"); + } + }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let r_vec = MIPSCLK::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_drag_value(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.clk_in, + crate::components::CLK_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown + }, + ); + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + crate::components::SEXT_IN_ID.to_string(), + Pos2::new(-40f32, 0f32) + own_pos, + ), + ( + crate::components::SEXT_OUT_ID.to_string(), + Pos2::new(40f32, 0f32) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + 20f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } +} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index fd8ccec7..4df9ec09 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -1,4 +1,5 @@ mod add; +mod clk; mod constant; mod cross; mod full_adder; diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 2594ee7a..7daded2f 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -133,6 +133,11 @@ impl Default for Library { pos: (0.0, 0.0), r_in: dummy_input.clone(), }), + Rc::new(MIPSCLK { + id: "clk".to_string(), + pos: (0.0, 0.0), + clk_in: dummy_input.clone(), + }), Rc::new( (FullAdd { id: "dummy".to_string(), From 39fa17f3c90534d9a1db50dd52c13cc8d93d85dd Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Tue, 16 Jul 2024 16:36:55 +0200 Subject: [PATCH 007/126] added function autowire, TODO get position argument for component then making the wire --- examples/clk.rs | 2 +- examples/full_adder.rs | 137 ++++++++++++++++++++++++++++++++--------- src/common.rs | 2 + src/fern.rs | 3 +- 4 files changed, 113 insertions(+), 31 deletions(-) diff --git a/examples/clk.rs b/examples/clk.rs index 0d2b92c0..7b7e4fae 100644 --- a/examples/clk.rs +++ b/examples/clk.rs @@ -14,7 +14,7 @@ fn main() { MIPSCLK::rc_new("clk", (200.0, 120.0), Input::new("reg", "out")), //Constant::rc_new("c1", (60.0, 100.0), 10), // ProbeEdit::rc_new("c1", (60.0, 100.0)), - Register::rc_new("reg", (100.0, 140.0), Input::new("clk", "out")), + Register::rc_new("reg", (200.0, 250.0), Input::new("clk", CLK_OUT_ID)), Probe::rc_new("p1", (270.0, 120.0), Input::new("clk", CLK_OUT_ID)), // Wire::rc_new( // "w1", diff --git a/examples/full_adder.rs b/examples/full_adder.rs index da54cce2..eb15b437 100644 --- a/examples/full_adder.rs +++ b/examples/full_adder.rs @@ -1,8 +1,12 @@ -use std::path::PathBuf; +use std::{ + any::{Any, TypeId}, + path::PathBuf, +}; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ common::{ComponentStore, Input}, + component_store, components::*, fern::fern_setup, }; @@ -21,37 +25,41 @@ fn main() { // Constant::rc_new("c1", (60.0, 100.0), 10), // Constant::rc_new("c2", (60.0, 140.0), 5), // Constant::rc_new("c3", (60.0, 180.0), 1), - ProbeEdit::rc_new("c1", (60.0, 100.0)), - ProbeEdit::rc_new("c2", (60.0, 140.0)), - ProbeEdit::rc_new("c3", (60.0, 180.0)), - Wire::rc_new( - "w1", - vec![(110.0, 100.0), (180.0, 100.0)], - Input::new("c1", "out"), - ), - Wire::rc_new( - "w2", - vec![(110.0, 140.0), (180.0, 140.0)], - Input::new("c2", "out"), - ), - Wire::rc_new( - "w3", - vec![(110.0, 180.0), (180.0, 180.0)], - Input::new("c3", "out"), - ), - Wire::rc_new( - "w4", - vec![(220.0, 120.0), (260.0, 120.0)], - Input::new("full_adder", FULL_ADD_OUT_ID), - ), - Probe::rc_new( - "p1", - (270.0, 120.0), - Input::new("full_adder", FULL_ADD_OUT_ID), - ), + + // ProbeEdit::rc_new("c1", (60.0, 100.0)), + // ProbeEdit::rc_new("c2", (60.0, 140.0)), + // ProbeEdit::rc_new("c3", (60.0, 180.0)), + + // Wire::rc_new( + // "w1", + // vec![(110.0, 100.0), (180.0, 100.0)], + // Input::new("c1", "out"), + // ), + // Wire::rc_new( + // "w2", + // vec![(110.0, 140.0), (180.0, 140.0)], + // Input::new("c2", "out"), + // ), + // Wire::rc_new( + // "w3", + // vec![(110.0, 180.0), (180.0, 180.0)], + // Input::new("c3", "out"), + // ), + // Wire::rc_new( + // "w4", + // vec![(220.0, 120.0), (260.0, 120.0)], + // Input::new("full_adder", FULL_ADD_OUT_ID), + // ), + // Probe::rc_new( + // "p1", + // (270.0, 120.0), + // Input::new("full_adder", FULL_ADD_OUT_ID), + // ), ], }; + let cs = autowire(cs); + let path = PathBuf::from("add.json"); cs.save_file(&path); @@ -61,3 +69,74 @@ fn main() { #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); } + +fn autowire(cs: ComponentStore) -> ComponentStore { + let mut x = 1; + // for component in cs { + // println!("{}", x); + // x = x + 1; + // } + // while x < 10 { + + // } + + //let cs_copy = cs.clone(); + + for c in &cs.store { + let (id, ports) = c.get_id_ports(); + println!("{}", id); + + //println!("{:?}", c.get_id_ports().1.inputs); + + let number_of_inputs = ports.inputs.len(); + + for n in 0..number_of_inputs { + println!("{:?}", ports.inputs[n]); + + let id_tmp = format!("w{n}"); + //let pos_temp = vec![]; + let input = ports.inputs[n].input.clone(); + //println!("{}", id_tmp); + //let w = Wire::rc_new("w{}", pos, input) + } + + //cs_copy.store.push("wow"); + + // Wire::rc_new( + // "w4", + // vec![(220.0, 120.0), (260.0, 120.0)], + // Input::new("full_adder", FULL_ADD_OUT_ID), + // ), + + // Ports { + // inputs: [ + // InputPort { + // port_id: "full_add_a_in", + // input: Input { + // id: "c1", + // field: "out", + // }, + // }, + // InputPort { + // port_id: "full_add_b_in", + // input: Input { + // id: "c2", + // field: "out", + // }, + // }, + // InputPort { + // port_id: "full_add_op_in", + // input: Input { + // id: "c3", + // field: "out", + // }, + // }, + // ], + + // out_type: Combinatorial, + // outputs: ["out"], + // } + } + + return cs; +} diff --git a/src/common.rs b/src/common.rs index 69f1fa9d..822f9715 100644 --- a/src/common.rs +++ b/src/common.rs @@ -67,6 +67,8 @@ pub trait Component { /// returns the (id, Ports) of the component fn get_id_ports(&self) -> (Id, Ports); + fn get_id_position_ports(&self) -> (Id, Position, Ports); + fn set_id_port(&mut self, _target_port_id: Id, _new_input: Input) { todo!("Set set_id_port for this Component"); } diff --git a/src/fern.rs b/src/fern.rs index 237e0bfd..79f23af5 100644 --- a/src/fern.rs +++ b/src/fern.rs @@ -16,7 +16,8 @@ pub fn fern_setup() { }) // Add blanket level filter - // .level(log::LevelFilter::Debug); - .level(log::LevelFilter::Trace); + // .level(log::LevelFilter::Trace); + .level(log::LevelFilter::Off); // - and per-module overrides #[cfg(feature = "gui-vizia")] From 3f2120df37ad9dd8d771776c09e8dd341d1370e7 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Wed, 17 Jul 2024 16:54:02 +0200 Subject: [PATCH 008/126] now full functioning autowire, ps dont make your own wires :) --- examples/clk.rs | 103 +++++++++++++++++++++++++++++-- examples/full_adder.rs | 114 +++++++++++++---------------------- src/common.rs | 3 +- src/components/full_adder.rs | 1 + 4 files changed, 143 insertions(+), 78 deletions(-) diff --git a/examples/clk.rs b/examples/clk.rs index 7b7e4fae..8001952c 100644 --- a/examples/clk.rs +++ b/examples/clk.rs @@ -1,4 +1,6 @@ use std::path::PathBuf; +use std::rc::Rc; +use syncrim::common::EguiComponent; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ @@ -11,15 +13,21 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - MIPSCLK::rc_new("clk", (200.0, 120.0), Input::new("reg", "out")), + MIPSCLK::rc_new("clk", (200.0, 120.0), Input::new("reg2", "out")), //Constant::rc_new("c1", (60.0, 100.0), 10), // ProbeEdit::rc_new("c1", (60.0, 100.0)), - Register::rc_new("reg", (200.0, 250.0), Input::new("clk", CLK_OUT_ID)), - Probe::rc_new("p1", (270.0, 120.0), Input::new("clk", CLK_OUT_ID)), + Register::rc_new("reg", (150.0, 250.0), Input::new("clk", "out")), + Register::rc_new("reg2", (250.0, 250.0), Input::new("reg", "out")), + // Probe::rc_new("p1", (270.0, 120.0), Input::new("clk", CLK_OUT_ID)), + // Wire::rc_new( + // "w2", + // vec![(200.0 - 50.0, 250.0), (200.0 - 50.0, 120.0)], + // Input::new("reg", "out"), + // ), // Wire::rc_new( // "w1", - // vec![(110.0, 140.0), (180.0, 100.0)], - // Input::new("c1", "out"), + // vec![(200.0, 120.0), (200.0, 250.0)], + // Input::new("clk", "out"), // ), // Wire::rc_new( // "w2", @@ -29,6 +37,8 @@ fn main() { ], }; + let cs = autowire(cs); + let path = PathBuf::from("add.json"); cs.save_file(&path); @@ -38,3 +48,86 @@ fn main() { #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); } + +fn autowire(mut cs: ComponentStore) -> ComponentStore { + let mut x = 1; + let mut tmp_vec: Vec> = vec![]; + + for c in &cs.store { + let (id, ports) = c.get_id_ports(); + println!("{}", id); + + let number_of_inputs = ports.inputs.len(); + + for n in 0..number_of_inputs { + println!("{:?}", ports.inputs[n].input.id); + println!("{:?}", ports); + + let id_tmp = format!("{id}_w{n}"); + //let pos_temp = vec![]; + let input = ports.inputs[n].input.clone(); + + let starting_pos = c.get_pos(); + + let mut destination_pos = (starting_pos.0 - 50.0, starting_pos.1); + + let default_input = Input::new(&format!("c{n}"), "out"); + let mut w = Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], default_input); + + for d in &cs.store { + let (id2, ports2) = d.get_id_ports(); + let input = Input::new(&id2, "out"); + if id2 == ports.inputs[n].input.id { + destination_pos = d.get_pos(); + w = Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], input.clone()); + } + } + tmp_vec.push(w); + + //TODO: get pos and set to destination, look through list of components a second time, then add that as starting pos. + + //println!("{}", id_tmp); + //let w = Wire::rc_new("w{}", pos, input) + } + + //cs_copy.store.push("wow"); + + // Wire::rc_new( + // "w4", + // vec![(220.0, 120.0), (260.0, 120.0)], + // Input::new("full_adder", FULL_ADD_OUT_ID), + // ), + + // Ports { + // inputs: [ + // InputPort { + // port_id: "full_add_a_in", + // input: Input { + // id: "c1", + // field: "out", + // }, + // }, + // InputPort { + // port_id: "full_add_b_in", + // input: Input { + // id: "c2", + // field: "out", + // }, + // }, + // InputPort { + // port_id: "full_add_op_in", + // input: Input { + // id: "c3", + // field: "out", + // }, + // }, + // ], + + // out_type: Combinatorial, + // outputs: ["out"], + // } + } + cs.store.append(&mut tmp_vec); + + return cs; +} diff --git a/examples/full_adder.rs b/examples/full_adder.rs index eb15b437..d31ea440 100644 --- a/examples/full_adder.rs +++ b/examples/full_adder.rs @@ -1,7 +1,9 @@ +use std::rc::Rc; use std::{ any::{Any, TypeId}, path::PathBuf, }; +use syncrim::common::EguiComponent; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ @@ -18,43 +20,41 @@ fn main() { FullAdd::rc_new( "full_adder", (200.0, 120.0), + Input::new("c0", "out"), Input::new("c1", "out"), Input::new("c2", "out"), - Input::new("c3", "out"), ), - // Constant::rc_new("c1", (60.0, 100.0), 10), - // Constant::rc_new("c2", (60.0, 140.0), 5), - // Constant::rc_new("c3", (60.0, 180.0), 1), - - // ProbeEdit::rc_new("c1", (60.0, 100.0)), - // ProbeEdit::rc_new("c2", (60.0, 140.0)), - // ProbeEdit::rc_new("c3", (60.0, 180.0)), - + // Constant::rc_new("c0", (60.0, 100.0), 10), + // Constant::rc_new("c1", (60.0, 140.0), 5), + // Constant::rc_new("c2", (60.0, 180.0), 1), + ProbeEdit::rc_new("c0", (60.0, 100.0)), + ProbeEdit::rc_new("c1", (60.0, 140.0)), + ProbeEdit::rc_new("c2", (60.0, 180.0)), // Wire::rc_new( // "w1", // vec![(110.0, 100.0), (180.0, 100.0)], - // Input::new("c1", "out"), + // Input::new("c0", "out"), // ), // Wire::rc_new( // "w2", // vec![(110.0, 140.0), (180.0, 140.0)], - // Input::new("c2", "out"), + // Input::new("c1", "out"), // ), // Wire::rc_new( // "w3", // vec![(110.0, 180.0), (180.0, 180.0)], - // Input::new("c3", "out"), + // Input::new("c2", "out"), // ), // Wire::rc_new( // "w4", // vec![(220.0, 120.0), (260.0, 120.0)], // Input::new("full_adder", FULL_ADD_OUT_ID), // ), - // Probe::rc_new( - // "p1", - // (270.0, 120.0), - // Input::new("full_adder", FULL_ADD_OUT_ID), - // ), + Probe::rc_new( + "p1", + (270.0, 120.0), + Input::new("full_adder", FULL_ADD_OUT_ID), + ), ], }; @@ -70,73 +70,43 @@ fn main() { syncrim::gui_vizia::gui(cs, &path); } -fn autowire(cs: ComponentStore) -> ComponentStore { - let mut x = 1; - // for component in cs { - // println!("{}", x); - // x = x + 1; - // } - // while x < 10 { - - // } - - //let cs_copy = cs.clone(); +fn autowire(mut cs: ComponentStore) -> ComponentStore { + let mut tmp_vec: Vec> = vec![]; + // look through the list of components for c in &cs.store { let (id, ports) = c.get_id_ports(); println!("{}", id); - //println!("{:?}", c.get_id_ports().1.inputs); - let number_of_inputs = ports.inputs.len(); for n in 0..number_of_inputs { - println!("{:?}", ports.inputs[n]); + // println!("{:?}", ports.inputs[n].input.id); + // println!("{:?}", ports.inputs[n]); - let id_tmp = format!("w{n}"); - //let pos_temp = vec![]; + let id_tmp = format!("{id}_w{n}"); let input = ports.inputs[n].input.clone(); - //println!("{}", id_tmp); - //let w = Wire::rc_new("w{}", pos, input) + let starting_pos = c.get_pos(); + + // creates temporary vales to use when constatnt inputs are there for testing + let mut destination_pos = (starting_pos.0 - 50.0, starting_pos.1); + let default_input = Input::new(&ports.inputs[n].input.id, "out"); + + // look through the list again and act when you find a matching id + for d in &cs.store { + let (id2, ports2) = d.get_id_ports(); + // look if the id matches the one you are looking for + if id2 == ports.inputs[n].input.id { + // collect the components destination and use it to make a complete wire + destination_pos = d.get_pos(); + let w = + Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], input.clone()); + tmp_vec.push(w); + } + } } - - //cs_copy.store.push("wow"); - - // Wire::rc_new( - // "w4", - // vec![(220.0, 120.0), (260.0, 120.0)], - // Input::new("full_adder", FULL_ADD_OUT_ID), - // ), - - // Ports { - // inputs: [ - // InputPort { - // port_id: "full_add_a_in", - // input: Input { - // id: "c1", - // field: "out", - // }, - // }, - // InputPort { - // port_id: "full_add_b_in", - // input: Input { - // id: "c2", - // field: "out", - // }, - // }, - // InputPort { - // port_id: "full_add_op_in", - // input: Input { - // id: "c3", - // field: "out", - // }, - // }, - // ], - - // out_type: Combinatorial, - // outputs: ["out"], - // } } + cs.store.append(&mut tmp_vec); return cs; } diff --git a/src/common.rs b/src/common.rs index 822f9715..7bd688e8 100644 --- a/src/common.rs +++ b/src/common.rs @@ -67,7 +67,8 @@ pub trait Component { /// returns the (id, Ports) of the component fn get_id_ports(&self) -> (Id, Ports); - fn get_id_position_ports(&self) -> (Id, Position, Ports); + // #default + // fn get_pos(&self) -> (Position); fn set_id_port(&mut self, _target_port_id: Id, _new_input: Input) { todo!("Set set_id_port for this Component"); diff --git a/src/components/full_adder.rs b/src/components/full_adder.rs index 37107851..d90ec0b5 100644 --- a/src/components/full_adder.rs +++ b/src/components/full_adder.rs @@ -135,6 +135,7 @@ impl Component for FullAdd { output = (b << 16); } else { output = 0xffffffff; + return Err(Condition::Error("undef opcode".to_string())); } //let j: u32 = a.wrapping_add(b ^ op).wrapping_add(1 & op); From ffe07f323ebe83207ef7e904a9b82283412529be Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Tue, 23 Jul 2024 16:48:57 +0200 Subject: [PATCH 009/126] control unit, need fixed input --- examples/mips_controll_unit.rs | 117 ++++++++++ src/components/mips_controll_unit.rs | 210 ++++++++++++++++++ src/components/mod.rs | 2 + src/gui_egui/components/mips_controll_unit.rs | 160 +++++++++++++ src/gui_egui/components/mod.rs | 1 + src/gui_egui/editor.rs | 5 + 6 files changed, 495 insertions(+) create mode 100644 examples/mips_controll_unit.rs create mode 100644 src/components/mips_controll_unit.rs create mode 100644 src/gui_egui/components/mips_controll_unit.rs diff --git a/examples/mips_controll_unit.rs b/examples/mips_controll_unit.rs new file mode 100644 index 00000000..789085a1 --- /dev/null +++ b/examples/mips_controll_unit.rs @@ -0,0 +1,117 @@ +use std::rc::Rc; +use std::{ + any::{Any, TypeId}, + path::PathBuf, +}; +use syncrim::common::EguiComponent; +#[cfg(feature = "gui-egui")] +use syncrim::gui_egui::editor::Library; +use syncrim::{ + common::{ComponentStore, Input}, + component_store, + components::*, + fern::fern_setup, +}; + +fn main() { + fern_setup(); + let cs = ComponentStore { + store: vec![ + ControlUnit::rc_new("control_unit", (200.0, 120.0), Input::new("c0", "out")), + // Constant::rc_new("c0", (60.0, 100.0), 10), + ProbeEdit::rc_new("c0", (60.0, 120.0)), + Probe::rc_new( + "p1", + (270.0, 120.0), + Input::new("control_unit", CONTROL_UNIT_MEMTOREG_ID), + ), + Probe::rc_new( + "p2", + (270.0, 170.0), + Input::new("control_unit", CONTROL_UNIT_MEMWRITE_ID), + ), + Probe::rc_new( + "p3", + (270.0, 220.0), + Input::new("control_unit", CONTROL_UNIT_BRANCH_ID), + ), + Probe::rc_new( + "p4", + (270.0, 270.0), + Input::new("control_unit", CONTROL_UNIT_ALUCONTROL_ID), + ), + Probe::rc_new( + "p5", + (270.0, 320.0), + Input::new("control_unit", CONTROL_UNIT_ALUSRC_ID), + ), + Probe::rc_new( + "p6", + (270.0, 370.0), + Input::new("control_unit", CONTROL_UNIT_REGDST_ID), + ), + Probe::rc_new( + "p7", + (270.0, 420.0), + Input::new("control_unit", CONTROL_UNIT_WRITEENABLE_ID), + ), + Probe::rc_new( + "p8", + (270.0, 470.0), + Input::new("control_unit", CONTROL_UNIT_JUMP_ID), + ), + ], + }; + + let cs = autowire(cs); + + let path = PathBuf::from("add.json"); + cs.save_file(&path); + + #[cfg(feature = "gui-egui")] + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + + #[cfg(feature = "gui-vizia")] + syncrim::gui_vizia::gui(cs, &path); +} + +fn autowire(mut cs: ComponentStore) -> ComponentStore { + let mut tmp_vec: Vec> = vec![]; + + // look through the list of components + for c in &cs.store { + let (id, ports) = c.get_id_ports(); + println!("{}", id); + + let number_of_inputs = ports.inputs.len(); + + for n in 0..number_of_inputs { + // println!("{:?}", ports.inputs[n].input.id); + // println!("{:?}", ports.inputs[n]); + + let id_tmp = format!("{id}_w{n}"); + let input = ports.inputs[n].input.clone(); + let starting_pos = c.get_pos(); + + // creates temporary vales to use when constatnt inputs are there for testing + let mut destination_pos = (starting_pos.0 - 50.0, starting_pos.1); + let default_input = Input::new(&ports.inputs[n].input.id, "out"); + + // look through the list again and act when you find a matching id + for d in &cs.store { + let (id2, ports2) = d.get_id_ports(); + // look if the id matches the one you are looking for + if id2 == ports.inputs[n].input.id { + // collect the components destination and use it to make a complete wire + destination_pos = d.get_pos(); + let w = + Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], input.clone()); + tmp_vec.push(w); + } + } + } + } + cs.store.append(&mut tmp_vec); + + return cs; +} diff --git a/src/components/mips_controll_unit.rs b/src/components/mips_controll_unit.rs new file mode 100644 index 00000000..e7ec5290 --- /dev/null +++ b/src/components/mips_controll_unit.rs @@ -0,0 +1,210 @@ +// use std::fmt::Alignment; +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, + SignalValue, Simulator, +}; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::rc::Rc; + +pub const CONTROL_UNIT_A_IN_ID: &str = "control_unit_a_in"; + +pub const CONTROL_UNIT_MEMTOREG_ID: &str = "MemToReg"; +pub const CONTROL_UNIT_MEMWRITE_ID: &str = "MemWrite"; +pub const CONTROL_UNIT_BRANCH_ID: &str = "Branch"; +pub const CONTROL_UNIT_ALUCONTROL_ID: &str = "ALUControl"; +pub const CONTROL_UNIT_ALUSRC_ID: &str = "ALUSrc"; +pub const CONTROL_UNIT_REGDST_ID: &str = "RegDst"; +pub const CONTROL_UNIT_WRITEENABLE_ID: &str = "WriteEnable"; +pub const CONTROL_UNIT_JUMP_ID: &str = "Jump"; + +#[derive(Serialize, Deserialize, Clone)] +pub struct ControlUnit { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) a_in: Input, +} + +#[typetag::serde] +impl Component for ControlUnit { + fn to_(&self) { + trace!("control_unit"); + } + #[cfg(feature = "gui-egui")] + fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + let dummy_input = Input::new("dummy", "out"); + Box::new(Rc::new(ControlUnit { + id: "dummy".to_string(), + pos: (0.0, 0.0), + a_in: dummy_input.clone(), + })) + } + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![&InputPort { + port_id: CONTROL_UNIT_A_IN_ID.to_string(), + input: self.a_in.clone(), + }], + OutputType::Combinatorial, + vec![ + CONTROL_UNIT_MEMTOREG_ID, + CONTROL_UNIT_MEMWRITE_ID, + CONTROL_UNIT_BRANCH_ID, + CONTROL_UNIT_ALUCONTROL_ID, + CONTROL_UNIT_ALUSRC_ID, + CONTROL_UNIT_REGDST_ID, + CONTROL_UNIT_WRITEENABLE_ID, + CONTROL_UNIT_JUMP_ID, + ], + ), + ) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + CONTROL_UNIT_A_IN_ID => self.a_in = new_input, + _ => {} + } + } + + // propagate sign extension to output + // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get input values + let a: u32 = simulator.get_input_value(&self.a_in).try_into().unwrap(); + + // let a_OpCode: u32 = (a >> 26) & 0x0000_003f; + // let a_func: u32 = a & 0x0000_001f; + let a_OpCode: u32 = a; + let a_func: u32 = 0; + + let MemToReg; + let MemWrite; + let Branch; + let ALUControl; + let ALUSrc; + let RegDst; + let WriteEnable; + let Jump; + + if a_OpCode == 0 || a_OpCode == 4 { + ALUSrc = 0; + } else { + ALUSrc = 1; + } + + if a_OpCode == 0 { + RegDst = 1; + } else { + RegDst = 0; + } + + if a_OpCode == 4 { + Branch = 1; + } else { + Branch = 0; + } + + if a_OpCode == 35 { + MemToReg = 1; + } else { + MemToReg = 0; + } + + if a_OpCode == 43 { + MemWrite = 1; + } else { + MemWrite = 0; + } + + if a_OpCode == 2 { + Jump = 1; + } else { + Jump = 0; + } + + if (a_OpCode == 0) + & (a_func == 32 || a_func == 34 || a_func == 42 || a_func == 36 || a_func == 37) + { + WriteEnable = 1; + } else if a_OpCode == 8 || a_OpCode == 10 || a_OpCode == 35 { + WriteEnable = 1; + } else { + WriteEnable = 0; + } + + if (a_OpCode == 0) & (a_func == 32) { + ALUControl = 2; // AND + } else if a_OpCode == 8 { + ALUControl = 2; // ANDI + } else if a_OpCode == 35 { + ALUControl = 2; //lw + } else if a_OpCode == 43 { + ALUControl = 2; //sw + } else if a_OpCode == 4 { + ALUControl = 6; // beq + } else if (a_OpCode == 0) & (a_func == 34) { + ALUControl = 6; // SUB + } else if (a_OpCode == 0) & (a_func == 42) { + ALUControl = 7; // SLT + } else if a_OpCode == 10 { + ALUControl = 7; // SLTI + } else if (a_OpCode == 0) & (a_func == 36) { + ALUControl = 0; // AND + } else if (a_OpCode == 0) & (a_func == 37) { + ALUControl = 1; //OR + } else { + ALUControl = 0; + } + + simulator.set_out_value( + &self.id, + CONTROL_UNIT_MEMTOREG_ID, + SignalValue::Data(MemToReg), + ); + simulator.set_out_value( + &self.id, + CONTROL_UNIT_MEMWRITE_ID, + SignalValue::Data(MemWrite), + ); + simulator.set_out_value(&self.id, CONTROL_UNIT_BRANCH_ID, SignalValue::Data(Branch)); + simulator.set_out_value( + &self.id, + CONTROL_UNIT_ALUCONTROL_ID, + SignalValue::Data(ALUControl), + ); + simulator.set_out_value(&self.id, CONTROL_UNIT_ALUSRC_ID, SignalValue::Data(ALUSrc)); + simulator.set_out_value(&self.id, CONTROL_UNIT_REGDST_ID, SignalValue::Data(RegDst)); + simulator.set_out_value(&self.id, CONTROL_UNIT_JUMP_ID, SignalValue::Data(Jump)); + simulator.set_out_value( + &self.id, + CONTROL_UNIT_WRITEENABLE_ID, + SignalValue::Data(WriteEnable), + ); + + Ok(()) + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl ControlUnit { + pub fn new(id: &str, pos: (f32, f32), a_in: Input) -> Self { + ControlUnit { + id: id.to_string(), + pos, + a_in, + } + } + + pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input) -> Rc { + Rc::new(ControlUnit::new(id, pos, a_in)) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index 71e7290f..fa877498 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -4,6 +4,7 @@ mod constant; mod cross; mod full_adder; mod mem; +mod mips_controll_unit; mod mux; mod probe; mod probe_assert; @@ -20,6 +21,7 @@ pub use constant::*; pub use cross::*; pub use full_adder::*; pub use mem::*; +pub use mips_controll_unit::*; pub use mux::*; pub use probe::*; pub use probe_assert::*; diff --git a/src/gui_egui/components/mips_controll_unit.rs b/src/gui_egui/components/mips_controll_unit.rs new file mode 100644 index 00000000..79c3e07c --- /dev/null +++ b/src/gui_egui/components/mips_controll_unit.rs @@ -0,0 +1,160 @@ +use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::components::ControlUnit; +use crate::gui_egui::component_ui::{ + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::offset_helper; +use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; + +#[typetag::serde] +impl EguiComponent for ControlUnit { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + // 81x41 + // middle: 41x 21y (0 0) + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + // The shape + ui.painter().add(Shape::closed_line( + vec![ + oh((-40f32, 0f32), s, o), + oh((40f32, 0f32), s, o), + oh((40f32, 20f32), s, o), + oh((-40f32, 20f32), s, o), + ], + Stroke { + width: scale, + color: Color32::RED, + }, + )); + + let rect = Rect { + min: oh((-40f32, -20f32), s, o), + max: oh((40f32, 20f32), s, o), + }; + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + // todo: is this actually correct? + if let Some(s) = &simulator { + ui.label({ + let a_r: Result = + s.get_input_value(&self.a_in).try_into(); + let mut s: String = "".to_string(); + + match a_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", a_r), + } + format!("{}", s) + }); + ui.label("ControlUnit"); + } + }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let r_vec = ControlUnit::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_drag_value(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.a_in, + crate::components::CLK_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown + }, + ); + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + crate::components::SEXT_IN_ID.to_string(), + Pos2::new(-40f32, 0f32) + own_pos, + ), + ( + crate::components::SEXT_OUT_ID.to_string(), + Pos2::new(40f32, 0f32) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + 20f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } +} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index 4df9ec09..d243ee71 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -4,6 +4,7 @@ mod constant; mod cross; mod full_adder; mod mem; +mod mips_controll_unit; mod mux; mod probe; mod probe_assert; diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 7daded2f..1244e7cf 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -138,6 +138,11 @@ impl Default for Library { pos: (0.0, 0.0), clk_in: dummy_input.clone(), }), + Rc::new(ControlUnit { + id: "a_in".to_string(), + pos: (0.0, 0.0), + a_in: dummy_input.clone(), + }), Rc::new( (FullAdd { id: "dummy".to_string(), From 35a3031c326cbdd532b7e401e7f4d518e66a431a Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:42:29 +0200 Subject: [PATCH 010/126] added example for mips mux implementation --- examples/mips_mux.rs | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 examples/mips_mux.rs diff --git a/examples/mips_mux.rs b/examples/mips_mux.rs new file mode 100644 index 00000000..93ac11e6 --- /dev/null +++ b/examples/mips_mux.rs @@ -0,0 +1,64 @@ +use std::path::PathBuf; +#[cfg(feature = "gui-egui")] +use syncrim::gui_egui::editor::Library; +use syncrim::{ + common::{ComponentStore, Input}, + components::*, + fern::fern_setup, +}; +fn main() { + fern_setup(); + let cs = ComponentStore { + store: vec![ + Mux::rc_new( + "mux", + (200.0, 200.0), + Input::new("ctrl", "out"), + vec![Input::new("c0", "out"), Input::new("c1", "out")], + ), + ProbeEdit::rc_new("ctrl", (190.0, 100.0)), + Wire::rc_new( + "w0", + vec![(190.0, 110.0), (190.0, 150.0)], + Input::new("ctrl", "out"), + ), + Constant::rc_new("c0", (140.0, 170.0), 0), + Constant::rc_new("c1", (140.0, 190.0), 1), + // Wire::rc_new( + // "w1", + // vec![(150.0, 170.0), (180.0, 170.0)], + // Input::new("c1", "out"), + // ), + // Wire::rc_new( + // "w2", + // vec![(150.0, 190.0), (180.0, 190.0)], + // Input::new("c2", "out"), + // ), + // Wire::rc_new( + // "w3", + // vec![(150.0, 210.0), (180.0, 210.0)], + // Input::new("c3", "out"), + // ), + // Wire::rc_new( + // "w4", + // vec![(150.0, 230.0), (180.0, 230.0)], + // Input::new("c4", "out"), + // ), + // Wire::rc_new( + // "w5", + // vec![(220.0, 200.0), (250.0, 200.0)], + // Input::new("mux", "out"), + // ), + Probe::rc_new("p_mux", (260.0, 200.0), Input::new("mux", "out")), + ], + }; + + let path = PathBuf::from("mux_edit.json"); + cs.save_file(&path); + + #[cfg(feature = "gui-egui")] + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + + #[cfg(feature = "gui-vizia")] + syncrim::gui_vizia::gui(cs, &path); +} From 428ed431570377c9c760f5710c32182571d48edb Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Thu, 25 Jul 2024 13:37:29 +0200 Subject: [PATCH 011/126] olle fixar errors snart :) --- src/components/mips_im.rs | 123 +++++++++++++ src/components/mod.rs | 2 + src/gui_egui/components/mips_im.rs | 287 +++++++++++++++++++++++++++++ src/gui_egui/components/mod.rs | 1 + src/gui_egui/editor.rs | 15 ++ 5 files changed, 428 insertions(+) create mode 100644 src/components/mips_im.rs create mode 100644 src/gui_egui/components/mips_im.rs diff --git a/src/components/mips_im.rs b/src/components/mips_im.rs new file mode 100644 index 00000000..e09372be --- /dev/null +++ b/src/components/mips_im.rs @@ -0,0 +1,123 @@ +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, + SignalValue, Simulator, +}; +use core::cell::RefCell; +use core::ops::Range; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::collections::BTreeMap; +use std::collections::HashMap; +use std::collections::HashSet; +use std::rc::Rc; + +pub const INSTR_MEM_PC_ID: &str = "pc"; + +pub const INSTR_MEM_INSTRUCTION_ID: &str = "instruction"; + +pub const INSTR_MEM_HEIGHT: f32 = 100.0; +pub const INSTR_MEM_WIDTH: f32 = 100.0; + +#[derive(Serialize, Deserialize, Clone)] +pub struct InstrMem { + pub width: f32, + pub height: f32, + pub id: String, + pub pos: (f32, f32), + #[serde(skip)] + pub bytes: BTreeMap, + pub pc: Input, + pub range: Range, + #[serde(skip)] + pub breakpoints: Rc>>, + #[serde(skip)] + pub symbols: HashMap, + pub le: bool, +} + +#[typetag::serde()] +impl Component for InstrMem { + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn to_(&self) { + //println!("InstrMem"); + } + #[cfg(feature = "gui-egui")] + fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + let dummy_input = Input::new("dummy", "out"); + Box::new(Rc::new(InstrMem { + width: INSTR_MEM_WIDTH, + height: INSTR_MEM_HEIGHT, + id: id.to_string(), + pos: (pos.0, pos.1), + bytes: BTreeMap::new(), + pc: dummy_input, + range: Range { + start: 0, + end: 0x1000, + }, + breakpoints: Rc::new(RefCell::new(HashSet::new())), + symbols: HashMap::new(), + le: true, + })) + } + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + if target_port_id.as_str() == INSTR_MEM_PC_ID { + self.pc = new_input; + } + } + fn get_id_ports(&self) -> (String, Ports) { + ( + self.id.clone(), + Ports::new( + vec![&InputPort { + port_id: INSTR_MEM_PC_ID.to_string(), + input: self.pc.clone(), + }], + OutputType::Combinatorial, + vec![INSTR_MEM_INSTRUCTION_ID], + ), + ) + } + + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get instr at pc/4 + let pc: u32 = simulator.get_input_value(&self.pc).try_into().unwrap(); + let instr = if !self.le { + (*self.bytes.get(&((pc) as usize)).unwrap() as u32) << 24 + | (*self.bytes.get(&((pc + 1) as usize)).unwrap() as u32) << 16 + | (*self.bytes.get(&((pc + 2) as usize)).unwrap() as u32) << 8 + | (*self.bytes.get(&((pc + 3) as usize)).unwrap() as u32) + } else { + (*self.bytes.get(&((pc) as usize)).unwrap() as u32) + | (*self.bytes.get(&((pc + 1) as usize)).unwrap() as u32) << 8 + | (*self.bytes.get(&((pc + 2) as usize)).unwrap() as u32) << 16 + | (*self.bytes.get(&((pc + 3) as usize)).unwrap() as u32) << 24 + }; + //the asm_riscv crate incorrectly panics when trying from instead of + //returning Err, catch it and handle instead + let instruction_fmt = { + format!( + "{:?}", + match asm_riscv::I::try_from(instr) { + Ok(i) => riscv_asm_strings::StringifyUpperHex::to_string(&i), + Err(_) => "Unknown instruction".to_string(), + } + ) + }; + trace!("instruction: {}", instruction_fmt); + trace!("pc:0x{:08x}", pc); + // set output + simulator.set_out_value(&self.id, "instruction", instr); + if !self.breakpoints.borrow().contains(&(pc as usize)) { + Ok(()) + } else { + Err(Condition::Halt(format!("Breakpoint at {}", pc))) + } + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index fa877498..86604272 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -5,6 +5,7 @@ mod cross; mod full_adder; mod mem; mod mips_controll_unit; +mod mips_im; mod mux; mod probe; mod probe_assert; @@ -22,6 +23,7 @@ pub use cross::*; pub use full_adder::*; pub use mem::*; pub use mips_controll_unit::*; +pub use mips_im::*; pub use mux::*; pub use probe::*; pub use probe_assert::*; diff --git a/src/gui_egui/components/mips_im.rs b/src/gui_egui/components/mips_im.rs new file mode 100644 index 00000000..25d0dddf --- /dev/null +++ b/src/gui_egui/components/mips_im.rs @@ -0,0 +1,287 @@ +use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::components::InstrMem; +use crate::gui_egui::component_ui::{ + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::offset_helper; +use egui::{ + Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Slider, Stroke, + TextWrapMode, Ui, Vec2, +}; + +impl InstrMem { + fn side_panel(&self, ctx: &Context, simulator: Option<&mut Simulator>) { + Window::new("Instruction Memory") + .resizable(true) + .show(ctx, |ui| { + TableBuilder::new(ui) + .striped(true) + .column(Column::initial(75.0).at_least(75.0)) + .column(Column::initial(10.0).resizable(false)) + .column(Column::initial(75.0).at_least(75.0)) + .column(Column::initial(75.0).at_least(50.0)) + .column(Column::initial(150.0).at_least(85.0).resizable(true)) + .column(Column::initial(5.0).at_least(5.0).resizable(false)) + .header(30.0, |mut header| { + header.col(|ui| { + ui.heading("Label"); + }); + header.col(|_ui| {}); + header.col(|ui| { + ui.heading("Address"); + }); + header.col(|ui| { + ui.heading("HEX"); + }); + header.col(|ui| { + ui.heading("Instruction"); + }); + }) + .body(|body| { + body.rows( + 15.0, + (self.range.end - self.range.start) / 4, + |index, mut row| { + let address = index * 4 + self.range.start; + let pc: u32 = { + if simulator.as_ref().is_some() { + simulator + .as_ref() + .unwrap() + .get_input_value(&self.pc) + .try_into() + .unwrap_or(0) + } else { + 0 + } + }; + let (bg_color, fg_color) = { + if pc as usize == address { + (Color32::DARK_GRAY, Color32::WHITE) + } else { + (Color32::TRANSPARENT, Color32::LIGHT_GRAY) + } + }; + let breakpoint_color = { + if self.breakpoints.borrow_mut().contains(&address) { + Color32::RED + } else { + Color32::TRANSPARENT + } + }; + row.col(|ui| match &self.symbols.get(&address) { + Some(s) => { + ui.add(Label::new(format!("{}:", s)).truncate(true)); + } + None => {} + }); + //breakpoint + row.col(|ui| { + ui.label(RichText::new("•").color(breakpoint_color)); + }); + //address + row.col(|ui| { + ui.add(Label::new(format!("0x{:08x}", address)).truncate(true)); + }); + let mut bytes = [0u8; 4]; + if !self.le { + bytes[3] = *self.bytes.get(&address).unwrap(); + bytes[2] = *self.bytes.get(&(address + 1)).unwrap(); + bytes[1] = *self.bytes.get(&(address + 2)).unwrap(); + bytes[0] = *self.bytes.get(&(address + 3)).unwrap(); + } else { + bytes[0] = *self.bytes.get(&address).unwrap(); + bytes[1] = *self.bytes.get(&(address + 1)).unwrap(); + bytes[2] = *self.bytes.get(&(address + 2)).unwrap(); + bytes[3] = *self.bytes.get(&(address + 3)).unwrap(); + } + let instr = ((bytes[3] as u32) << 24) + | ((bytes[2] as u32) << 16) + | ((bytes[1] as u32) << 8) + | (bytes[0] as u32); + + let instr_fmt = match asm_riscv::I::try_from(instr) { + Ok(i) => riscv_asm_strings::StringifyUpperHex::to_string(&i), + Err(_) => "Unknown instruction".to_string(), + }; + //hex instr + row.col(|ui| { + ui.add(Label::new(format!("0x{:08X}", instr)).truncate(true)); + }); + row.col(|ui| { + if ui + .add( + Label::new( + RichText::new(instr_fmt) + .color(fg_color) + .background_color(bg_color), + ) + .truncate(true) + .sense(Sense::click()), + ) + .clicked() + { + trace!("clicked"); + if !self.breakpoints.borrow_mut().remove(&address) { + self.breakpoints.borrow_mut().insert(address); + } + }; + }); + row.col(|_| {}); + }, + ); + }); + }); + } +} + +#[typetag::serde] +impl EguiComponent for InstrMem { + fn render( + &self, + ui: &mut Ui, + _ctx: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + // 21x41 + // middle: 11x 21y (0 0) + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + //self.side_panel(ui.ctx(), simulator); + // The shape + let rect = Rect { + min: oh((-self.width / 2f32, -self.height / 2f32), s, o), + max: oh((self.width / 2f32, self.height / 2f32), s, o), + }; + ui.painter().add(Shape::rect_stroke( + rect, + Rounding::ZERO, + Stroke { + width: scale, + color: Color32::BLACK, + }, + )); + ui.painter().text( + o.to_pos2(), + egui::Align2::CENTER_CENTER, + "InstrMem", + FontId::monospace(14.0), + Color32::BLACK, + ); + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + ui.label("InstrMem"); + }); + match editor_mode { + EditorMode::Simulator => { + self.side_panel(ui.ctx(), simulator); + } + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(syncrim::common::Id, Ports)], + grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let r_vec = InstrMem::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_drag_value(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.pc, + crate::components::INSTR_MEM_PC_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown + }, + ); + + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(syncrim::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + crate::components::INSTR_MEM_PC_ID.to_string(), + Pos2::new( + self.width / 10f32 * 1f32 - self.width / 2f32, + -self.height / 2f32, + ) + own_pos, + ), + ( + crate::components::INSTR_MEM_INSTRUCTION_ID.to_string(), + Pos2::new( + -self.width / 10f32 * 2f32 + self.width / 2f32, + -self.height / 2f32, + ) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + self.height / 4f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } +} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index d243ee71..8f0ccfb6 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -5,6 +5,7 @@ mod cross; mod full_adder; mod mem; mod mips_controll_unit; +mod mips_im; mod mux; mod probe; mod probe_assert; diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 1244e7cf..4ff80d12 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -143,6 +143,21 @@ impl Default for Library { pos: (0.0, 0.0), a_in: dummy_input.clone(), }), + Rc::new(InstrMem { + width: INSTR_MEM_WIDTH, + height: INSTR_MEM_HEIGHT, + id: "instruction".to_string(), + pos: (0.0, 0.0), + bytes: BTreeMap::new(), + pc: dummy_input, + range: Range { + start: 0, + end: 0x1000, + }, + breakpoints: Rc::new(RefCell::new(HashSet::new())), + symbols: HashMap::new(), + le: true, + }), Rc::new( (FullAdd { id: "dummy".to_string(), From ff1e9d01069acc339f745d166f35a2ad29b67762 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 25 Jul 2024 15:17:59 +0200 Subject: [PATCH 012/126] update probe to try parse as unsigned if signed parse failes --- src/gui_egui/components/probe_edit.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui_egui/components/probe_edit.rs b/src/gui_egui/components/probe_edit.rs index 6ca94558..14cea32d 100644 --- a/src/gui_egui/components/probe_edit.rs +++ b/src/gui_egui/components/probe_edit.rs @@ -178,6 +178,8 @@ fn parse_signal(text: &str) -> SignalValue { if let Ok(signal) = text.parse::() { (signal as SignalUnsigned).into() + } else if let Ok(signal) = text.parse::() { + (signal as SignalUnsigned).into() } else if let Some(hex) = text.strip_prefix("0x") { if let Ok(signal) = SignalUnsigned::from_str_radix(hex, 16) { signal.into() From b4f208cf9a21f334c02e6a2898e1137cd90fd4c8 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:38:24 +0200 Subject: [PATCH 013/126] work in progress cu --- src/components/mips_controll_unit.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/mips_controll_unit.rs b/src/components/mips_controll_unit.rs index e7ec5290..9e8ae9df 100644 --- a/src/components/mips_controll_unit.rs +++ b/src/components/mips_controll_unit.rs @@ -78,10 +78,12 @@ impl Component for ControlUnit { // get input values let a: u32 = simulator.get_input_value(&self.a_in).try_into().unwrap(); - // let a_OpCode: u32 = (a >> 26) & 0x0000_003f; - // let a_func: u32 = a & 0x0000_001f; - let a_OpCode: u32 = a; - let a_func: u32 = 0; + let a_OpCode: u32 = (&a >> 26) & 0x0000_003f; + let a_func: u32 = &a & 0x0000_001f; + debug!("opcode: {:#010x}", a_OpCode); + debug!(" func: {:#010x}", a_func); + // let a_OpCode: u32 = a; + // let a_func: u32 = 0; let MemToReg; let MemWrite; From a718593c90f70e4c1f3e738f47dad27a8cbcb5a8 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Fri, 26 Jul 2024 14:00:33 +0200 Subject: [PATCH 014/126] updated full adder --- src/components/full_adder.rs | 238 +++++++++++++++++++------- src/gui_egui/components/full_adder.rs | 42 ++++- 2 files changed, 213 insertions(+), 67 deletions(-) diff --git a/src/components/full_adder.rs b/src/components/full_adder.rs index d90ec0b5..bb383605 100644 --- a/src/components/full_adder.rs +++ b/src/components/full_adder.rs @@ -13,9 +13,25 @@ use std::rc::Rc; pub const FULL_ADD_A_IN_ID: &str = "full_add_a_in"; pub const FULL_ADD_B_IN_ID: &str = "full_add_b_in"; pub const FULL_ADD_OP_IN_ID: &str = "full_add_op_in"; - pub const FULL_ADD_OUT_ID: &str = "out"; +pub mod alu_op { + pub const ADD: u32 = 0; + pub const ADDU: u32 = 1; + pub const SUB: u32 = 2; + pub const SUBU: u32 = 3; + pub const AND: u32 = 4; + pub const OR: u32 = 5; + pub const XOR: u32 = 6; + pub const NOR: u32 = 7; + pub const SLT: u32 = 8; + pub const SLTU: u32 = 9; + pub const SLL: u32 = 10; + pub const SRL: u32 = 11; + pub const SRA: u32 = 12; + pub const LUI: u32 = 13; +} + #[derive(Serialize, Deserialize, Clone)] pub struct FullAdd { pub(crate) id: Id, @@ -74,78 +90,64 @@ impl Component for FullAdd { } } - // propagate sign extension to output - // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { // get input values let a: u32 = simulator.get_input_value(&self.a_in).try_into().unwrap(); let b: u32 = simulator.get_input_value(&self.b_in).try_into().unwrap(); let op: u32 = simulator.get_input_value(&self.op_in).try_into().unwrap(); - const OPADD: u32 = 0; - const OPADDU: u32 = 1; - const OPSUB: u32 = 2; - const OPSUBU: u32 = 3; - const OPAND: u32 = 4; - const OPOR: u32 = 5; - const OPXOR: u32 = 6; - const OPNOR: u32 = 7; - const OPDONOTHING: u32 = 8; - const OPSLT: u32 = 10; - const OPSLTU: u32 = 11; - const OPSLL: u32 = 12; - const OPSRL: u32 = 13; - const OPSRA: u32 = 14; - const OPLUI: u32 = 15; - let output: u32; - //pub const HEAT: &str = "heat".to_uppercase().as_str(); - - // if op == 1 { - // op = 0xFFFFFFFF; - // } else { - // op = 0x00000000; - // } - - if op == OPADD { - output = a.wrapping_add(b); - } else if op == OPSUB { - output = a.wrapping_add(b ^ 0xffffffff).wrapping_add(1); - } else if op == OPAND { - output = (a & b); - } else if op == OPOR { - output = (a | b); - } else if op == OPXOR { - output = (a ^ b); - } else if op == OPNOR { - output = !(a | b); - } else if op == OPDONOTHING { - // output = - todo!("something sll r0 r0 0"); - } else if op == OPSLT { - output = (0 == a.wrapping_add(b ^ op).wrapping_add(1)) as u32; - } else if op == OPSLL { - output = (a << b); - } else if op == OPSRL { - output = (a >> b); - } else if op == OPSRA { - output = ((a as i32) >> b) as u32; - } else if op == OPLUI { - output = (b << 16); - } else { - output = 0xffffffff; - return Err(Condition::Error("undef opcode".to_string())); + match op { + alu_op::ADD => { + output = a.wrapping_add(b); + } + alu_op::ADDU => { + return Err(Condition::Error("ADDU not implemented".to_string())); + } + alu_op::SUB => { + output = a.wrapping_add(b ^ 0xffffffff).wrapping_add(1); + } + alu_op::SUBU => { + return Err(Condition::Error("SUBU not implemented".to_string())); + } + alu_op::AND => { + output = (a & b); + } + alu_op::OR => { + output = (a | b); + } + alu_op::XOR => { + output = (a ^ b); + } + alu_op::NOR => { + output = !(a | b); + } + alu_op::SLT => { + output = ((a as i32) < (b as i32)) as u32; + } + alu_op::SLTU => { + output = (a < b) as u32; + } + alu_op::SLL => { + output = a << b; + } + alu_op::SRL => { + output = a >> b; + } + alu_op::SRA => { + output = ((a as i32) >> b) as u32; + } + alu_op::LUI => { + output = (a & 0x0000_ffff) | (b << 16); + } + _ => { + return Err(Condition::Error( + "undef alu operation or unimplemented instruction".to_string(), + )); + } } - - //let j: u32 = a.wrapping_add(b ^ op).wrapping_add(1 & op); - - simulator.set_out_value( - &self.id, - FULL_ADD_OUT_ID, - SignalValue::Data(output), - //SignalValue::Data(((a as i32) + (b as i32)) as u32), - ); + simulator.set_out_value(&self.id, FULL_ADD_OUT_ID, SignalValue::Data(output)); Ok(()) } @@ -169,3 +171,111 @@ impl FullAdd { Rc::new(FullAdd::new(id, pos, a_in, b_in, op_in)) } } + +mod test { + use super::*; + + use crate::{ + common::{ComponentStore, Input, SignalUnsigned, Simulator}, + components::ProbeOut, + }; + use std::rc::Rc; + + #[test] + fn test_some_alu_op() { + let cs = ComponentStore { + store: vec![ + Rc::new(ProbeOut::new("op")), + Rc::new(ProbeOut::new("a")), + Rc::new(ProbeOut::new("b")), + FullAdd::rc_new( + "ALU", + (0.0, 0.0), + Input::new("a", "out"), + Input::new("b", "out"), + Input::new("op", "out"), + ), + ], + }; + let mut simulator = Simulator::new(cs).unwrap(); + + assert_eq!(simulator.cycle, 1); + + // outputs + let alu_val = &Input::new("ALU", "out"); + + // reset + assert_eq!(simulator.get_input_value(alu_val), (0 + 0).into()); + + println!(""); + simulator.set_out_value("a", "out", 42); + simulator.set_out_value("b", "out", 1337); + simulator.set_out_value("op", "out", OPADD); + println!("sim_state {:?}", simulator.sim_state); + println!(""); + simulator.clock(); + println!("sim_state {:?}", simulator.sim_state); + assert_eq!(simulator.cycle, 2); + assert_eq!( + simulator.get_input_value(alu_val), + (42 + 1337).into(), + "testing add (1)" + ); + + println!(""); + simulator.set_out_value("a", "out", (-100i32 as u32)); + simulator.set_out_value("b", "out", 1337); + simulator.set_out_value("op", "out", OPADD); + println!("sim_state {:?}", simulator.sim_state); + println!(""); + simulator.clock(); + println!("sim_state {:?}", simulator.sim_state); + assert_eq!( + simulator.get_input_value(alu_val), + (1337 - 100).into(), + "testing add (2)" + ); + + println!(""); + simulator.set_out_value("a", "out", (-100i32 as u32)); + simulator.set_out_value("b", "out", 1337); + simulator.set_out_value("op", "out", OPSUB); + println!("sim_state {:?}", simulator.sim_state); + println!(""); + simulator.clock(); + println!("sim_state {:?}", simulator.sim_state); + assert_eq!( + simulator.get_input_value(alu_val), + ((-100i32 - 1337) as u32).into(), + "testing sub" + ); + + println!(""); + simulator.set_out_value("a", "out", (-100i32 as u32)); + simulator.set_out_value("b", "out", 1337); + simulator.set_out_value("op", "out", OPSLT); + println!("sim_state {:?}", simulator.sim_state); + println!(""); + simulator.clock(); + println!("sim_state {:?}", simulator.sim_state); + assert_eq!( + simulator.get_input_value(alu_val), + true.into(), + "testing SLT" + ); + + println!(""); + simulator.set_out_value("a", "out", (-100i32 as u32)); + simulator.set_out_value("b", "out", 1337); + simulator.set_out_value("op", "out", OPSLTU); + println!("sim_state {:?}", simulator.sim_state); + println!(""); + simulator.clock(); + println!("sim_state {:?}", simulator.sim_state); + assert_eq!( + simulator.get_input_value(alu_val), + false.into(), + "testing SLT" + ); + } +} diff --git a/src/gui_egui/components/full_adder.rs b/src/gui_egui/components/full_adder.rs index 072f1eb8..3200200b 100644 --- a/src/gui_egui/components/full_adder.rs +++ b/src/gui_egui/components/full_adder.rs @@ -1,5 +1,5 @@ use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; -use crate::components::FullAdd; +use crate::components::{alu_op, FullAdd}; use crate::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, visualize_ports, @@ -45,9 +45,45 @@ impl EguiComponent for FullAdd { )); let rect = Rect { - min: oh((-40f32, -20f32), s, o), - max: oh((40f32, 20f32), s, o), + min: oh((-20f32, -40f32), s, o), + max: oh((20f32, 40f32), s, o), }; + let op: String = if let Some(s) = simulator { + match TryInto::::try_into(s.get_input_value(&self.op_in)).unwrap() { + alu_op::ADD => "ADD", + alu_op::ADDU => "ADDU", + alu_op::SUB => "SUB", + alu_op::SUBU => "SUBU", + alu_op::AND => "AND", + alu_op::OR => "OR", + alu_op::XOR => "XOR", + alu_op::NOR => "NOR", + alu_op::SLT => "SLT", + alu_op::SLTU => "SLTU", + alu_op::SLL => "SLL", + alu_op::SRL => "SRL", + alu_op::SRA => "SRA", + alu_op::LUI => "LUI", + _ => "UNDEF", + } + .to_string() + } else { + "no sim".to_string() + }; + + let area = Area::new(egui::Id::from(self.id.to_string())) + .order(Order::Middle) + .current_pos(offset.to_pos2() + Vec2::new(5.0, 0.0) * scale) + .movable(false) + .enabled(true) + .interactable(false) + .pivot(Align2::CENTER_CENTER) + .constrain(false) + .show(ui.ctx(), |ui| { + ui.set_clip_rect(clip_rect); + ui.style_mut().wrap_mode = Some(TextWrapMode::Extend); + ui.label(RichText::new(format!("ALU\n{}", op)).size(scale * 12f32)) + }); let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { ui.label(format!("Id: {}", self.id.clone())); // todo: is this actually correct? From a7b6f40ed0cb7bb0c8539ce614b29de392f29a33 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Sun, 28 Jul 2024 22:49:04 +0200 Subject: [PATCH 015/126] olle tmp work --- src/components/mips_controll_unit.rs | 37 +- src/components/mips_im.rs | 232 +++++------ src/fern.rs | 4 +- src/gui_egui/components/mips_im.rs | 554 +++++++++++++-------------- src/gui_egui/editor.rs | 30 +- 5 files changed, 443 insertions(+), 414 deletions(-) diff --git a/src/components/mips_controll_unit.rs b/src/components/mips_controll_unit.rs index 9e8ae9df..8581b309 100644 --- a/src/components/mips_controll_unit.rs +++ b/src/components/mips_controll_unit.rs @@ -21,6 +21,39 @@ pub const CONTROL_UNIT_REGDST_ID: &str = "RegDst"; pub const CONTROL_UNIT_WRITEENABLE_ID: &str = "WriteEnable"; pub const CONTROL_UNIT_JUMP_ID: &str = "Jump"; +const NOP: u32 = 0; +const OP_0: u32 = 0; +const OP_1: u32 = 1; +const OP_J: u32 = 0b000_010; +const OP_JAL: u32 = 0b000_011; +const OP_BEQ: u32 = 0b000_100; +const OP_BNE: u32 = 0b000_101; +const OP_BLEZ: u32 = 0b000_110; +const OP_BGTZ: u32 = 0b000_111; +const OP_ADDI: u32 = 0b001_000; +const OP_ADDIU: u32 = 0b001_001; +const OP_SLTI: u32 = 0b001_010; +const OP_SLTIU: u32 = 0b001_011; +const OP_ANDI: u32 = 0b001_100; +const OP_ORI: u32 = 0b001_101; +const OP_XORI: u32 = 0b001_110; +const OP_LUI: u32 = 0b001_111; +const CP0: u32 = 0b010_000; + +const OP_LB: u32 = 0b100_000; +const OP_LH: u32 = 0b100_001; +const OP_LWL: u32 = 0b100_010; +const OP_LW: u32 = 0b100_011; +const OP_LBU: u32 = 0b100_100; +const OP_LHU: u32 = 0b100_101; +const OP_LWR: u32 = 0b100_110; + +const OP_SB: u32 = 0b101_000; +const OP_SH: u32 = 0b101_001; +const OP_SWL: u32 = 0b101_010; +const OP_SW: u32 = 0b101_011; +const OP_SWR: u32 = 0b101_110; + #[derive(Serialize, Deserialize, Clone)] pub struct ControlUnit { pub(crate) id: Id, @@ -80,10 +113,6 @@ impl Component for ControlUnit { let a_OpCode: u32 = (&a >> 26) & 0x0000_003f; let a_func: u32 = &a & 0x0000_001f; - debug!("opcode: {:#010x}", a_OpCode); - debug!(" func: {:#010x}", a_func); - // let a_OpCode: u32 = a; - // let a_func: u32 = 0; let MemToReg; let MemWrite; diff --git a/src/components/mips_im.rs b/src/components/mips_im.rs index e09372be..a02c8353 100644 --- a/src/components/mips_im.rs +++ b/src/components/mips_im.rs @@ -1,123 +1,123 @@ -#[cfg(feature = "gui-egui")] -use crate::common::EguiComponent; -use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, - SignalValue, Simulator, -}; -use core::cell::RefCell; -use core::ops::Range; -use log::*; -use serde::{Deserialize, Serialize}; -use std::any::Any; -use std::collections::BTreeMap; -use std::collections::HashMap; -use std::collections::HashSet; -use std::rc::Rc; +// #[cfg(feature = "gui-egui")] +// use crate::common::EguiComponent; +// use crate::common::{ +// Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, +// SignalValue, Simulator, +// }; +// use core::cell::RefCell; +// use core::ops::Range; +// use log::*; +// use serde::{Deserialize, Serialize}; +// use std::any::Any; +// use std::collections::BTreeMap; +// use std::collections::HashMap; +// use std::collections::HashSet; +// use std::rc::Rc; -pub const INSTR_MEM_PC_ID: &str = "pc"; +// pub const INSTR_MEM_PC_ID: &str = "pc"; -pub const INSTR_MEM_INSTRUCTION_ID: &str = "instruction"; +// pub const INSTR_MEM_INSTRUCTION_ID: &str = "instruction"; -pub const INSTR_MEM_HEIGHT: f32 = 100.0; -pub const INSTR_MEM_WIDTH: f32 = 100.0; +// pub const INSTR_MEM_HEIGHT: f32 = 100.0; +// pub const INSTR_MEM_WIDTH: f32 = 100.0; -#[derive(Serialize, Deserialize, Clone)] -pub struct InstrMem { - pub width: f32, - pub height: f32, - pub id: String, - pub pos: (f32, f32), - #[serde(skip)] - pub bytes: BTreeMap, - pub pc: Input, - pub range: Range, - #[serde(skip)] - pub breakpoints: Rc>>, - #[serde(skip)] - pub symbols: HashMap, - pub le: bool, -} +// #[derive(Serialize, Deserialize, Clone)] +// pub struct InstrMem { +// pub width: f32, +// pub height: f32, +// pub id: String, +// pub pos: (f32, f32), +// #[serde(skip)] +// pub bytes: BTreeMap, +// pub pc: Input, +// pub range: Range, +// #[serde(skip)] +// pub breakpoints: Rc>>, +// #[serde(skip)] +// pub symbols: HashMap, +// pub le: bool, +// } -#[typetag::serde()] -impl Component for InstrMem { - fn as_any(&self) -> &dyn std::any::Any { - self - } +// #[typetag::serde()] +// impl Component for InstrMem { +// fn as_any(&self) -> &dyn std::any::Any { +// self +// } - fn to_(&self) { - //println!("InstrMem"); - } - #[cfg(feature = "gui-egui")] - fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { - let dummy_input = Input::new("dummy", "out"); - Box::new(Rc::new(InstrMem { - width: INSTR_MEM_WIDTH, - height: INSTR_MEM_HEIGHT, - id: id.to_string(), - pos: (pos.0, pos.1), - bytes: BTreeMap::new(), - pc: dummy_input, - range: Range { - start: 0, - end: 0x1000, - }, - breakpoints: Rc::new(RefCell::new(HashSet::new())), - symbols: HashMap::new(), - le: true, - })) - } - fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { - if target_port_id.as_str() == INSTR_MEM_PC_ID { - self.pc = new_input; - } - } - fn get_id_ports(&self) -> (String, Ports) { - ( - self.id.clone(), - Ports::new( - vec![&InputPort { - port_id: INSTR_MEM_PC_ID.to_string(), - input: self.pc.clone(), - }], - OutputType::Combinatorial, - vec![INSTR_MEM_INSTRUCTION_ID], - ), - ) - } +// fn to_(&self) { +// //println!("InstrMem"); +// } +// #[cfg(feature = "gui-egui")] +// fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { +// let dummy_input = Input::new("dummy", "out"); +// Box::new(Rc::new(InstrMem { +// width: INSTR_MEM_WIDTH, +// height: INSTR_MEM_HEIGHT, +// id: id.to_string(), +// pos: (pos.0, pos.1), +// bytes: BTreeMap::new(), +// pc: dummy_input, +// range: Range { +// start: 0, +// end: 0x1000, +// }, +// breakpoints: Rc::new(RefCell::new(HashSet::new())), +// symbols: HashMap::new(), +// le: true, +// })) +// } +// fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { +// if target_port_id.as_str() == INSTR_MEM_PC_ID { +// self.pc = new_input; +// } +// } +// fn get_id_ports(&self) -> (String, Ports) { +// ( +// self.id.clone(), +// Ports::new( +// vec![&InputPort { +// port_id: INSTR_MEM_PC_ID.to_string(), +// input: self.pc.clone(), +// }], +// OutputType::Combinatorial, +// vec![INSTR_MEM_INSTRUCTION_ID], +// ), +// ) +// } - fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { - // get instr at pc/4 - let pc: u32 = simulator.get_input_value(&self.pc).try_into().unwrap(); - let instr = if !self.le { - (*self.bytes.get(&((pc) as usize)).unwrap() as u32) << 24 - | (*self.bytes.get(&((pc + 1) as usize)).unwrap() as u32) << 16 - | (*self.bytes.get(&((pc + 2) as usize)).unwrap() as u32) << 8 - | (*self.bytes.get(&((pc + 3) as usize)).unwrap() as u32) - } else { - (*self.bytes.get(&((pc) as usize)).unwrap() as u32) - | (*self.bytes.get(&((pc + 1) as usize)).unwrap() as u32) << 8 - | (*self.bytes.get(&((pc + 2) as usize)).unwrap() as u32) << 16 - | (*self.bytes.get(&((pc + 3) as usize)).unwrap() as u32) << 24 - }; - //the asm_riscv crate incorrectly panics when trying from instead of - //returning Err, catch it and handle instead - let instruction_fmt = { - format!( - "{:?}", - match asm_riscv::I::try_from(instr) { - Ok(i) => riscv_asm_strings::StringifyUpperHex::to_string(&i), - Err(_) => "Unknown instruction".to_string(), - } - ) - }; - trace!("instruction: {}", instruction_fmt); - trace!("pc:0x{:08x}", pc); - // set output - simulator.set_out_value(&self.id, "instruction", instr); - if !self.breakpoints.borrow().contains(&(pc as usize)) { - Ok(()) - } else { - Err(Condition::Halt(format!("Breakpoint at {}", pc))) - } - } -} +// fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { +// // get instr at pc/4 +// let pc: u32 = simulator.get_input_value(&self.pc).try_into().unwrap(); +// let instr = if !self.le { +// (*self.bytes.get(&((pc) as usize)).unwrap() as u32) << 24 +// | (*self.bytes.get(&((pc + 1) as usize)).unwrap() as u32) << 16 +// | (*self.bytes.get(&((pc + 2) as usize)).unwrap() as u32) << 8 +// | (*self.bytes.get(&((pc + 3) as usize)).unwrap() as u32) +// } else { +// (*self.bytes.get(&((pc) as usize)).unwrap() as u32) +// | (*self.bytes.get(&((pc + 1) as usize)).unwrap() as u32) << 8 +// | (*self.bytes.get(&((pc + 2) as usize)).unwrap() as u32) << 16 +// | (*self.bytes.get(&((pc + 3) as usize)).unwrap() as u32) << 24 +// }; +// //the asm_riscv crate incorrectly panics when trying from instead of +// //returning Err, catch it and handle instead +// let instruction_fmt = { +// format!( +// "{:?}", +// match asm_riscv::I::try_from(instr) { +// Ok(i) => riscv_asm_strings::StringifyUpperHex::to_string(&i), +// Err(_) => "Unknown instruction".to_string(), +// } +// ) +// }; +// trace!("instruction: {}", instruction_fmt); +// trace!("pc:0x{:08x}", pc); +// // set output +// simulator.set_out_value(&self.id, "instruction", instr); +// if !self.breakpoints.borrow().contains(&(pc as usize)) { +// Ok(()) +// } else { +// Err(Condition::Halt(format!("Breakpoint at {}", pc))) +// } +// } +// } diff --git a/src/fern.rs b/src/fern.rs index 79f23af5..8b80fb23 100644 --- a/src/fern.rs +++ b/src/fern.rs @@ -16,8 +16,8 @@ pub fn fern_setup() { }) // Add blanket level filter - // .level(log::LevelFilter::Debug); - // .level(log::LevelFilter::Trace); - .level(log::LevelFilter::Off); + .level(log::LevelFilter::Trace); + // .level(log::LevelFilter::Off); // - and per-module overrides #[cfg(feature = "gui-vizia")] diff --git a/src/gui_egui/components/mips_im.rs b/src/gui_egui/components/mips_im.rs index 25d0dddf..c6d48937 100644 --- a/src/gui_egui/components/mips_im.rs +++ b/src/gui_egui/components/mips_im.rs @@ -1,287 +1,287 @@ -use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; -use crate::components::InstrMem; -use crate::gui_egui::component_ui::{ - drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, - rect_with_hover, visualize_ports, -}; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; -use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::offset_helper; -use egui::{ - Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Slider, Stroke, - TextWrapMode, Ui, Vec2, -}; +// use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +// use crate::components::InstrMem; +// use crate::gui_egui::component_ui::{ +// drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, +// rect_with_hover, visualize_ports, +// }; +// use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +// use crate::gui_egui::gui::EguiExtra; +// use crate::gui_egui::helper::offset_helper; +// use egui::{ +// Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Slider, Stroke, +// TextWrapMode, Ui, Vec2, +// }; -impl InstrMem { - fn side_panel(&self, ctx: &Context, simulator: Option<&mut Simulator>) { - Window::new("Instruction Memory") - .resizable(true) - .show(ctx, |ui| { - TableBuilder::new(ui) - .striped(true) - .column(Column::initial(75.0).at_least(75.0)) - .column(Column::initial(10.0).resizable(false)) - .column(Column::initial(75.0).at_least(75.0)) - .column(Column::initial(75.0).at_least(50.0)) - .column(Column::initial(150.0).at_least(85.0).resizable(true)) - .column(Column::initial(5.0).at_least(5.0).resizable(false)) - .header(30.0, |mut header| { - header.col(|ui| { - ui.heading("Label"); - }); - header.col(|_ui| {}); - header.col(|ui| { - ui.heading("Address"); - }); - header.col(|ui| { - ui.heading("HEX"); - }); - header.col(|ui| { - ui.heading("Instruction"); - }); - }) - .body(|body| { - body.rows( - 15.0, - (self.range.end - self.range.start) / 4, - |index, mut row| { - let address = index * 4 + self.range.start; - let pc: u32 = { - if simulator.as_ref().is_some() { - simulator - .as_ref() - .unwrap() - .get_input_value(&self.pc) - .try_into() - .unwrap_or(0) - } else { - 0 - } - }; - let (bg_color, fg_color) = { - if pc as usize == address { - (Color32::DARK_GRAY, Color32::WHITE) - } else { - (Color32::TRANSPARENT, Color32::LIGHT_GRAY) - } - }; - let breakpoint_color = { - if self.breakpoints.borrow_mut().contains(&address) { - Color32::RED - } else { - Color32::TRANSPARENT - } - }; - row.col(|ui| match &self.symbols.get(&address) { - Some(s) => { - ui.add(Label::new(format!("{}:", s)).truncate(true)); - } - None => {} - }); - //breakpoint - row.col(|ui| { - ui.label(RichText::new("•").color(breakpoint_color)); - }); - //address - row.col(|ui| { - ui.add(Label::new(format!("0x{:08x}", address)).truncate(true)); - }); - let mut bytes = [0u8; 4]; - if !self.le { - bytes[3] = *self.bytes.get(&address).unwrap(); - bytes[2] = *self.bytes.get(&(address + 1)).unwrap(); - bytes[1] = *self.bytes.get(&(address + 2)).unwrap(); - bytes[0] = *self.bytes.get(&(address + 3)).unwrap(); - } else { - bytes[0] = *self.bytes.get(&address).unwrap(); - bytes[1] = *self.bytes.get(&(address + 1)).unwrap(); - bytes[2] = *self.bytes.get(&(address + 2)).unwrap(); - bytes[3] = *self.bytes.get(&(address + 3)).unwrap(); - } - let instr = ((bytes[3] as u32) << 24) - | ((bytes[2] as u32) << 16) - | ((bytes[1] as u32) << 8) - | (bytes[0] as u32); +// impl InstrMem { +// fn side_panel(&self, ctx: &Context, simulator: Option<&mut Simulator>) { +// Window::new("Instruction Memory") +// .resizable(true) +// .show(ctx, |ui| { +// TableBuilder::new(ui) +// .striped(true) +// .column(Column::initial(75.0).at_least(75.0)) +// .column(Column::initial(10.0).resizable(false)) +// .column(Column::initial(75.0).at_least(75.0)) +// .column(Column::initial(75.0).at_least(50.0)) +// .column(Column::initial(150.0).at_least(85.0).resizable(true)) +// .column(Column::initial(5.0).at_least(5.0).resizable(false)) +// .header(30.0, |mut header| { +// header.col(|ui| { +// ui.heading("Label"); +// }); +// header.col(|_ui| {}); +// header.col(|ui| { +// ui.heading("Address"); +// }); +// header.col(|ui| { +// ui.heading("HEX"); +// }); +// header.col(|ui| { +// ui.heading("Instruction"); +// }); +// }) +// .body(|body| { +// body.rows( +// 15.0, +// (self.range.end - self.range.start) / 4, +// |index, mut row| { +// let address = index * 4 + self.range.start; +// let pc: u32 = { +// if simulator.as_ref().is_some() { +// simulator +// .as_ref() +// .unwrap() +// .get_input_value(&self.pc) +// .try_into() +// .unwrap_or(0) +// } else { +// 0 +// } +// }; +// let (bg_color, fg_color) = { +// if pc as usize == address { +// (Color32::DARK_GRAY, Color32::WHITE) +// } else { +// (Color32::TRANSPARENT, Color32::LIGHT_GRAY) +// } +// }; +// let breakpoint_color = { +// if self.breakpoints.borrow_mut().contains(&address) { +// Color32::RED +// } else { +// Color32::TRANSPARENT +// } +// }; +// row.col(|ui| match &self.symbols.get(&address) { +// Some(s) => { +// ui.add(Label::new(format!("{}:", s)).truncate(true)); +// } +// None => {} +// }); +// //breakpoint +// row.col(|ui| { +// ui.label(RichText::new("•").color(breakpoint_color)); +// }); +// //address +// row.col(|ui| { +// ui.add(Label::new(format!("0x{:08x}", address)).truncate(true)); +// }); +// let mut bytes = [0u8; 4]; +// if !self.le { +// bytes[3] = *self.bytes.get(&address).unwrap(); +// bytes[2] = *self.bytes.get(&(address + 1)).unwrap(); +// bytes[1] = *self.bytes.get(&(address + 2)).unwrap(); +// bytes[0] = *self.bytes.get(&(address + 3)).unwrap(); +// } else { +// bytes[0] = *self.bytes.get(&address).unwrap(); +// bytes[1] = *self.bytes.get(&(address + 1)).unwrap(); +// bytes[2] = *self.bytes.get(&(address + 2)).unwrap(); +// bytes[3] = *self.bytes.get(&(address + 3)).unwrap(); +// } +// let instr = ((bytes[3] as u32) << 24) +// | ((bytes[2] as u32) << 16) +// | ((bytes[1] as u32) << 8) +// | (bytes[0] as u32); - let instr_fmt = match asm_riscv::I::try_from(instr) { - Ok(i) => riscv_asm_strings::StringifyUpperHex::to_string(&i), - Err(_) => "Unknown instruction".to_string(), - }; - //hex instr - row.col(|ui| { - ui.add(Label::new(format!("0x{:08X}", instr)).truncate(true)); - }); - row.col(|ui| { - if ui - .add( - Label::new( - RichText::new(instr_fmt) - .color(fg_color) - .background_color(bg_color), - ) - .truncate(true) - .sense(Sense::click()), - ) - .clicked() - { - trace!("clicked"); - if !self.breakpoints.borrow_mut().remove(&address) { - self.breakpoints.borrow_mut().insert(address); - } - }; - }); - row.col(|_| {}); - }, - ); - }); - }); - } -} +// let instr_fmt = match asm_riscv::I::try_from(instr) { +// Ok(i) => riscv_asm_strings::StringifyUpperHex::to_string(&i), +// Err(_) => "Unknown instruction".to_string(), +// }; +// //hex instr +// row.col(|ui| { +// ui.add(Label::new(format!("0x{:08X}", instr)).truncate(true)); +// }); +// row.col(|ui| { +// if ui +// .add( +// Label::new( +// RichText::new(instr_fmt) +// .color(fg_color) +// .background_color(bg_color), +// ) +// .truncate(true) +// .sense(Sense::click()), +// ) +// .clicked() +// { +// trace!("clicked"); +// if !self.breakpoints.borrow_mut().remove(&address) { +// self.breakpoints.borrow_mut().insert(address); +// } +// }; +// }); +// row.col(|_| {}); +// }, +// ); +// }); +// }); +// } +// } -#[typetag::serde] -impl EguiComponent for InstrMem { - fn render( - &self, - ui: &mut Ui, - _ctx: &mut EguiExtra, - simulator: Option<&mut Simulator>, - offset: Vec2, - scale: f32, - clip_rect: Rect, - editor_mode: EditorMode, - ) -> Option> { - // 21x41 - // middle: 11x 21y (0 0) - let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; - let offset_old = offset; - let mut offset = offset; - offset.x += self.pos.0 * scale; - offset.y += self.pos.1 * scale; - let s = scale; - let o = offset; - //self.side_panel(ui.ctx(), simulator); - // The shape - let rect = Rect { - min: oh((-self.width / 2f32, -self.height / 2f32), s, o), - max: oh((self.width / 2f32, self.height / 2f32), s, o), - }; - ui.painter().add(Shape::rect_stroke( - rect, - Rounding::ZERO, - Stroke { - width: scale, - color: Color32::BLACK, - }, - )); - ui.painter().text( - o.to_pos2(), - egui::Align2::CENTER_CENTER, - "InstrMem", - FontId::monospace(14.0), - Color32::BLACK, - ); - let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - ui.label(format!("Id: {}", self.id.clone())); - ui.label("InstrMem"); - }); - match editor_mode { - EditorMode::Simulator => { - self.side_panel(ui.ctx(), simulator); - } - _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), - } - Some(vec![r]) - } +// #[typetag::serde] +// impl EguiComponent for InstrMem { +// fn render( +// &self, +// ui: &mut Ui, +// _ctx: &mut EguiExtra, +// simulator: Option<&mut Simulator>, +// offset: Vec2, +// scale: f32, +// clip_rect: Rect, +// editor_mode: EditorMode, +// ) -> Option> { +// // 21x41 +// // middle: 11x 21y (0 0) +// let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; +// let offset_old = offset; +// let mut offset = offset; +// offset.x += self.pos.0 * scale; +// offset.y += self.pos.1 * scale; +// let s = scale; +// let o = offset; +// //self.side_panel(ui.ctx(), simulator); +// // The shape +// let rect = Rect { +// min: oh((-self.width / 2f32, -self.height / 2f32), s, o), +// max: oh((self.width / 2f32, self.height / 2f32), s, o), +// }; +// ui.painter().add(Shape::rect_stroke( +// rect, +// Rounding::ZERO, +// Stroke { +// width: scale, +// color: Color32::BLACK, +// }, +// )); +// ui.painter().text( +// o.to_pos2(), +// egui::Align2::CENTER_CENTER, +// "InstrMem", +// FontId::monospace(14.0), +// Color32::BLACK, +// ); +// let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { +// ui.label(format!("Id: {}", self.id.clone())); +// ui.label("InstrMem"); +// }); +// match editor_mode { +// EditorMode::Simulator => { +// self.side_panel(ui.ctx(), simulator); +// } +// _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), +// } +// Some(vec![r]) +// } - fn render_editor( - &mut self, - ui: &mut Ui, - context: &mut EguiExtra, - simulator: Option<&mut Simulator>, - offset: Vec2, - scale: f32, - clip_rect: Rect, - id_ports: &[(syncrim::common::Id, Ports)], - grid: &GridOptions, - editor_mode: EditorMode, - ) -> EditorRenderReturn { - let r_vec = InstrMem::render( - self, - ui, - context, - simulator, - offset, - scale, - clip_rect, - editor_mode, - ) - .unwrap(); - let resp = &r_vec[0]; - let delete = drag_logic( - ui.ctx(), - resp, - &mut self.pos, - &mut context.pos_tmp, - scale, - offset, - grid, - ); +// fn render_editor( +// &mut self, +// ui: &mut Ui, +// context: &mut EguiExtra, +// simulator: Option<&mut Simulator>, +// offset: Vec2, +// scale: f32, +// clip_rect: Rect, +// id_ports: &[(syncrim::common::Id, Ports)], +// grid: &GridOptions, +// editor_mode: EditorMode, +// ) -> EditorRenderReturn { +// let r_vec = InstrMem::render( +// self, +// ui, +// context, +// simulator, +// offset, +// scale, +// clip_rect, +// editor_mode, +// ) +// .unwrap(); +// let resp = &r_vec[0]; +// let delete = drag_logic( +// ui.ctx(), +// resp, +// &mut self.pos, +// &mut context.pos_tmp, +// scale, +// offset, +// grid, +// ); - properties_window( - ui, - self.id.clone(), - resp, - &mut context.properties_window, - |ui| { - let mut clicked_dropdown = false; - input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_drag_value(ui, &mut self.pos); - clicked_dropdown |= input_selector( - ui, - &mut self.pc, - crate::components::INSTR_MEM_PC_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown - }, - ); +// properties_window( +// ui, +// self.id.clone(), +// resp, +// &mut context.properties_window, +// |ui| { +// let mut clicked_dropdown = false; +// input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); +// pos_drag_value(ui, &mut self.pos); +// clicked_dropdown |= input_selector( +// ui, +// &mut self.pc, +// crate::components::INSTR_MEM_PC_ID.to_string(), +// id_ports, +// self.id.clone(), +// ); +// clicked_dropdown +// }, +// ); - EditorRenderReturn { - delete, - resp: Some(r_vec), - } - } +// EditorRenderReturn { +// delete, +// resp: Some(r_vec), +// } +// } - fn ports_location(&self) -> Vec<(syncrim::common::Id, Pos2)> { - let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![ - ( - crate::components::INSTR_MEM_PC_ID.to_string(), - Pos2::new( - self.width / 10f32 * 1f32 - self.width / 2f32, - -self.height / 2f32, - ) + own_pos, - ), - ( - crate::components::INSTR_MEM_INSTRUCTION_ID.to_string(), - Pos2::new( - -self.width / 10f32 * 2f32 + self.width / 2f32, - -self.height / 2f32, - ) + own_pos, - ), - ] - } +// fn ports_location(&self) -> Vec<(syncrim::common::Id, Pos2)> { +// let own_pos = Vec2::new(self.pos.0, self.pos.1); +// vec![ +// ( +// crate::components::INSTR_MEM_PC_ID.to_string(), +// Pos2::new( +// self.width / 10f32 * 1f32 - self.width / 2f32, +// -self.height / 2f32, +// ) + own_pos, +// ), +// ( +// crate::components::INSTR_MEM_INSTRUCTION_ID.to_string(), +// Pos2::new( +// -self.width / 10f32 * 2f32 + self.width / 2f32, +// -self.height / 2f32, +// ) + own_pos, +// ), +// ] +// } - fn top_padding(&self) -> f32 { - self.height / 4f32 - } +// fn top_padding(&self) -> f32 { +// self.height / 4f32 +// } - fn set_pos(&mut self, pos: (f32, f32)) { - self.pos = pos; - } +// fn set_pos(&mut self, pos: (f32, f32)) { +// self.pos = pos; +// } - fn get_pos(&self) -> (f32, f32) { - self.pos - } -} +// fn get_pos(&self) -> (f32, f32) { +// self.pos +// } +// } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 4ff80d12..e6641f62 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -143,21 +143,21 @@ impl Default for Library { pos: (0.0, 0.0), a_in: dummy_input.clone(), }), - Rc::new(InstrMem { - width: INSTR_MEM_WIDTH, - height: INSTR_MEM_HEIGHT, - id: "instruction".to_string(), - pos: (0.0, 0.0), - bytes: BTreeMap::new(), - pc: dummy_input, - range: Range { - start: 0, - end: 0x1000, - }, - breakpoints: Rc::new(RefCell::new(HashSet::new())), - symbols: HashMap::new(), - le: true, - }), + // Rc::new(InstrMem { + // width: INSTR_MEM_WIDTH, + // height: INSTR_MEM_HEIGHT, + // id: "instruction".to_string(), + // pos: (0.0, 0.0), + // bytes: BTreeMap::new(), + // pc: dummy_input, + // range: Range { + // start: 0, + // end: 0x1000, + // }, + // breakpoints: Rc::new(RefCell::new(HashSet::new())), + // symbols: HashMap::new(), + // le: true, + // }), Rc::new( (FullAdd { id: "dummy".to_string(), From 45aa6270e0bafc7da440f3a2ef5b96c098088fdf Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Fri, 26 Jul 2024 15:21:56 +0200 Subject: [PATCH 016/126] 0 progress --- src/gui_egui/components/mips_im.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui_egui/components/mips_im.rs b/src/gui_egui/components/mips_im.rs index c6d48937..23a5b5a3 100644 --- a/src/gui_egui/components/mips_im.rs +++ b/src/gui_egui/components/mips_im.rs @@ -7,6 +7,7 @@ // use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; // use crate::gui_egui::gui::EguiExtra; // use crate::gui_egui::helper::offset_helper; +// use egui::Window; // use egui::{ // Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Slider, Stroke, // TextWrapMode, Ui, Vec2, From e19362213130d7bec6e180021cb83ab7c3ddba44 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Fri, 26 Jul 2024 15:24:05 +0200 Subject: [PATCH 017/126] started work on reg file, missing how to carry over state --- src/components/mips_reg_file.rs | 166 ++++++++++++++++++ src/components/mod.rs | 2 + src/gui_egui/components/mips_reg_file.rs | 205 +++++++++++++++++++++++ src/gui_egui/components/mod.rs | 1 + 4 files changed, 374 insertions(+) create mode 100644 src/components/mips_reg_file.rs create mode 100644 src/gui_egui/components/mips_reg_file.rs diff --git a/src/components/mips_reg_file.rs b/src/components/mips_reg_file.rs new file mode 100644 index 00000000..81443c51 --- /dev/null +++ b/src/components/mips_reg_file.rs @@ -0,0 +1,166 @@ +// use std::fmt::Alignment; +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, + SignalValue, Simulator, +}; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::rc::Rc; + +use super::register; + +pub const REG_FILE_A1_IN_ID: &str = "reg_file_a1_in"; +pub const REG_FILE_A2_IN_ID: &str = "reg_file_a2_in"; +pub const REG_FILE_A3_IN_ID: &str = "reg_file_a3_in"; +pub const REG_FILE_WD3_IN_ID: &str = "reg_file_wd3_in"; +pub const REG_FILE_WE3_IN_ID: &str = "reg_file_we3_in"; + +pub const REG_FILE_RD1_OUT_ID: &str = "rd1_out"; +pub const REG_FILE_RD2_OUT_ID: &str = "rd2_out"; + +#[derive(Serialize, Deserialize, Clone)] +pub struct RegFile { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) a1_in: Input, + pub(crate) a2_in: Input, + pub(crate) a3_in: Input, + pub(crate) wd3_in: Input, + pub(crate) we3_in: Input, + registers: Vec, +} + +#[typetag::serde] +impl Component for RegFile { + fn to_(&self) { + trace!("full_adder"); + } + #[cfg(feature = "gui-egui")] + fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + let dummy_input = Input::new("dummy", "out"); + Box::new(Rc::new(RegFile { + id: "dummy".to_string(), + pos: (0.0, 0.0), + a1_in: dummy_input.clone(), + a2_in: dummy_input.clone(), + a3_in: dummy_input.clone(), + wd3_in: dummy_input.clone(), + we3_in: dummy_input.clone(), + registers: vec![0; 32], + })) + } + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![ + &InputPort { + port_id: REG_FILE_A1_IN_ID.to_string(), + input: self.a1_in.clone(), + }, + &InputPort { + port_id: REG_FILE_A2_IN_ID.to_string(), + input: self.a2_in.clone(), + }, + &InputPort { + port_id: REG_FILE_A3_IN_ID.to_string(), + input: self.a3_in.clone(), + }, + &InputPort { + port_id: REG_FILE_WD3_IN_ID.to_string(), + input: self.wd3_in.clone(), + }, + &InputPort { + port_id: REG_FILE_WE3_IN_ID.to_string(), + input: self.we3_in.clone(), + }, + ], + OutputType::Combinatorial, + vec![REG_FILE_RD1_OUT_ID, REG_FILE_RD2_OUT_ID], + ), + ) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + REG_FILE_A1_IN_ID => self.a1_in = new_input, + REG_FILE_A2_IN_ID => self.a2_in = new_input, + REG_FILE_A3_IN_ID => self.a3_in = new_input, + REG_FILE_WD3_IN_ID => self.wd3_in = new_input, + REG_FILE_WE3_IN_ID => self.we3_in = new_input, + _ => {} + } + } + + // propagate sign extension to output + // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get input values + let a1: u32 = simulator.get_input_value(&self.a1_in).try_into().unwrap(); + let a2: u32 = simulator.get_input_value(&self.a2_in).try_into().unwrap(); + let a3: u32 = simulator.get_input_value(&self.a3_in).try_into().unwrap(); + let wd3: u32 = simulator.get_input_value(&self.wd3_in).try_into().unwrap(); + let we3: u32 = simulator.get_input_value(&self.we3_in).try_into().unwrap(); + let registers: Vec = &mut simulator.get_input_value(&self.registers); + + if we3 == 1 { + registers.get_mut(a3 as usize).unwrap() = wd3; + } + + let a1_out = a1 >> 21; + let a2_out = a2 >> 16; + + simulator.set_out_value( + &self.id, + REG_FILE_RD1_OUT_ID, + SignalValue::Data(self.registers[a1_out as usize]), + ); + simulator.set_out_value( + &self.id, + REG_FILE_RD2_OUT_ID, + SignalValue::Data(self.registers[a2_out as usize]), + ); + Ok(()) + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl RegFile { + pub fn new( + id: &str, + pos: (f32, f32), + a1_in: Input, + a2_in: Input, + a3_in: Input, + wd3_in: Input, + we3_in: Input, + ) -> Self { + RegFile { + id: id.to_string(), + pos, + a1_in, + a2_in, + a3_in, + wd3_in, + we3_in, + } + } + + pub fn rc_new( + id: &str, + pos: (f32, f32), + a1_in: Input, + a2_in: Input, + a3_in: Input, + wd3_in: Input, + we3_in: Input, + ) -> Rc { + Rc::new(RegFile::new(id, pos, a1_in, a2_in, a3_in, wd3_in, we3_in)) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index 86604272..8a161fae 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -6,6 +6,7 @@ mod full_adder; mod mem; mod mips_controll_unit; mod mips_im; +mod mips_reg_file; mod mux; mod probe; mod probe_assert; @@ -24,6 +25,7 @@ pub use full_adder::*; pub use mem::*; pub use mips_controll_unit::*; pub use mips_im::*; +pub use mips_reg_file::*; pub use mux::*; pub use probe::*; pub use probe_assert::*; diff --git a/src/gui_egui/components/mips_reg_file.rs b/src/gui_egui/components/mips_reg_file.rs new file mode 100644 index 00000000..8387fb28 --- /dev/null +++ b/src/gui_egui/components/mips_reg_file.rs @@ -0,0 +1,205 @@ +use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::components::RegFile; +use crate::gui_egui::component_ui::{ + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::offset_helper; +use egui::{ + Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Slider, Stroke, + TextWrapMode, Ui, Vec2, +}; + +#[typetag::serde] +impl EguiComponent for RegFile { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + // 41x81 + // middle: 21x 41y (0 0) + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + // The shape + ui.painter().add(Shape::closed_line( + vec![ + oh((-20f32, -40f32), s, o), + oh((0f32, -40f32), s, o), + oh((20f32, -20f32), s, o), + oh((20f32, 20f32), s, o), + oh((0f32, 40f32), s, o), + oh((-20f32, 40f32), s, o), + oh((-20f32, 20f32), s, o), + oh((-10f32, 0f32), s, o), + oh((-20f32, -20f32), s, o), + ], + Stroke { + width: scale, + color: Color32::BLACK, + }, + )); + + let rect = Rect { + min: oh((-20f32, -40f32), s, o), + max: oh((20f32, 40f32), s, o), + }; + let op: String = if let Some(s) = simulator { + match TryInto::::try_into(s.get_input_value(&self.op_in)).unwrap() { + 0 => "ADD", + 1 => "ADDU", + 2 => "SUB", + 3 => "SUBU", + 4 => "AND", + 5 => "OR", + 6 => "XOR", + 7 => "NOR", + 8 => "DONOTHING", + 10 => "SLT", + 11 => "SLTU", + 12 => "SLL", + 13 => "SRL", + 14 => "SRA", + 15 => "LUI", + _ => "UNDEF", + } + .to_string() + } else { + "no sim".to_string() + }; + + let area = Area::new(egui::Id::from(self.id.to_string())) + .order(Order::Middle) + .current_pos(offset.to_pos2() + Vec2::new(5.0, 0.0) * scale) + .movable(false) + .enabled(true) + .interactable(false) + .pivot(Align2::CENTER_CENTER) + .constrain(false) + .show(ui.ctx(), |ui| { + ui.set_clip_rect(clip_rect); + ui.style_mut().wrap_mode = Some(TextWrapMode::Extend); + ui.label(RichText::new(format!("ALU\n{}", op)).size(scale * 12f32)) + }); + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + ui.label("Adder"); + }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let r_vec = RegFile::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_drag_value(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.a_in, + crate::components::FULL_ADD_A_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.b_in, + crate::components::FULL_ADD_B_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.op_in, + crate::components::FULL_ADD_OP_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown + }, + ); + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + crate::components::SEXT_IN_ID.to_string(), + Pos2::new(-40f32, 0f32) + own_pos, + ), + ( + crate::components::SEXT_OUT_ID.to_string(), + Pos2::new(40f32, 0f32) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + 20f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } +} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index 8f0ccfb6..b2a92752 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -6,6 +6,7 @@ mod full_adder; mod mem; mod mips_controll_unit; mod mips_im; +mod mips_reg_file; mod mux; mod probe; mod probe_assert; From 37d651eec5069e656b61b547b7a039aaf53df860 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 10 Jul 2024 14:49:07 +0200 Subject: [PATCH 018/126] added more ui stuff --- src/gui_egui/components/full_adder.rs | 51 +++++++++------------------ src/gui_egui/menu.rs | 4 +-- 2 files changed, 19 insertions(+), 36 deletions(-) diff --git a/src/gui_egui/components/full_adder.rs b/src/gui_egui/components/full_adder.rs index 3200200b..bcf132d7 100644 --- a/src/gui_egui/components/full_adder.rs +++ b/src/gui_egui/components/full_adder.rs @@ -7,7 +7,10 @@ use crate::gui_egui::component_ui::{ use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; -use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; +use egui::{ + Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Slider, Stroke, + TextWrapMode, Ui, Vec2, +}; #[typetag::serde] impl EguiComponent for FullAdd { @@ -21,8 +24,8 @@ impl EguiComponent for FullAdd { clip_rect: Rect, editor_mode: EditorMode, ) -> Option> { - // 81x41 - // middle: 41x 21y (0 0) + // 41x81 + // middle: 21x 41y (0 0) let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; let offset_old = offset; let mut offset = offset; @@ -33,14 +36,19 @@ impl EguiComponent for FullAdd { // The shape ui.painter().add(Shape::closed_line( vec![ - oh((-40f32, 0f32), s, o), - oh((40f32, 0f32), s, o), - oh((40f32, 20f32), s, o), - oh((-40f32, 20f32), s, o), + oh((-20f32, -40f32), s, o), + oh((0f32, -40f32), s, o), + oh((20f32, -20f32), s, o), + oh((20f32, 20f32), s, o), + oh((0f32, 40f32), s, o), + oh((-20f32, 40f32), s, o), + oh((-20f32, 20f32), s, o), + oh((-10f32, 0f32), s, o), + oh((-20f32, -20f32), s, o), ], Stroke { width: scale, - color: Color32::RED, + color: Color32::BLACK, }, )); @@ -86,32 +94,7 @@ impl EguiComponent for FullAdd { }); let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { ui.label(format!("Id: {}", self.id.clone())); - // todo: is this actually correct? - if let Some(s) = &simulator { - ui.label({ - let a_r: Result = - s.get_input_value(&self.a_in).try_into(); - let b_r: Result = - s.get_input_value(&self.b_in).try_into(); - let op_r: Result = - s.get_input_value(&self.op_in).try_into(); - let mut s: String = "".to_string(); - match a_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", a_r), - } - match b_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", b_r), - } - match op_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", op_r), - } - format!("{}", s) - }); - ui.label("full_adder"); - } + ui.label("Adder"); }); match editor_mode { EditorMode::Simulator => (), diff --git a/src/gui_egui/menu.rs b/src/gui_egui/menu.rs index 4ffa741b..f32e75f2 100644 --- a/src/gui_egui/menu.rs +++ b/src/gui_egui/menu.rs @@ -1,10 +1,10 @@ +use crate::common::RunningState; use crate::gui_egui::{ editor::{Editor, GridOptions}, gui::Gui, keymap, }; -use egui::{menu, Button, DragValue, KeyboardShortcut, Response, Ui}; - +use egui::{menu, Button, Color32, DragValue, KeyboardShortcut, Response, RichText, Ui}; pub(crate) struct Menu {} impl Menu { From b97d7ee876c9c3a4f4f5673a7565659ad89ca9ae Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Tue, 30 Jul 2024 10:09:35 +0200 Subject: [PATCH 019/126] added testing reg_file and template for im --- examples/mips_reg_file.rs | 137 +++++++++++ src/components/mips_reg_file.rs | 295 ++++++++++++++++++++--- src/gui_egui/components/mips_reg_file.rs | 132 +++++----- src/gui_egui/menu.rs | 1 - 4 files changed, 468 insertions(+), 97 deletions(-) create mode 100644 examples/mips_reg_file.rs diff --git a/examples/mips_reg_file.rs b/examples/mips_reg_file.rs new file mode 100644 index 00000000..a8ba9954 --- /dev/null +++ b/examples/mips_reg_file.rs @@ -0,0 +1,137 @@ +use std::path::PathBuf; +use std::rc::Rc; +use syncrim::common::EguiComponent; +#[cfg(feature = "gui-egui")] +use syncrim::gui_egui::editor::Library; +use syncrim::{ + common::{ComponentStore, Input}, + components::*, + fern::fern_setup, +}; + +fn main() { + fern_setup(); + let cs = ComponentStore { + store: vec![ + RegFile::rc_new( + "reg_file", + (200.0, 200.0), + Input::new("c0", "out"), + Input::new("c1", "out"), + Input::new("c2", "out"), + Input::new("c3", "out"), + Input::new("c4", "out"), + true, + ), + ProbeEdit::rc_new("c0", (60.0, 100.0)), + ProbeEdit::rc_new("c1", (60.0, 140.0)), + ProbeEdit::rc_new("c2", (60.0, 160.0)), + ProbeEdit::rc_new("c3", (60.0, 200.0)), + ProbeEdit::rc_new("c4", (60.0, 240.0)), + Probe::rc_new( + "p1", + (270.0, 120.0), + Input::new("reg_file", REG_FILE_RD1_OUT_ID), + ), + Probe::rc_new( + "p2", + (270.0, 160.0), + Input::new("reg_file", REG_FILE_RD2_OUT_ID), + ), + ], + }; + + let cs = autowire(cs); + + let path = PathBuf::from("add.json"); + cs.save_file(&path); + + #[cfg(feature = "gui-egui")] + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + + #[cfg(feature = "gui-vizia")] + syncrim::gui_vizia::gui(cs, &path); +} + +fn autowire(mut cs: ComponentStore) -> ComponentStore { + let mut x = 1; + let mut tmp_vec: Vec> = vec![]; + + for c in &cs.store { + let (id, ports) = c.get_id_ports(); + println!("{}", id); + + let number_of_inputs = ports.inputs.len(); + + for n in 0..number_of_inputs { + println!("{:?}", ports.inputs[n].input.id); + println!("{:?}", ports); + + let id_tmp = format!("{id}_w{n}"); + //let pos_temp = vec![]; + let input = ports.inputs[n].input.clone(); + + let starting_pos = c.get_pos(); + + let mut destination_pos = (starting_pos.0 - 50.0, starting_pos.1); + + let default_input = Input::new(&format!("c{n}"), "out"); + let mut w = Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], default_input); + + for d in &cs.store { + let (id2, ports2) = d.get_id_ports(); + let input = Input::new(&id2, "out"); + if id2 == ports.inputs[n].input.id { + destination_pos = d.get_pos(); + w = Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], input.clone()); + } + } + tmp_vec.push(w); + + //TODO: get pos and set to destination, look through list of components a second time, then add that as starting pos. + + //println!("{}", id_tmp); + //let w = Wire::rc_new("w{}", pos, input) + } + + //cs_copy.store.push("wow"); + + // Wire::rc_new( + // "w4", + // vec![(220.0, 120.0), (260.0, 120.0)], + // Input::new("full_adder", FULL_ADD_OUT_ID), + // ), + + // Ports { + // inputs: [ + // InputPort { + // port_id: "full_add_a_in", + // input: Input { + // id: "c1", + // field: "out", + // }, + // }, + // InputPort { + // port_id: "full_add_b_in", + // input: Input { + // id: "c2", + // field: "out", + // }, + // }, + // InputPort { + // port_id: "full_add_op_in", + // input: Input { + // id: "c3", + // field: "out", + // }, + // }, + // ], + + // out_type: Combinatorial, + // outputs: ["out"], + // } + } + cs.store.append(&mut tmp_vec); + + return cs; +} diff --git a/src/components/mips_reg_file.rs b/src/components/mips_reg_file.rs index 81443c51..859c1080 100644 --- a/src/components/mips_reg_file.rs +++ b/src/components/mips_reg_file.rs @@ -8,10 +8,11 @@ use crate::common::{ use log::*; use serde::{Deserialize, Serialize}; use std::any::Any; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::ops::Deref; use std::rc::Rc; -use super::register; - pub const REG_FILE_A1_IN_ID: &str = "reg_file_a1_in"; pub const REG_FILE_A2_IN_ID: &str = "reg_file_a2_in"; pub const REG_FILE_A3_IN_ID: &str = "reg_file_a3_in"; @@ -30,28 +31,184 @@ pub struct RegFile { pub(crate) a3_in: Input, pub(crate) wd3_in: Input, pub(crate) we3_in: Input, - registers: Vec, + + pub big_endian: bool, + + #[serde(skip)] + pub memory: Memory, + history: RefCell>, + #[serde(skip)] + pub init_state: BTreeMap, +} + +#[derive(Serialize, Deserialize, Clone)] +struct MemOp { + pub data: Option, + pub addr: usize, + pub size: u8, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Memory(pub Rc>>); + +impl Default for Memory { + fn default() -> Self { + Self::new(BTreeMap::new()) + } +} + +impl Memory { + pub fn new(data: BTreeMap) -> Self { + Memory(Rc::new(RefCell::new(data))) + } + + fn align(&self, addr: usize, size: usize) -> SignalValue { + ((addr % size != 0) as SignalUnsigned).into() + } + + pub fn read(&self, addr: usize, size: usize, sign: bool, big_endian: bool) -> SignalValue { + let data: Vec = (0..size) + .map(|i| *self.0.borrow().get(&(addr + i)).unwrap_or(&0)) + .collect(); + + let data = data.as_slice(); + + //trace!("{:x?}", data); + + match size { + 1 => { + if sign { + data[0] as i8 as SignalSigned as SignalUnsigned + } else { + data[0] as SignalUnsigned + } + } + 2 => { + if sign { + if big_endian { + trace!("read signed half word be"); + let i_16 = i16::from_be_bytes(data.try_into().unwrap()); + trace!("i_16 {:x?}", i_16); + let i_32 = i_16 as i32; + trace!("i_32 {:x?}", i_32); + i_32 as SignalUnsigned + } else { + trace!("read signed half word le"); + let i_16 = i16::from_le_bytes(data.try_into().unwrap()); + trace!("i_16 {:x?}", i_16); + let i_32 = i_16 as i32; + trace!("i_32 {:x?}", i_32); + i_32 as SignalUnsigned + } + } else if big_endian { + trace!("read unsigned half word be"); + let u_16 = u16::from_be_bytes(data.try_into().unwrap()); + trace!("u_16 {:x?}", u_16); + let u_32 = u_16 as u32; + trace!("u_32 {:x?}", u_32); + u_32 as SignalUnsigned + } else { + trace!("read unsigned half word le"); + let u_16 = u16::from_le_bytes(data.try_into().unwrap()); + trace!("u_16 {:x?}", u_16); + let u_32 = u_16 as u32; + trace!("u_32 {:x?}", u_32); + u_32 as SignalUnsigned + } + } + 4 => { + if sign { + if big_endian { + i32::from_be_bytes(data.try_into().unwrap()) as SignalUnsigned + } else { + i32::from_le_bytes(data.try_into().unwrap()) as SignalUnsigned + } + } else if big_endian { + u32::from_be_bytes(data.try_into().unwrap()) as SignalUnsigned + } else { + u32::from_le_bytes(data.try_into().unwrap()) as SignalUnsigned + } + } + _ => panic!("illegal sized memory operation"), + } + .into() + } + + pub fn write(&self, addr: usize, size: usize, big_endian: bool, data: SignalValue) { + let data: SignalUnsigned = data.try_into().unwrap(); + trace!("we = 1, now writing {:?} at addr {:?}", data, addr); + + match size { + 1 => { + trace!("write byte"); + self.0.borrow_mut().insert(addr, data as u8); + } + 2 => { + if big_endian { + trace!("write half word be"); + (data as u16) + .to_be_bytes() + .iter() + .enumerate() + .for_each(|(i, bytes)| { + self.0.borrow_mut().insert(addr + i, *bytes); + }) + } else { + trace!("write half word le"); + (data as u16) + .to_le_bytes() + .iter() + .enumerate() + .for_each(|(i, bytes)| { + self.0.borrow_mut().insert(addr + i, *bytes); + }) + } + } + + 4 => { + if big_endian { + trace!("write word be"); + data.to_be_bytes() + .iter() + .enumerate() + .for_each(|(i, bytes)| { + self.0.borrow_mut().insert(addr + i, *bytes); + }) + } else { + trace!("write word le"); + data.to_le_bytes() + .iter() + .enumerate() + .for_each(|(i, bytes)| { + self.0.borrow_mut().insert(addr + i, *bytes); + }) + } + } + _ => { + panic!("illegal sized memory operation, size = {}", size) + } + }; + } } #[typetag::serde] impl Component for RegFile { fn to_(&self) { - trace!("full_adder"); + trace!("reg_file"); } #[cfg(feature = "gui-egui")] - fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { - let dummy_input = Input::new("dummy", "out"); - Box::new(Rc::new(RegFile { - id: "dummy".to_string(), - pos: (0.0, 0.0), - a1_in: dummy_input.clone(), - a2_in: dummy_input.clone(), - a3_in: dummy_input.clone(), - wd3_in: dummy_input.clone(), - we3_in: dummy_input.clone(), - registers: vec![0; 32], - })) - } + // fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + // let dummy_input = Input::new("dummy", "out"); + // Box::new(Rc::new(RegFile { + // id: "dummy".to_string(), + // pos: (0.0, 0.0), + // a1_in: dummy_input.clone(), + // a2_in: dummy_input.clone(), + // a3_in: dummy_input.clone(), + // wd3_in: dummy_input.clone(), + // we3_in: dummy_input.clone(), + // })) + // } fn get_id_ports(&self) -> (Id, Ports) { ( self.id.clone(), @@ -99,30 +256,78 @@ impl Component for RegFile { // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { // get input values + let mut history_entry = MemOp { + data: None, + addr: 0, + size: 0, + }; + let a1: u32 = simulator.get_input_value(&self.a1_in).try_into().unwrap(); let a2: u32 = simulator.get_input_value(&self.a2_in).try_into().unwrap(); let a3: u32 = simulator.get_input_value(&self.a3_in).try_into().unwrap(); - let wd3: u32 = simulator.get_input_value(&self.wd3_in).try_into().unwrap(); + let wd3: SignalValue = simulator.get_input_value(&self.wd3_in); let we3: u32 = simulator.get_input_value(&self.we3_in).try_into().unwrap(); - let registers: Vec = &mut simulator.get_input_value(&self.registers); + let size = 4; + let sign: bool = false; // in the mips, always read as unsigned + + // let a1_addr = a1 >> 21; + // let a2_addr = a2 >> 16; + let a1_addr = a1; + let a2_addr = a2; + let a3_addr = a3; // the shifting is handled in the mux + + // since the addr is only 5 bits, it cant be out of bounds, 2^5 = 32 + + // read RD1 and RD2 + trace!("read addr {:?} size {:?}", a1_addr, size); + let value1 = self + .memory + .read(a1_addr as usize, size as usize, sign, self.big_endian) + .try_into() + .unwrap(); + + trace!("read addr {:?} size {:?}", a2_addr, size); + let value2 = self + .memory + .read(a2_addr as usize, size as usize, sign, self.big_endian) + .try_into() + .unwrap(); + + // if we, write to reg if we3 == 1 { - registers.get_mut(a3 as usize).unwrap() = wd3; + let size = 4; + history_entry = MemOp { + data: match self.memory.read( + a3_addr as usize, + size as usize, + false, + self.big_endian, + ) { + SignalValue::Data(d) => Some(d as usize), + _ => None, + }, + + addr: a3_addr as usize, + size: size as u8, + }; + trace!("write addr {:?} size {:?}", a3_addr, size); + + if a3_addr != 0 { + self.memory + .write(a3_addr as usize, size as usize, self.big_endian, wd3); + } else { + // does nothing and reg remains 0 + } + + let value = self.memory.align(a3_addr as usize, size as usize); + trace!("align {:?}", value); } - let a1_out = a1 >> 21; - let a2_out = a2 >> 16; - - simulator.set_out_value( - &self.id, - REG_FILE_RD1_OUT_ID, - SignalValue::Data(self.registers[a1_out as usize]), - ); - simulator.set_out_value( - &self.id, - REG_FILE_RD2_OUT_ID, - SignalValue::Data(self.registers[a2_out as usize]), - ); + simulator.set_out_value(&self.id, REG_FILE_RD1_OUT_ID, SignalValue::Data(value1)); + simulator.set_out_value(&self.id, REG_FILE_RD2_OUT_ID, SignalValue::Data(value2)); + + self.history.borrow_mut().push(history_entry); Ok(()) } @@ -131,6 +336,14 @@ impl Component for RegFile { } } +impl Deref for Memory { + type Target = RefCell>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl RegFile { pub fn new( id: &str, @@ -140,6 +353,8 @@ impl RegFile { a3_in: Input, wd3_in: Input, we3_in: Input, + big_endian: bool, + memory: BTreeMap, ) -> Self { RegFile { id: id.to_string(), @@ -149,6 +364,10 @@ impl RegFile { a3_in, wd3_in, we3_in, + big_endian, + memory: Memory::new(memory.clone()), + history: RefCell::new(vec![]), + init_state: memory.clone(), } } @@ -160,7 +379,15 @@ impl RegFile { a3_in: Input, wd3_in: Input, we3_in: Input, + big_endian: bool, ) -> Rc { - Rc::new(RegFile::new(id, pos, a1_in, a2_in, a3_in, wd3_in, we3_in)) + let mut mem = BTreeMap::new(); + //fill the defined memory range with zeroes + for i in 0..32.clone() { + mem.insert(i as usize, 0u8); + } + Rc::new(RegFile::new( + id, pos, a1_in, a2_in, a3_in, wd3_in, we3_in, big_endian, mem, + )) } } diff --git a/src/gui_egui/components/mips_reg_file.rs b/src/gui_egui/components/mips_reg_file.rs index 8387fb28..b7089b43 100644 --- a/src/gui_egui/components/mips_reg_file.rs +++ b/src/gui_egui/components/mips_reg_file.rs @@ -7,10 +7,7 @@ use crate::gui_egui::component_ui::{ use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; -use egui::{ - Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Slider, Stroke, - TextWrapMode, Ui, Vec2, -}; +use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for RegFile { @@ -24,8 +21,8 @@ impl EguiComponent for RegFile { clip_rect: Rect, editor_mode: EditorMode, ) -> Option> { - // 41x81 - // middle: 21x 41y (0 0) + // 81x41 + // middle: 41x 21y (0 0) let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; let offset_old = offset; let mut offset = offset; @@ -36,66 +33,63 @@ impl EguiComponent for RegFile { // The shape ui.painter().add(Shape::closed_line( vec![ - oh((-20f32, -40f32), s, o), - oh((0f32, -40f32), s, o), - oh((20f32, -20f32), s, o), - oh((20f32, 20f32), s, o), - oh((0f32, 40f32), s, o), - oh((-20f32, 40f32), s, o), - oh((-20f32, 20f32), s, o), - oh((-10f32, 0f32), s, o), - oh((-20f32, -20f32), s, o), + oh((-40f32, 0f32), s, o), + oh((40f32, 0f32), s, o), + oh((40f32, 20f32), s, o), + oh((-40f32, 20f32), s, o), ], Stroke { width: scale, - color: Color32::BLACK, + color: Color32::RED, }, )); let rect = Rect { - min: oh((-20f32, -40f32), s, o), - max: oh((20f32, 40f32), s, o), - }; - let op: String = if let Some(s) = simulator { - match TryInto::::try_into(s.get_input_value(&self.op_in)).unwrap() { - 0 => "ADD", - 1 => "ADDU", - 2 => "SUB", - 3 => "SUBU", - 4 => "AND", - 5 => "OR", - 6 => "XOR", - 7 => "NOR", - 8 => "DONOTHING", - 10 => "SLT", - 11 => "SLTU", - 12 => "SLL", - 13 => "SRL", - 14 => "SRA", - 15 => "LUI", - _ => "UNDEF", - } - .to_string() - } else { - "no sim".to_string() + min: oh((-40f32, -20f32), s, o), + max: oh((40f32, 20f32), s, o), }; - - let area = Area::new(egui::Id::from(self.id.to_string())) - .order(Order::Middle) - .current_pos(offset.to_pos2() + Vec2::new(5.0, 0.0) * scale) - .movable(false) - .enabled(true) - .interactable(false) - .pivot(Align2::CENTER_CENTER) - .constrain(false) - .show(ui.ctx(), |ui| { - ui.set_clip_rect(clip_rect); - ui.style_mut().wrap_mode = Some(TextWrapMode::Extend); - ui.label(RichText::new(format!("ALU\n{}", op)).size(scale * 12f32)) - }); let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { ui.label(format!("Id: {}", self.id.clone())); - ui.label("Adder"); + // todo: is this actually correct? + if let Some(s) = &simulator { + ui.label({ + let a1_r: Result = + s.get_input_value(&self.a1_in).try_into(); + let a2_r: Result = + s.get_input_value(&self.a2_in).try_into(); + let a3_r: Result = + s.get_input_value(&self.a3_in).try_into(); + let wd3_r: Result = + s.get_input_value(&self.wd3_in).try_into(); + let we3_r: Result = + s.get_input_value(&self.we3_in).try_into(); + + let mut s: String = "".to_string(); + + match a1_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", a1_r), + } + match a2_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", a2_r), + } + match a3_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", a3_r), + } + match wd3_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", wd3_r), + } + match we3_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", we3_r), + } + format!("{}", s) + }); + ui.label("reg_file"); + } }); match editor_mode { EditorMode::Simulator => (), @@ -149,22 +143,36 @@ impl EguiComponent for RegFile { pos_drag_value(ui, &mut self.pos); clicked_dropdown |= input_selector( ui, - &mut self.a_in, - crate::components::FULL_ADD_A_IN_ID.to_string(), + &mut self.a1_in, + crate::components::REG_FILE_A1_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.a2_in, + crate::components::REG_FILE_A2_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.a3_in, + crate::components::REG_FILE_A3_IN_ID.to_string(), id_ports, self.id.clone(), ); clicked_dropdown |= input_selector( ui, - &mut self.b_in, - crate::components::FULL_ADD_B_IN_ID.to_string(), + &mut self.wd3_in, + crate::components::REG_FILE_WD3_IN_ID.to_string(), id_ports, self.id.clone(), ); clicked_dropdown |= input_selector( ui, - &mut self.op_in, - crate::components::FULL_ADD_OP_IN_ID.to_string(), + &mut self.we3_in, + crate::components::REG_FILE_WE3_IN_ID.to_string(), id_ports, self.id.clone(), ); diff --git a/src/gui_egui/menu.rs b/src/gui_egui/menu.rs index f32e75f2..ed722dc9 100644 --- a/src/gui_egui/menu.rs +++ b/src/gui_egui/menu.rs @@ -1,4 +1,3 @@ -use crate::common::RunningState; use crate::gui_egui::{ editor::{Editor, GridOptions}, gui::Gui, From 071287cd9cbcecd9981b435255bda5b01188c2a6 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:36:00 +0200 Subject: [PATCH 020/126] added code to help test persisting error related missing field out --- src/simulator.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/simulator.rs b/src/simulator.rs index 0312d61b..e7da119e 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -182,6 +182,10 @@ impl Simulator { .id_field_index .get(&(input.id.clone(), input.field.clone())) .unwrap_or_else(|| { + error!( + "Component {:?}, field {:?} not found.", + input.id, input.field + ); panic!( "Component {:?}, field {:?} not found.", input.id, input.field From e7921bab0d14d58b5038172f6acc94e7aecd01dc Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:16:32 +0200 Subject: [PATCH 021/126] added component signal splitter --- examples/mips_instruction_splitter.rs | 120 +++++++++++++ src/components/mips_instruction_splitter.rs | 137 +++++++++++++++ src/components/mod.rs | 2 + .../components/mips_instruction_splitter.rs | 160 ++++++++++++++++++ src/gui_egui/components/mod.rs | 1 + 5 files changed, 420 insertions(+) create mode 100644 examples/mips_instruction_splitter.rs create mode 100644 src/components/mips_instruction_splitter.rs create mode 100644 src/gui_egui/components/mips_instruction_splitter.rs diff --git a/examples/mips_instruction_splitter.rs b/examples/mips_instruction_splitter.rs new file mode 100644 index 00000000..2f9a3146 --- /dev/null +++ b/examples/mips_instruction_splitter.rs @@ -0,0 +1,120 @@ +use std::rc::Rc; +use std::{ + any::{Any, TypeId}, + path::PathBuf, +}; +use syncrim::common::EguiComponent; +#[cfg(feature = "gui-egui")] +use syncrim::gui_egui::editor::Library; +use syncrim::{ + common::{ComponentStore, Input}, + component_store, + components::*, + fern::fern_setup, +}; + +fn main() { + fern_setup(); + let cs = ComponentStore { + store: vec![ + InstrSplit::rc_new( + "instruction_splitter", + (200.0, 120.0), + Input::new("c0", "out"), + ), + ProbeEdit::rc_new("c0", (60.0, 100.0)), + Probe::rc_new( + "op", + (270.0, 120.0), + Input::new("instruction_splitter", INSTRUCTION_SPLITTER_OP_ID), + ), + Probe::rc_new( + "rs", + (270.0, 140.0), + Input::new("instruction_splitter", INSTRUCTION_SPLITTER_RS_ID), + ), + Probe::rc_new( + "rt", + (270.0, 160.0), + Input::new("instruction_splitter", INSTRUCTION_SPLITTER_RT_ID), + ), + Probe::rc_new( + "rd", + (270.0, 180.0), + Input::new("instruction_splitter", INSTRUCTION_SPLITTER_RD_ID), + ), + Probe::rc_new( + "shamt", + (270.0, 200.0), + Input::new("instruction_splitter", INSTRUCTION_SPLITTER_SHAMT_ID), + ), + Probe::rc_new( + "funct", + (270.0, 220.0), + Input::new("instruction_splitter", INSTRUCTION_SPLITTER_FUNCT_ID), + ), + Probe::rc_new( + "immiediate", + (270.0, 240.0), + Input::new("instruction_splitter", INSTRUCTION_SPLITTER_IMMEDIATE_ID), + ), + Probe::rc_new( + "target", + (270.0, 260.0), + Input::new("instruction_splitter", INSTRUCTION_SPLITTER_TARGET_ID), + ), + ], + }; + + let cs = autowire(cs); + + let path = PathBuf::from("add.json"); + cs.save_file(&path); + + #[cfg(feature = "gui-egui")] + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + + #[cfg(feature = "gui-vizia")] + syncrim::gui_vizia::gui(cs, &path); +} + +fn autowire(mut cs: ComponentStore) -> ComponentStore { + let mut tmp_vec: Vec> = vec![]; + + // look through the list of components + for c in &cs.store { + let (id, ports) = c.get_id_ports(); + println!("{}", id); + + let number_of_inputs = ports.inputs.len(); + + for n in 0..number_of_inputs { + // println!("{:?}", ports.inputs[n].input.id); + // println!("{:?}", ports.inputs[n]); + + let id_tmp = format!("{id}_w{n}"); + let input = ports.inputs[n].input.clone(); + let starting_pos = c.get_pos(); + + // creates temporary vales to use when constatnt inputs are there for testing + let mut destination_pos = (starting_pos.0 - 50.0, starting_pos.1); + let default_input = Input::new(&ports.inputs[n].input.id, "out"); + + // look through the list again and act when you find a matching id + for d in &cs.store { + let (id2, ports2) = d.get_id_ports(); + // look if the id matches the one you are looking for + if id2 == ports.inputs[n].input.id { + // collect the components destination and use it to make a complete wire + destination_pos = d.get_pos(); + let w = + Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], input.clone()); + tmp_vec.push(w); + } + } + } + } + cs.store.append(&mut tmp_vec); + + return cs; +} diff --git a/src/components/mips_instruction_splitter.rs b/src/components/mips_instruction_splitter.rs new file mode 100644 index 00000000..03a37397 --- /dev/null +++ b/src/components/mips_instruction_splitter.rs @@ -0,0 +1,137 @@ +// use std::fmt::Alignment; +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, + SignalValue, Simulator, +}; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::rc::Rc; + +pub const INSTRUCTION_SPLITTER_IN_ID: &str = "instruction_in"; + +pub const INSTRUCTION_SPLITTER_OP_ID: &str = "op_out"; +pub const INSTRUCTION_SPLITTER_RS_ID: &str = "rs_out"; +pub const INSTRUCTION_SPLITTER_RT_ID: &str = "rt_out"; +pub const INSTRUCTION_SPLITTER_RD_ID: &str = "rd_out"; +pub const INSTRUCTION_SPLITTER_SHAMT_ID: &str = "shamt_out"; +pub const INSTRUCTION_SPLITTER_FUNCT_ID: &str = "funct_out"; +pub const INSTRUCTION_SPLITTER_IMMEDIATE_ID: &str = "immediate_out"; +pub const INSTRUCTION_SPLITTER_TARGET_ID: &str = "target_out"; + +#[derive(Serialize, Deserialize, Clone)] +pub struct InstrSplit { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) instruction_in: Input, +} + +#[typetag::serde] +impl Component for InstrSplit { + fn to_(&self) { + trace!("pc+4"); + } + #[cfg(feature = "gui-egui")] + fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + let dummy_input = Input::new("dummy", "out"); + Box::new(Rc::new(InstrSplit { + id: "dummy".to_string(), + pos: (0.0, 0.0), + instruction_in: dummy_input.clone(), + })) + } + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![&InputPort { + port_id: INSTRUCTION_SPLITTER_IN_ID.to_string(), + input: self.instruction_in.clone(), + }], + OutputType::Combinatorial, + vec![ + INSTRUCTION_SPLITTER_OP_ID, + INSTRUCTION_SPLITTER_RS_ID, + INSTRUCTION_SPLITTER_RT_ID, + INSTRUCTION_SPLITTER_RD_ID, + INSTRUCTION_SPLITTER_SHAMT_ID, + INSTRUCTION_SPLITTER_FUNCT_ID, + INSTRUCTION_SPLITTER_IMMEDIATE_ID, + INSTRUCTION_SPLITTER_TARGET_ID, + ], + ), + ) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + INSTRUCTION_SPLITTER_IN_ID => self.instruction_in = new_input, + _ => {} + } + } + + // propagate sign extension to output + // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get input values + let instruction: u32 = simulator + .get_input_value(&self.instruction_in) + .try_into() + .unwrap(); + + let op = (instruction >> 26) & 0x0000_003f; + let rs = (instruction >> 21) & 0x0000_001f; + let rt = (instruction >> 16) & 0x0000_001f; + let rd = (instruction >> 11) & 0x0000_001f; + let shamt = (instruction >> 6) & 0x0000_001f; + let funct = instruction & 0x0000_003f; + let immediate = instruction & 0x0000_ffff; + let target = instruction & 0x03ff_ffff; + + simulator.set_out_value(&self.id, INSTRUCTION_SPLITTER_OP_ID, SignalValue::Data(op)); + simulator.set_out_value(&self.id, INSTRUCTION_SPLITTER_RS_ID, SignalValue::Data(rs)); + simulator.set_out_value(&self.id, INSTRUCTION_SPLITTER_RT_ID, SignalValue::Data(rt)); + simulator.set_out_value(&self.id, INSTRUCTION_SPLITTER_RD_ID, SignalValue::Data(rd)); + simulator.set_out_value( + &self.id, + INSTRUCTION_SPLITTER_SHAMT_ID, + SignalValue::Data(shamt), + ); + simulator.set_out_value( + &self.id, + INSTRUCTION_SPLITTER_FUNCT_ID, + SignalValue::Data(funct), + ); + simulator.set_out_value( + &self.id, + INSTRUCTION_SPLITTER_IMMEDIATE_ID, + SignalValue::Data(immediate), + ); + simulator.set_out_value( + &self.id, + INSTRUCTION_SPLITTER_TARGET_ID, + SignalValue::Data(target), + ); + Ok(()) + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl InstrSplit { + pub fn new(id: &str, pos: (f32, f32), instruction_in: Input) -> Self { + InstrSplit { + id: id.to_string(), + pos, + instruction_in, + } + } + + pub fn rc_new(id: &str, pos: (f32, f32), instruction_in: Input) -> Rc { + Rc::new(InstrSplit::new(id, pos, instruction_in)) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index 8a161fae..dd2fa2d0 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -6,6 +6,7 @@ mod full_adder; mod mem; mod mips_controll_unit; mod mips_im; +mod mips_instruction_splitter; mod mips_reg_file; mod mux; mod probe; @@ -25,6 +26,7 @@ pub use full_adder::*; pub use mem::*; pub use mips_controll_unit::*; pub use mips_im::*; +pub use mips_instruction_splitter::*; pub use mips_reg_file::*; pub use mux::*; pub use probe::*; diff --git a/src/gui_egui/components/mips_instruction_splitter.rs b/src/gui_egui/components/mips_instruction_splitter.rs new file mode 100644 index 00000000..cfe834f8 --- /dev/null +++ b/src/gui_egui/components/mips_instruction_splitter.rs @@ -0,0 +1,160 @@ +use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::components::InstrSplit; +use crate::gui_egui::component_ui::{ + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::offset_helper; +use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; + +#[typetag::serde] +impl EguiComponent for InstrSplit { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + // 81x41 + // middle: 41x 21y (0 0) + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + // The shape + ui.painter().add(Shape::closed_line( + vec![ + oh((-40f32, 0f32), s, o), + oh((40f32, 0f32), s, o), + oh((40f32, 20f32), s, o), + oh((-40f32, 20f32), s, o), + ], + Stroke { + width: scale, + color: Color32::RED, + }, + )); + + let rect = Rect { + min: oh((-40f32, -20f32), s, o), + max: oh((40f32, 20f32), s, o), + }; + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + // todo: is this actually correct? + if let Some(s) = &simulator { + ui.label({ + let a_r: Result = + s.get_input_value(&self.instruction_in).try_into(); + let mut s: String = "".to_string(); + + match a_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", a_r), + } + format!("{}", s) + }); + ui.label("InstrSplit"); + } + }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let r_vec = InstrSplit::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_drag_value(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.instruction_in, + crate::components::CLK_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown + }, + ); + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + crate::components::SEXT_IN_ID.to_string(), + Pos2::new(-40f32, 0f32) + own_pos, + ), + ( + crate::components::SEXT_OUT_ID.to_string(), + Pos2::new(40f32, 0f32) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + 20f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } +} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index b2a92752..34ee1797 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -6,6 +6,7 @@ mod full_adder; mod mem; mod mips_controll_unit; mod mips_im; +mod mips_instruction_splitter; mod mips_reg_file; mod mux; mod probe; From fa14e7322ef5ae22131f41220cf168923198a0cb Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Thu, 1 Aug 2024 16:14:53 +0200 Subject: [PATCH 022/126] clarified addresses for interaction with split component --- src/components/mips_reg_file.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/components/mips_reg_file.rs b/src/components/mips_reg_file.rs index 859c1080..ec8313ed 100644 --- a/src/components/mips_reg_file.rs +++ b/src/components/mips_reg_file.rs @@ -271,11 +271,9 @@ impl Component for RegFile { let size = 4; let sign: bool = false; // in the mips, always read as unsigned - // let a1_addr = a1 >> 21; - // let a2_addr = a2 >> 16; - let a1_addr = a1; - let a2_addr = a2; - let a3_addr = a3; // the shifting is handled in the mux + let a1_addr = a1; // rs + let a2_addr = a2; // rt + let a3_addr = a3; // rt or rd depending on mux output, operation type // since the addr is only 5 bits, it cant be out of bounds, 2^5 = 32 From d05861b7800fdf159a83d84525f9d4bcc4aaa1f6 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Thu, 1 Aug 2024 16:43:46 +0200 Subject: [PATCH 023/126] added component to calc jump addr --- src/components/mips_jump_merge.rs | 110 ++++++++++++++++++++++++++++++ src/components/mod.rs | 2 + 2 files changed, 112 insertions(+) create mode 100644 src/components/mips_jump_merge.rs diff --git a/src/components/mips_jump_merge.rs b/src/components/mips_jump_merge.rs new file mode 100644 index 00000000..993ebff6 --- /dev/null +++ b/src/components/mips_jump_merge.rs @@ -0,0 +1,110 @@ +// use std::fmt::Alignment; +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, + SignalValue, Simulator, +}; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::rc::Rc; + +pub const MERGE_INSTR_ADDR_ID: &str = "merge_instr_addr_in"; +pub const MERGE_JUMP_ADDR_ID: &str = "merge_jump_addr_in"; + +pub const MERGE_OUT_ID: &str = "out"; + +#[derive(Serialize, Deserialize, Clone)] +pub struct JumpMerge { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) instr_addr_in: Input, + pub(crate) jump_addr_in: Input, +} + +#[typetag::serde] +impl Component for JumpMerge { + fn to_(&self) { + trace!("merge"); + } + // #[cfg(feature = "gui-egui")] + // fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + // let dummy_input = Input::new("dummy", "out"); + // Box::new(Rc::new(JumpMerge { + // id: "dummy".to_string(), + // pos: (0.0, 0.0), + // clk_in: dummy_input.clone(), + // })) + // } + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![ + &InputPort { + port_id: MERGE_INSTR_ADDR_ID.to_string(), + input: self.instr_addr_in.clone(), + }, + &InputPort { + port_id: MERGE_JUMP_ADDR_ID.to_string(), + input: self.jump_addr_in.clone(), + }, + ], + OutputType::Combinatorial, + vec![MERGE_OUT_ID], + ), + ) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + MERGE_INSTR_ADDR_ID => self.instr_addr_in = new_input, + MERGE_JUMP_ADDR_ID => self.jump_addr_in = new_input, + _ => {} + } + } + + // propagate sign extension to output + // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get input values + let instr_addr: u32 = simulator + .get_input_value(&self.instr_addr_in) + .try_into() + .unwrap(); + let jump_addr: u32 = simulator + .get_input_value(&self.jump_addr_in) + .try_into() + .unwrap(); + + let output = (instr_addr & 0xf000_0000) & (jump_addr << 2); + + simulator.set_out_value(&self.id, MERGE_OUT_ID, SignalValue::Data(output)); + Ok(()) + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl JumpMerge { + pub fn new(id: &str, pos: (f32, f32), instr_addr_in: Input, jump_addr_in: Input) -> Self { + JumpMerge { + id: id.to_string(), + pos, + instr_addr_in, + jump_addr_in, + } + } + + pub fn rc_new( + id: &str, + pos: (f32, f32), + instr_addr_in: Input, + jump_addr_in: Input, + ) -> Rc { + Rc::new(JumpMerge::new(id, pos, instr_addr_in, jump_addr_in)) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index dd2fa2d0..ccdb1993 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -7,6 +7,7 @@ mod mem; mod mips_controll_unit; mod mips_im; mod mips_instruction_splitter; +mod mips_jump_merge; mod mips_reg_file; mod mux; mod probe; @@ -27,6 +28,7 @@ pub use mem::*; pub use mips_controll_unit::*; pub use mips_im::*; pub use mips_instruction_splitter::*; +pub use mips_jump_merge::*; pub use mips_reg_file::*; pub use mux::*; pub use probe::*; From ef9dc31ec51456ff33f8f9b835d014f2ae616b59 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Fri, 2 Aug 2024 11:40:10 +0200 Subject: [PATCH 024/126] added gui and example for jump merge --- examples/mips_jump_merge.rs | 86 ++++++++++ src/gui_egui/components/mips_jump_merge.rs | 175 +++++++++++++++++++++ src/gui_egui/components/mod.rs | 1 + 3 files changed, 262 insertions(+) create mode 100644 examples/mips_jump_merge.rs create mode 100644 src/gui_egui/components/mips_jump_merge.rs diff --git a/examples/mips_jump_merge.rs b/examples/mips_jump_merge.rs new file mode 100644 index 00000000..4629677a --- /dev/null +++ b/examples/mips_jump_merge.rs @@ -0,0 +1,86 @@ +use std::rc::Rc; +use std::{ + any::{Any, TypeId}, + path::PathBuf, +}; +use syncrim::common::EguiComponent; +#[cfg(feature = "gui-egui")] +use syncrim::gui_egui::editor::Library; +use syncrim::{ + common::{ComponentStore, Input}, + component_store, + components::*, + fern::fern_setup, +}; + +fn main() { + fern_setup(); + let cs = ComponentStore { + store: vec![ + JumpMerge::rc_new( + "jump_merge", + (160.0, 120.0), + Input::new("c0", "out"), + Input::new("c1", "out"), + ), + // Constant::rc_new("c0", (60.0, 100.0), 10), + // Constant::rc_new("c1", (60.0, 140.0), 5), + // Constant::rc_new("c2", (60.0, 180.0), 1), + ProbeEdit::rc_new("c0", (60.0, 100.0)), + ProbeEdit::rc_new("c1", (60.0, 140.0)), + Probe::rc_new("p1", (270.0, 120.0), Input::new("jump_merge", MERGE_OUT_ID)), + ], + }; + + let cs = autowire(cs); + + let path = PathBuf::from("add.json"); + cs.save_file(&path); + + #[cfg(feature = "gui-egui")] + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + + #[cfg(feature = "gui-vizia")] + syncrim::gui_vizia::gui(cs, &path); +} + +fn autowire(mut cs: ComponentStore) -> ComponentStore { + let mut tmp_vec: Vec> = vec![]; + + // look through the list of components + for c in &cs.store { + let (id, ports) = c.get_id_ports(); + println!("{}", id); + + let number_of_inputs = ports.inputs.len(); + + for n in 0..number_of_inputs { + // println!("{:?}", ports.inputs[n].input.id); + // println!("{:?}", ports.inputs[n]); + + let id_tmp = format!("{id}_w{n}"); + let input = ports.inputs[n].input.clone(); + let starting_pos = c.get_pos(); + + // creates temporary vales to use when constatnt inputs are there for testing + let mut destination_pos = (starting_pos.0 - 50.0, starting_pos.1); + let default_input = Input::new(&ports.inputs[n].input.id, "out"); + + // look through the list again and act when you find a matching id + for d in &cs.store { + let (id2, ports2) = d.get_id_ports(); + // look if the id matches the one you are looking for + if id2 == ports.inputs[n].input.id { + // collect the components destination and use it to make a complete wire + destination_pos = d.get_pos(); + let w = + Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], input.clone()); + tmp_vec.push(w); + } + } + } + } + cs.store.append(&mut tmp_vec); + + return cs; +} diff --git a/src/gui_egui/components/mips_jump_merge.rs b/src/gui_egui/components/mips_jump_merge.rs new file mode 100644 index 00000000..0fccb7c9 --- /dev/null +++ b/src/gui_egui/components/mips_jump_merge.rs @@ -0,0 +1,175 @@ +use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::components::JumpMerge; +use crate::gui_egui::component_ui::{ + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::offset_helper; +use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; + +#[typetag::serde] +impl EguiComponent for JumpMerge { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + // 81x41 + // middle: 41x 21y (0 0) + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + // The shape + ui.painter().add(Shape::closed_line( + vec![ + oh((-40f32, 0f32), s, o), + oh((40f32, 0f32), s, o), + oh((40f32, 20f32), s, o), + oh((-40f32, 20f32), s, o), + ], + Stroke { + width: scale, + color: Color32::RED, + }, + )); + + let rect = Rect { + min: oh((-40f32, -20f32), s, o), + max: oh((40f32, 20f32), s, o), + }; + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + // todo: is this actually correct? + if let Some(s) = &simulator { + ui.label({ + let a_r: Result = + s.get_input_value(&self.instr_addr_in).try_into(); + + let b_r: Result = + s.get_input_value(&self.jump_addr_in).try_into(); + + let mut s: String = "".to_string(); + + match a_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", a_r), + } + match b_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", b_r), + } + format!("{}", s) + }); + ui.label("Merge"); + } + }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let r_vec = JumpMerge::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_drag_value(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.instr_addr_in, + crate::components::MERGE_INSTR_ADDR_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.jump_addr_in, + crate::components::MERGE_JUMP_ADDR_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown + }, + ); + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + crate::components::SEXT_IN_ID.to_string(), + Pos2::new(-40f32, 0f32) + own_pos, + ), + ( + crate::components::SEXT_OUT_ID.to_string(), + Pos2::new(40f32, 0f32) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + 20f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } +} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index 34ee1797..d053676a 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -7,6 +7,7 @@ mod mem; mod mips_controll_unit; mod mips_im; mod mips_instruction_splitter; +mod mips_jump_merge; mod mips_reg_file; mod mux; mod probe; From cd4736e242487b499d75add9daae112e57e9e08c Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Fri, 2 Aug 2024 16:10:16 +0200 Subject: [PATCH 025/126] fixed tests on full adder --- src/components/full_adder.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/full_adder.rs b/src/components/full_adder.rs index bb383605..6597e1a3 100644 --- a/src/components/full_adder.rs +++ b/src/components/full_adder.rs @@ -171,7 +171,7 @@ impl FullAdd { Rc::new(FullAdd::new(id, pos, a_in, b_in, op_in)) } } - +#[cfg(test)] mod test { use super::*; @@ -210,7 +210,7 @@ mod test { println!(""); simulator.set_out_value("a", "out", 42); simulator.set_out_value("b", "out", 1337); - simulator.set_out_value("op", "out", OPADD); + simulator.set_out_value("op", "out", alu_op::ADD); println!("sim_state {:?}", simulator.sim_state); println!(""); simulator.clock(); @@ -225,7 +225,7 @@ mod test { println!(""); simulator.set_out_value("a", "out", (-100i32 as u32)); simulator.set_out_value("b", "out", 1337); - simulator.set_out_value("op", "out", OPADD); + simulator.set_out_value("op", "out", alu_op::ADD); println!("sim_state {:?}", simulator.sim_state); println!(""); simulator.clock(); @@ -239,7 +239,7 @@ mod test { println!(""); simulator.set_out_value("a", "out", (-100i32 as u32)); simulator.set_out_value("b", "out", 1337); - simulator.set_out_value("op", "out", OPSUB); + simulator.set_out_value("op", "out", alu_op::SUB); println!("sim_state {:?}", simulator.sim_state); println!(""); simulator.clock(); @@ -253,7 +253,7 @@ mod test { println!(""); simulator.set_out_value("a", "out", (-100i32 as u32)); simulator.set_out_value("b", "out", 1337); - simulator.set_out_value("op", "out", OPSLT); + simulator.set_out_value("op", "out", alu_op::SLT); println!("sim_state {:?}", simulator.sim_state); println!(""); simulator.clock(); @@ -267,7 +267,7 @@ mod test { println!(""); simulator.set_out_value("a", "out", (-100i32 as u32)); simulator.set_out_value("b", "out", 1337); - simulator.set_out_value("op", "out", OPSLTU); + simulator.set_out_value("op", "out", alu_op::SLTU); println!("sim_state {:?}", simulator.sim_state); println!(""); simulator.clock(); From d56215c2390784f263c85647544d9f0d15aad0b3 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Fri, 2 Aug 2024 16:11:58 +0200 Subject: [PATCH 026/126] updated control unit to support a majority of operations and added tests --- src/components/mips_controll_unit.rs | 1035 ++++++++++++++++++++++---- 1 file changed, 886 insertions(+), 149 deletions(-) diff --git a/src/components/mips_controll_unit.rs b/src/components/mips_controll_unit.rs index 8581b309..0f5c632c 100644 --- a/src/components/mips_controll_unit.rs +++ b/src/components/mips_controll_unit.rs @@ -5,54 +5,177 @@ use crate::common::{ Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, SignalValue, Simulator, }; -use log::*; +use log::trace; use serde::{Deserialize, Serialize}; -use std::any::Any; -use std::rc::Rc; +use std::{any::Any, rc::Rc}; -pub const CONTROL_UNIT_A_IN_ID: &str = "control_unit_a_in"; +use super::alu_op; // values used in communication to the alu -pub const CONTROL_UNIT_MEMTOREG_ID: &str = "MemToReg"; -pub const CONTROL_UNIT_MEMWRITE_ID: &str = "MemWrite"; -pub const CONTROL_UNIT_BRANCH_ID: &str = "Branch"; -pub const CONTROL_UNIT_ALUCONTROL_ID: &str = "ALUControl"; -pub const CONTROL_UNIT_ALUSRC_ID: &str = "ALUSrc"; -pub const CONTROL_UNIT_REGDST_ID: &str = "RegDst"; -pub const CONTROL_UNIT_WRITEENABLE_ID: &str = "WriteEnable"; -pub const CONTROL_UNIT_JUMP_ID: &str = "Jump"; +/// The input and output felid ids for the control unit +pub mod cntr_field { + + pub const INSTR_IN: &str = "control_unit_instr_in"; + + /// const REG_DEST_RT: u32 = 0; + /// const REG_DEST_RD: u32 = 1; + /// const REG_DEST_31: u32 = 2; + pub const REG_DEST_OUT: &str = "reg_dest"; + + /// 0 or 1 + pub const REG_WRITE_ENABLE_OUT: &str = "reg_write_enable"; + + /// const WRITE_REG_SRC_ALU:u32 = 0; + /// const WRITE_REG_SRC_MEM:u32 = 1; + pub const REG_WRITE_SRC_OUT: &str = "reg_write_src"; + + /// se module full_adder:alu_op + pub const ALU_OP_OUT: &str = "alu_op"; + + /// const ALU_SRC_A_OP:u32 = 0; + /// const ALU_SRC_A_RS:u32 = 1; + /// const ALU_SRC_A_ZERO:u32 = 3; + pub const ALU_SRC_A_OUT: &str = "alu_src_a"; + + /// const ALU_SRC_B_RT:u32 = 0; + /// const ALU_SRC_B_PC:u32 = 1; + /// const ALU_SRC_B_IMM:u32 = 2; + pub const ALU_SRC_B_OUT: &str = "alu_src_b"; + + // const EXTEND_ZERO:u32 = 0; + // const EXTEND_SIGNED:u32 = 1; + pub const EXTEND_SELECT_OUT: &str = "extend_select"; + + // 0 or 1 + pub const MEM_WRITE_ENABLE_OUT: &str = "mem_write_enable"; + + // 0 or 1, used for co-processor address stuff + pub const BRANCH_INTERRUPT_OUT: &str = "branch_interrupt"; + + // pub const CP0_MFC0 = 0; + // pub const CP0_MTC0 = 1; + // pub const CP0_RFE = 2; + // pub const CP0_SYSCALL = 3; + pub const CP0_OUT: &str = "cp0_out"; + + pub const MMU_OUT: &str = "mmu_out"; + + //TODO + // Opcode is passed to branch unit wich is responsible to controll branch logic + // pub const BRANCH_TYPE_OUT: &str = "branch"; + + //TODO + // NOTE no mem mode, decided to pass opcode to data mem instead, + // might change when LWL/LWR is implemented along with the load/store controller + // pub const MEM_MODE_OUT : &str = "mem_mode"; +} const NOP: u32 = 0; const OP_0: u32 = 0; + +const FUNCT_SLL: u32 = 0; +const FUNCT_SRL: u32 = 0b00_0010; +const FUNCT_SRA: u32 = 0b00_0011; +const FUNCT_SLLV: u32 = 0b00_0100; +const FUNCT_SRLV: u32 = 0b00_0110; +const FUNCT_SRAV: u32 = 0b00_111; +const FUNCT_JR: u32 = 0b00_1000; +const FUNCT_JALR: u32 = 0b00_1001; +const SYSCALL: u32 = 0b00_1100; +const FUNCT_ADD: u32 = 0b10_0000; +const FUNCT_ADDU: u32 = 0b10_0001; +const FUNCT_SUB: u32 = 0b10_0010; +const FUNCT_SUBU: u32 = 0b10_0011; +const FUNCT_AND: u32 = 0b10_0100; +const FUNCT_OR: u32 = 0b10_0101; +const FUNCT_XOR: u32 = 0b10_0110; +const FUNCT_NOR: u32 = 0b10_0111; +const FUNCT_SLT: u32 = 0b10_1010; +const FUNCT_SLTU: u32 = 0b10_1011; + const OP_1: u32 = 1; -const OP_J: u32 = 0b000_010; -const OP_JAL: u32 = 0b000_011; -const OP_BEQ: u32 = 0b000_100; -const OP_BNE: u32 = 0b000_101; -const OP_BLEZ: u32 = 0b000_110; -const OP_BGTZ: u32 = 0b000_111; -const OP_ADDI: u32 = 0b001_000; -const OP_ADDIU: u32 = 0b001_001; -const OP_SLTI: u32 = 0b001_010; -const OP_SLTIU: u32 = 0b001_011; -const OP_ANDI: u32 = 0b001_100; -const OP_ORI: u32 = 0b001_101; -const OP_XORI: u32 = 0b001_110; -const OP_LUI: u32 = 0b001_111; -const CP0: u32 = 0b010_000; - -const OP_LB: u32 = 0b100_000; -const OP_LH: u32 = 0b100_001; -const OP_LWL: u32 = 0b100_010; -const OP_LW: u32 = 0b100_011; -const OP_LBU: u32 = 0b100_100; -const OP_LHU: u32 = 0b100_101; -const OP_LWR: u32 = 0b100_110; - -const OP_SB: u32 = 0b101_000; -const OP_SH: u32 = 0b101_001; -const OP_SWL: u32 = 0b101_010; -const OP_SW: u32 = 0b101_011; -const OP_SWR: u32 = 0b101_110; + +const B_FUNCT_BLTZ: u32 = 0; +const B_FUNCT_BGEZ: u32 = 1; +const B_FUNCT_BLTZAL: u32 = 0b1_0000; +const B_FUNCT_BGEZAL: u32 = 0b1_0001; + +const OP_J: u32 = 0b00_0010; +const OP_JAL: u32 = 0b00_0011; +const OP_BEQ: u32 = 0b00_0100; +const OP_BNE: u32 = 0b00_0101; +const OP_BLEZ: u32 = 0b00_0110; +const OP_BGTZ: u32 = 0b00_0111; + +const OP_ADDI: u32 = 0b00_1000; +const OP_ADDIU: u32 = 0b00_1001; +const OP_SLTI: u32 = 0b00_1010; +const OP_SLTIU: u32 = 0b00_1011; +const OP_ANDI: u32 = 0b00_1100; +const OP_ORI: u32 = 0b00_1101; +const OP_XORI: u32 = 0b00_1110; +const OP_LUI: u32 = 0b00_1111; + +const OP_CP0: u32 = 0b01_0000; +const CP0_FUNCT_MFC0: u32 = 0; +const CP0_FUNCT_MTF0: u32 = 0b0_0100; +const CP0_FUNCT_SPECIAL: u32 = 0b1_0000; +const CP0_FUNCT_SPECIAL_: u32 = 0b1_0000; + +const OP_LB: u32 = 0b10_0000; +const OP_LH: u32 = 0b10_0001; +const OP_LWL: u32 = 0b10_0010; +const OP_LW: u32 = 0b10_0011; +const OP_LBU: u32 = 0b10_0100; +const OP_LHU: u32 = 0b10_0101; +const OP_LWR: u32 = 0b10_0110; + +const OP_SB: u32 = 0b10_1000; +const OP_SH: u32 = 0b10_1001; +const OP_SWL: u32 = 0b10_1010; +const OP_SW: u32 = 0b10_1011; +const OP_SWR: u32 = 0b10_1110; + +/// module used to get what u32 represent. Used for communication between components +pub mod cntr_unit_signals { + pub const REG_DEST_RT: u32 = 0; + pub const REG_DEST_RD: u32 = 1; + pub const REG_DEST_31: u32 = 2; + + pub const REG_WRITE_DISABLE: u32 = 0; + pub const REG_WRITE_ENABLE: u32 = 1; + + pub const MEM_WRITE_DISABLE: u32 = 0; + pub const MEM_WRITE_ENABLE: u32 = 1; + + pub const ALU_SRC_A_SHAMT: u32 = 0; + pub const ALU_SRC_A_RS: u32 = 1; + pub const ALU_SRC_A_ZERO: u32 = 3; + + pub const ALU_SRC_B_RT: u32 = 0; + pub const ALU_SRC_B_PC: u32 = 1; + pub const ALU_SRC_B_IMM: u32 = 2; + + pub const WRITE_REG_SRC_ALU: u32 = 0; + pub const WRITE_REG_SRC_MEM: u32 = 1; + + pub const NO_BRANCH_INTERRUPT: u32 = 0; + pub const BRANCH_INTERRUPT: u32 = 1; + + pub const EXTEND_ZERO: u32 = 0; + pub const EXTEND_SIGNED: u32 = 1; + + pub const CP0_MFC0: u32 = 0; + pub const CP0_MTC0: u32 = 1; + pub const CP0_RFE: u32 = 2; + pub const CP0_SYSCALL: u32 = 3; + + pub const MMU_NORMAL: u32 = 0; + pub const MMU_CP0: u32 = 1; + pub const MMU_NOP: u32 = 2; + + // Note, it was decided to pass opcode to data mem to handle load + // and store instructions there +} #[derive(Serialize, Deserialize, Clone)] pub struct ControlUnit { @@ -60,7 +183,6 @@ pub struct ControlUnit { pub(crate) pos: (f32, f32), pub(crate) a_in: Input, } - #[typetag::serde] impl Component for ControlUnit { fn to_(&self) { @@ -80,19 +202,22 @@ impl Component for ControlUnit { self.id.clone(), Ports::new( vec![&InputPort { - port_id: CONTROL_UNIT_A_IN_ID.to_string(), + port_id: cntr_field::INSTR_IN.to_string(), input: self.a_in.clone(), }], OutputType::Combinatorial, vec![ - CONTROL_UNIT_MEMTOREG_ID, - CONTROL_UNIT_MEMWRITE_ID, - CONTROL_UNIT_BRANCH_ID, - CONTROL_UNIT_ALUCONTROL_ID, - CONTROL_UNIT_ALUSRC_ID, - CONTROL_UNIT_REGDST_ID, - CONTROL_UNIT_WRITEENABLE_ID, - CONTROL_UNIT_JUMP_ID, + cntr_field::REG_DEST_OUT, + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_field::REG_WRITE_SRC_OUT, + cntr_field::ALU_OP_OUT, + cntr_field::ALU_SRC_A_OUT, + cntr_field::ALU_SRC_B_OUT, + cntr_field::EXTEND_SELECT_OUT, + cntr_field::MEM_WRITE_ENABLE_OUT, + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_field::CP0_OUT, + cntr_field::MMU_OUT, ], ), ) @@ -100,125 +225,433 @@ impl Component for ControlUnit { fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { match target_port_id.as_str() { - CONTROL_UNIT_A_IN_ID => self.a_in = new_input, + cntr_field::INSTR_IN => self.a_in = new_input, _ => {} } } - // propagate sign extension to output - // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { - // get input values - let a: u32 = simulator.get_input_value(&self.a_in).try_into().unwrap(); - - let a_OpCode: u32 = (&a >> 26) & 0x0000_003f; - let a_func: u32 = &a & 0x0000_001f; - - let MemToReg; - let MemWrite; - let Branch; - let ALUControl; - let ALUSrc; - let RegDst; - let WriteEnable; - let Jump; - - if a_OpCode == 0 || a_OpCode == 4 { - ALUSrc = 0; - } else { - ALUSrc = 1; - } + let instr_in: u32 = simulator.get_input_value(&self.a_in).try_into().unwrap(); - if a_OpCode == 0 { - RegDst = 1; - } else { - RegDst = 0; - } + let op_code: u32 = (&instr_in >> 26) & 0x0000_003f; - if a_OpCode == 4 { - Branch = 1; - } else { - Branch = 0; + /// Sets the given field to the given value + macro_rules! set { + ($field:expr, $signal_val:expr) => { + simulator.set_out_value(&self.id, $field, SignalValue::Data($signal_val)) + }; } - if a_OpCode == 35 { - MemToReg = 1; - } else { - MemToReg = 0; - } + /// sets the relevant fields for an i instruction + /// OP rt rs imm + /// ALU_OP and EXTEND ned to be set separately + macro_rules! set_i_instr { + () => { + // set target reg to be RT and read from alu + set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_RT); + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_ENABLE + ); + set!( + cntr_field::REG_WRITE_SRC_OUT, + cntr_unit_signals::WRITE_REG_SRC_ALU + ); - if a_OpCode == 43 { - MemWrite = 1; - } else { - MemWrite = 0; + // set alu src to be RS and imm + set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_RS); + set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_IMM); + }; } - if a_OpCode == 2 { - Jump = 1; - } else { - Jump = 0; - } + /// sets the relevant fields for an load operation + /// reg_src = mem + /// reg_dest = rt + /// addu rs (imm sign extended) + /// MEM MODE needs to be set separately + macro_rules! set_load_instr { + () => { + // set target reg to be RT and read from mem + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_ENABLE + ); + set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_RT); + set!( + cntr_field::REG_WRITE_SRC_OUT, + cntr_unit_signals::WRITE_REG_SRC_MEM + ); - if (a_OpCode == 0) - & (a_func == 32 || a_func == 34 || a_func == 42 || a_func == 36 || a_func == 37) - { - WriteEnable = 1; - } else if a_OpCode == 8 || a_OpCode == 10 || a_OpCode == 35 { - WriteEnable = 1; - } else { - WriteEnable = 0; + // set alu to be addu with rs and signed imm + set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_RS); + set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_IMM); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_SIGNED + ); + }; } + macro_rules! set_store_instr { + () => { + // SET reg_write to disabled nad mem write to enable + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_DISABLE + ); + set!( + cntr_field::MEM_WRITE_ENABLE_OUT, + cntr_unit_signals::MEM_WRITE_ENABLE + ); - if (a_OpCode == 0) & (a_func == 32) { - ALUControl = 2; // AND - } else if a_OpCode == 8 { - ALUControl = 2; // ANDI - } else if a_OpCode == 35 { - ALUControl = 2; //lw - } else if a_OpCode == 43 { - ALUControl = 2; //sw - } else if a_OpCode == 4 { - ALUControl = 6; // beq - } else if (a_OpCode == 0) & (a_func == 34) { - ALUControl = 6; // SUB - } else if (a_OpCode == 0) & (a_func == 42) { - ALUControl = 7; // SLT - } else if a_OpCode == 10 { - ALUControl = 7; // SLTI - } else if (a_OpCode == 0) & (a_func == 36) { - ALUControl = 0; // AND - } else if (a_OpCode == 0) & (a_func == 37) { - ALUControl = 1; //OR - } else { - ALUControl = 0; + // set alu to be addu with rs and signed imm + set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_RS); + set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_IMM); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_SIGNED + ); + }; } - simulator.set_out_value( - &self.id, - CONTROL_UNIT_MEMTOREG_ID, - SignalValue::Data(MemToReg), + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_DISABLE ); - simulator.set_out_value( - &self.id, - CONTROL_UNIT_MEMWRITE_ID, - SignalValue::Data(MemWrite), + set!( + cntr_field::MEM_WRITE_ENABLE_OUT, + cntr_unit_signals::MEM_WRITE_DISABLE ); - simulator.set_out_value(&self.id, CONTROL_UNIT_BRANCH_ID, SignalValue::Data(Branch)); - simulator.set_out_value( - &self.id, - CONTROL_UNIT_ALUCONTROL_ID, - SignalValue::Data(ALUControl), - ); - simulator.set_out_value(&self.id, CONTROL_UNIT_ALUSRC_ID, SignalValue::Data(ALUSrc)); - simulator.set_out_value(&self.id, CONTROL_UNIT_REGDST_ID, SignalValue::Data(RegDst)); - simulator.set_out_value(&self.id, CONTROL_UNIT_JUMP_ID, SignalValue::Data(Jump)); - simulator.set_out_value( - &self.id, - CONTROL_UNIT_WRITEENABLE_ID, - SignalValue::Data(WriteEnable), + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::NO_BRANCH_INTERRUPT ); + //TODO an idea would be to init all variables + // let alu_src_a : Signal; + // this would make the compiler force us to populate all paths so to not let any signal be undefined + // It would be more code, but would hopefully be more "secure" as it would stop us from forgetting a value + // another idea is to set all signals to uninitialized or dont care for better debugging + + // match the opcode + match op_code { + OP_0 => { + let funct: u32 = &instr_in & 0x0000_003f; + + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_ENABLE + ); // overwritten by JR and SYSCALL to disabled + + set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_RD); // overwritten by JALR to REG_DEST_31 + set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_RS); // overwritten by JALR, SRA, SRL to shamt or zero + set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_RT); // overwritten by JALR to PC + set!( + cntr_field::REG_WRITE_SRC_OUT, + cntr_unit_signals::WRITE_REG_SRC_ALU + ); + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::NO_BRANCH_INTERRUPT + ); // overiden by jr and jalr + + match funct { + FUNCT_SLL => { + set!( + cntr_field::ALU_SRC_A_OUT, + cntr_unit_signals::ALU_SRC_A_SHAMT + ); + set!(cntr_field::ALU_OP_OUT, alu_op::SLL); + Ok(()) + } + FUNCT_SRL => { + set!( + cntr_field::ALU_SRC_A_OUT, + cntr_unit_signals::ALU_SRC_A_SHAMT + ); + set!(cntr_field::ALU_OP_OUT, alu_op::SRL); + Ok(()) + } + FUNCT_SRA => { + set!( + cntr_field::ALU_SRC_A_OUT, + cntr_unit_signals::ALU_SRC_A_SHAMT + ); + set!(cntr_field::ALU_OP_OUT, alu_op::SRA); + Ok(()) + } + FUNCT_SLLV => { + set!(cntr_field::ALU_OP_OUT, alu_op::SLL); + Ok(()) + } + FUNCT_SRLV => { + set!(cntr_field::ALU_OP_OUT, alu_op::SRL); + Ok(()) + } + FUNCT_SRAV => { + set!(cntr_field::ALU_OP_OUT, alu_op::SRL); + Ok(()) + } + FUNCT_JR => { + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::BRANCH_INTERRUPT + ); + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_DISABLE + ); + Ok(()) + } + FUNCT_JALR => { + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::BRANCH_INTERRUPT + ); + set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_RD); // this is different from syncsim as there its defined as 31, but that dosen't match mips documentation; + set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_ZERO); + set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_PC); + set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + Ok(()) + } + SYSCALL => { + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_DISABLE + ); + set!(cntr_field::CP0_OUT, cntr_unit_signals::CP0_SYSCALL); + Ok(()) + } + FUNCT_ADD => { + set!(cntr_field::ALU_OP_OUT, alu_op::ADD); + Ok(()) + } + FUNCT_ADDU => { + set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + Ok(()) + } + FUNCT_SUB => { + set!(cntr_field::ALU_OP_OUT, alu_op::SUB); + Ok(()) + } + FUNCT_SUBU => { + set!(cntr_field::ALU_OP_OUT, alu_op::SUBU); + Ok(()) + } + FUNCT_AND => { + set!(cntr_field::ALU_OP_OUT, alu_op::AND); + Ok(()) + } + FUNCT_OR => { + set!(cntr_field::ALU_OP_OUT, alu_op::OR); + Ok(()) + } + FUNCT_XOR => { + set!(cntr_field::ALU_OP_OUT, alu_op::XOR); + Ok(()) + } + FUNCT_NOR => { + set!(cntr_field::ALU_OP_OUT, alu_op::NOR); + Ok(()) + } + FUNCT_SLT => { + set!(cntr_field::ALU_OP_OUT, alu_op::SLT); + Ok(()) + } + FUNCT_SLTU => { + set!(cntr_field::ALU_OP_OUT, alu_op::SLTU); + Ok(()) + } + _ => Err(Condition::Error(format!( + "unknown funct {:#08b} for opcode 0b000000", + funct + ))), + } + } + OP_1 => { + // branch stuff, BGEZ BGEZAL BLTZ BLTZAL, + // Note many branch and jump instructions are actually pseudo instructions and will be compiled to others + // BAL => BGEZAL r0 offset + let tmp: u32 = simulator.get_input_signal(&self.a_in).try_into().unwrap(); + let b_funct: u32 = (tmp >> 16) & 0b11111; + + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::BRANCH_INTERRUPT + ); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_SIGNED + ); + match b_funct { + B_FUNCT_BGEZ | B_FUNCT_BLTZ => Ok(()), + B_FUNCT_BGEZAL | B_FUNCT_BLTZAL => { + // save pc to reg + set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_31); + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_ENABLE + ); + set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_ZERO); + set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_PC); + set!( + cntr_field::REG_WRITE_SRC_OUT, + cntr_unit_signals::WRITE_REG_SRC_ALU + ); + Ok(()) + } + _ => Err(Condition::Error(format!( + "unknown funct {:#07b} for opcode 0b000001", + b_funct + ))), + } + } + OP_J => { + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::BRANCH_INTERRUPT + ); + Ok(()) + } + OP_JAL => { + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::BRANCH_INTERRUPT + ); + set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_31); + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_ENABLE + ); + set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_ZERO); + set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_PC); + set!( + cntr_field::REG_WRITE_SRC_OUT, + cntr_unit_signals::WRITE_REG_SRC_ALU + ); + Ok(()) + } + OP_BEQ | OP_BNE | OP_BLEZ | OP_BGTZ => { + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::BRANCH_INTERRUPT + ); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_SIGNED + ); + Ok(()) + } + OP_ADDI => { + set_i_instr!(); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_SIGNED + ); + set!(cntr_field::ALU_OP_OUT, alu_op::ADD); + Ok(()) + } + OP_ADDIU => { + set_i_instr!(); + set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + Ok(()) + } + OP_SLTI => { + set_i_instr!(); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_SIGNED + ); + set!(cntr_field::ALU_OP_OUT, alu_op::SLT); + Ok(()) + } + OP_SLTIU => { + set_i_instr!(); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_ZERO + ); + set!(cntr_field::ALU_OP_OUT, alu_op::SLTU); + Ok(()) + } + OP_ANDI => { + set_i_instr!(); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_ZERO + ); + set!(cntr_field::ALU_OP_OUT, alu_op::AND); + Ok(()) + } + OP_ORI => { + set_i_instr!(); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_ZERO + ); + set!(cntr_field::ALU_OP_OUT, alu_op::OR); + Ok(()) + } + OP_XORI => { + set_i_instr!(); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_ZERO + ); + set!(cntr_field::ALU_OP_OUT, alu_op::XOR); + Ok(()) + } + OP_LUI => { + set_i_instr!(); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_ZERO + ); + set!(cntr_field::ALU_OP_OUT, alu_op::LUI); + Ok(()) + } + OP_CP0 => { + // let cp0_funct:u32 = (&instr_in >> 21) & 0b11111; + // match cp0_funct { + // CP0_FUNCT_MFC0 =>{ + // set!(cntr_field::REG_DEST_OUT,cntr_unit_signals::REG_DEST_RT); + // set!(cntr_field::REG_WRITE_ENABLE_OUT, cntr_unit_signals::REG_WRITE_ENABLE); + + // //TODO no idea why alu would be required for this operation and cant find any path in syncsim, + // // but following blindly. If time permits figure out why and change + // set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + // set!(cntr_field::ALU_SRC_A_OUT,cntr_unit_signals::ALU_SRC_A_SHAMT); + // set!(cntr_field::ALU_SRC_B_OUT,cntr_unit_signals::ALU_SRC_B_IMM); + // todo!("implement memory mode to complete MFC0") + + // } + // _ => { + // Err(Condition::Error(format!("unknown funct {:#07b}for opcode {:#08b} CP0", cp0_funct, OP_CP0))) + // } + // } + Err(Condition::Error(format!( + "CP0 instructions not yet implemented" + ))) + } + //TODO use mem_mode, now it assumed data_mem uses opcode to determine that itself + OP_LB | OP_LBU | OP_LH | OP_LHU | OP_LW => { + set_load_instr!(); + Ok(()) + } - Ok(()) + OP_SB | OP_SH | OP_SW => { + set_store_instr!(); + Ok(()) + } + + OP_LWL | OP_LWR | OP_SWL | OP_SWR => Err(Condition::Error( + "LWL, LWR, SWL and SWR are not implemented".to_string(), + )), + + _ => Err(Condition::Error(format!("Unknown opcode {:#08b}", op_code))), + } } fn as_any(&self) -> &dyn Any { @@ -239,3 +672,307 @@ impl ControlUnit { Rc::new(ControlUnit::new(id, pos, a_in)) } } +#[cfg(test)] +mod test { + use crate::{common::ComponentStore, components::ProbeOut}; + + use super::*; + + fn setup_simulator() -> Simulator { + let cs = ComponentStore { + store: vec![ + Rc::new(ProbeOut::new("instr")), + ControlUnit::rc_new("cntr", (0.0, 0.0), Input::new("instr", "out")), + ], + }; + Simulator::new(cs).unwrap() + } + /// This tests + /// - beq t3 t0 7 => 000100 01011 01000 0000000000000111 + /// - xori $t6,$s4,32 => 001110 10100 01110 0000000000100000 + /// - sub $t0,$a0,$t0 => 000000 00100 01000 01000 00000 100010 + /// - lh $a1,14($s1) => 100001 10001 00101 0000000000001110 + /// - jal => 000011 10101010101010101010101010 + /// - jalr r10 r18 => 000000_10010_00000_01010_00000_001001 + #[test] + fn test_random_instrs() { + let mut sim = setup_simulator(); + + assert_eq!(sim.cycle, 1); + + println!("testing beq t3 t0 7 => 000100 01011 01000 0000000000000111"); + sim.set_out_value("instr", "out", 0b000100_01011_01000_0000000000000111); + println!("clock sim"); + sim.clock(); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), + cntr_unit_signals::BRANCH_INTERRUPT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), + cntr_unit_signals::REG_WRITE_DISABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), + cntr_unit_signals::MEM_WRITE_DISABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::EXTEND_SELECT_OUT)), + cntr_unit_signals::EXTEND_SIGNED.into() + ); + + println!("testing xori $t6,$s4,32 => 001110 10100 01110 0000000000100000"); + sim.set_out_value("instr", "out", 0b001110_10100_01110_0000000000100000); + println!("clock sim"); + sim.clock(); + // no branch or mem write + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), + cntr_unit_signals::NO_BRANCH_INTERRUPT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), + cntr_unit_signals::MEM_WRITE_DISABLE.into() + ); + + // reg write, src alu and reg_dest rt, since rd is occupied by imm + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), + cntr_unit_signals::REG_WRITE_ENABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), + cntr_unit_signals::WRITE_REG_SRC_ALU.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), + cntr_unit_signals::REG_DEST_RT.into() + ); + + // ALU xor rs and imm zero extend + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::EXTEND_SELECT_OUT)), + cntr_unit_signals::EXTEND_ZERO.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), + cntr_unit_signals::ALU_SRC_A_RS.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), + cntr_unit_signals::ALU_SRC_B_IMM.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), + alu_op::XOR.into() + ); + + print!("testing sub $t0,$a0,$t0 => 000000 00100 01000 01000 00000 100010"); + sim.set_out_value("instr", "out", 0b000000_00100_01000_01000_00000_100010); + println!("clock sim"); + sim.clock(); + // no branch or mem write + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), + cntr_unit_signals::NO_BRANCH_INTERRUPT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), + cntr_unit_signals::MEM_WRITE_DISABLE.into() + ); + + // reg write, src alu and reg_dest rd + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), + cntr_unit_signals::REG_WRITE_ENABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), + cntr_unit_signals::WRITE_REG_SRC_ALU.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), + cntr_unit_signals::REG_DEST_RD.into(), + ); + + // ALU sub rs and rt + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), + cntr_unit_signals::ALU_SRC_A_RS.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), + cntr_unit_signals::ALU_SRC_B_RT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), + alu_op::SUB.into() + ); + + print!("testing lh $a1,14($s1) => 100001 10001 00101 0000000000001110"); + sim.set_out_value("instr", "out", 0b100001_10001_00101_0000000000001110); + println!("clock sim"); + sim.clock(); + // reg write, no branch, no mem write + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), + cntr_unit_signals::NO_BRANCH_INTERRUPT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), + cntr_unit_signals::MEM_WRITE_DISABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), + cntr_unit_signals::REG_WRITE_ENABLE.into() + ); + + // reg dst rt, reg src mem + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), + cntr_unit_signals::WRITE_REG_SRC_MEM.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), + cntr_unit_signals::REG_DEST_RT.into() + ); + + // ADDU rs imm (signed) + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::EXTEND_SELECT_OUT)), + cntr_unit_signals::EXTEND_SIGNED.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), + cntr_unit_signals::ALU_SRC_A_RS.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), + cntr_unit_signals::ALU_SRC_B_IMM.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), + alu_op::ADDU.into() + ); + + println!("testing SW $r2 4($r3) => 101011 00011 00010 0000_0000_0000_0100"); + sim.set_out_value("instr", "out", 0b101011_00011_00010_0000_0000_0000_0100); + println!("clock sim"); + sim.clock(); + // no reg write, no branch, mem write + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), + cntr_unit_signals::NO_BRANCH_INTERRUPT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), + cntr_unit_signals::MEM_WRITE_ENABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), + cntr_unit_signals::REG_WRITE_DISABLE.into() + ); + + // ADDU rs imm (signed) + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::EXTEND_SELECT_OUT)), + cntr_unit_signals::EXTEND_SIGNED.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), + cntr_unit_signals::ALU_SRC_A_RS.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), + cntr_unit_signals::ALU_SRC_B_IMM.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), + alu_op::ADDU.into() + ); + + println!("testing jal => 000011 10101010101010101010101010 "); + sim.set_out_value("instr", "out", 0b000011_10101010101010101010101010); + println!("clock sim"); + sim.clock(); + // reg write, branch, no mem write + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), + cntr_unit_signals::BRANCH_INTERRUPT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), + cntr_unit_signals::MEM_WRITE_DISABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), + cntr_unit_signals::REG_WRITE_ENABLE.into() + ); + + // ALU zero + pc + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), + cntr_unit_signals::ALU_SRC_A_ZERO.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), + cntr_unit_signals::ALU_SRC_B_PC.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), + alu_op::ADDU.into() + ); + + // reg dst 31, reg src alu + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), + cntr_unit_signals::WRITE_REG_SRC_ALU.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), + cntr_unit_signals::REG_DEST_31.into() + ); + + println!("testing jalr r10 r18 => 000000_10010_00000_01010_00000_001001"); + sim.set_out_value("instr", "out", 0b000000_10010_00000_01010_00000_001001); + println!("clock sim"); + sim.clock(); + // reg write, branch, no mem write + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), + cntr_unit_signals::BRANCH_INTERRUPT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), + cntr_unit_signals::MEM_WRITE_DISABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), + cntr_unit_signals::REG_WRITE_ENABLE.into() + ); + + // ALU zero + pc + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), + cntr_unit_signals::ALU_SRC_A_ZERO.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), + cntr_unit_signals::ALU_SRC_B_PC.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), + alu_op::ADDU.into() + ); + + // reg dst rd, reg src alu + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), + cntr_unit_signals::WRITE_REG_SRC_ALU.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), + cntr_unit_signals::REG_DEST_RD.into() + ); + } +} From 01665814a7ae1f02eb9d5b7be0dfac86bf9b9d6b Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Mon, 5 Aug 2024 10:39:52 +0200 Subject: [PATCH 027/126] updated control unit example --- examples/mips_controll_unit.rs | 58 ++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/examples/mips_controll_unit.rs b/examples/mips_controll_unit.rs index 789085a1..6461e18f 100644 --- a/examples/mips_controll_unit.rs +++ b/examples/mips_controll_unit.rs @@ -17,48 +17,52 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - ControlUnit::rc_new("control_unit", (200.0, 120.0), Input::new("c0", "out")), - // Constant::rc_new("c0", (60.0, 100.0), 10), - ProbeEdit::rc_new("c0", (60.0, 120.0)), + Rc::new(ProbeEdit::new("instr", (100.0, 10.0))), + ControlUnit::rc_new("cntr", (200.0, 10.0), Input::new("instr", "out")), Probe::rc_new( - "p1", - (270.0, 120.0), - Input::new("control_unit", CONTROL_UNIT_MEMTOREG_ID), + "reg_dest", + (300.0, 10.0), + Input::new("cntr", cntr_field::REG_DEST_OUT), ), Probe::rc_new( - "p2", - (270.0, 170.0), - Input::new("control_unit", CONTROL_UNIT_MEMWRITE_ID), + "reg_write", + (300.0, 30.0), + Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT), ), Probe::rc_new( - "p3", - (270.0, 220.0), - Input::new("control_unit", CONTROL_UNIT_BRANCH_ID), + "reg_write_src", + (300.0, 50.0), + Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT), ), Probe::rc_new( - "p4", - (270.0, 270.0), - Input::new("control_unit", CONTROL_UNIT_ALUCONTROL_ID), + "alu_op", + (300.0, 70.0), + Input::new("cntr", cntr_field::ALU_OP_OUT), ), Probe::rc_new( - "p5", - (270.0, 320.0), - Input::new("control_unit", CONTROL_UNIT_ALUSRC_ID), + "alu_src_a", + (300.0, 90.0), + Input::new("cntr", cntr_field::ALU_SRC_A_OUT), ), Probe::rc_new( - "p6", - (270.0, 370.0), - Input::new("control_unit", CONTROL_UNIT_REGDST_ID), + "alu_src_b", + (300.0, 110.0), + Input::new("cntr", cntr_field::ALU_SRC_B_OUT), ), Probe::rc_new( - "p7", - (270.0, 420.0), - Input::new("control_unit", CONTROL_UNIT_WRITEENABLE_ID), + "extend_select", + (300.0, 130.0), + Input::new("cntr", cntr_field::EXTEND_SELECT_OUT), ), Probe::rc_new( - "p8", - (270.0, 470.0), - Input::new("control_unit", CONTROL_UNIT_JUMP_ID), + "mem_write", + (300.0, 150.0), + Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT), + ), + Probe::rc_new( + "branch_interrupt", + (300.0, 170.0), + Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT), ), ], }; From 1a5f6a8eb2886cfd43fd227f227a54b73cc801e7 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Mon, 5 Aug 2024 14:07:31 +0200 Subject: [PATCH 028/126] added component for branch logic --- src/components/mips_branch_logic.rs | 244 ++++++++++++++++++++++++++++ src/components/mod.rs | 2 + 2 files changed, 246 insertions(+) create mode 100644 src/components/mips_branch_logic.rs diff --git a/src/components/mips_branch_logic.rs b/src/components/mips_branch_logic.rs new file mode 100644 index 00000000..c7c37a38 --- /dev/null +++ b/src/components/mips_branch_logic.rs @@ -0,0 +1,244 @@ +// use std::fmt::Alignment; +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, + SignalValue, Simulator, +}; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::rc::Rc; + +pub const BRANCH_OP_ID: &str = "branch_op_in"; +pub const BRANCH_RS_ID: &str = "branch_rs_in"; +pub const BRANCH_RT_ID: &str = "branch_rt_in"; +pub const BRANCH_FUNCT_ID: &str = "branch_funct_in"; + +pub const BRANCH_RS_VALUE_ID: &str = "branch_rs_vlaue_id"; +pub const BRANCH_RT_VALUE_ID: &str = "branch_rt_value_id"; + +pub const BRANCH_OUT_ID: &str = "out"; + +pub const BRANCH_OFFSET: u32 = 0; +pub const BRANCH_REGISTER: u32 = 1; +pub const BRANCH_TARGET: u32 = 2; +pub const BRANCH_ADD4: u32 = 3; + +#[derive(Serialize, Deserialize, Clone)] +pub struct BranchLogic { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) op_in: Input, + pub(crate) rs_in: Input, + pub(crate) rt_in: Input, + pub(crate) funct_in: Input, + pub(crate) rs_value: Input, + pub(crate) rt_value: Input, +} + +#[typetag::serde] +impl Component for BranchLogic { + fn to_(&self) { + trace!("branch_logic"); + } + // #[cfg(feature = "gui-egui")] + // fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + // let dummy_input = Input::new("dummy", "out"); + // Box::new(Rc::new(BranchLogic { + // id: "dummy".to_string(), + // pos: (0.0, 0.0), + // clk_in: dummy_input.clone(), + // })) + // } + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![ + &InputPort { + port_id: BRANCH_OP_ID.to_string(), + input: self.op_in.clone(), + }, + &InputPort { + port_id: BRANCH_RS_ID.to_string(), + input: self.rs_in.clone(), + }, + &InputPort { + port_id: BRANCH_RT_ID.to_string(), + input: self.rt_in.clone(), + }, + &InputPort { + port_id: BRANCH_FUNCT_ID.to_string(), + input: self.funct_in.clone(), + }, + &InputPort { + port_id: BRANCH_RS_VALUE_ID.to_string(), + input: self.rs_value.clone(), + }, + &InputPort { + port_id: BRANCH_RT_VALUE_ID.to_string(), + input: self.rt_value.clone(), + }, + ], + OutputType::Combinatorial, + vec![BRANCH_OUT_ID], + ), + ) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + BRANCH_OP_ID => self.op_in = new_input, + BRANCH_RS_ID => self.rs_in = new_input, + BRANCH_RT_ID => self.rt_in = new_input, + BRANCH_FUNCT_ID => self.funct_in = new_input, + BRANCH_RS_VALUE_ID => self.rs_value = new_input, + BRANCH_RT_VALUE_ID => self.rt_value = new_input, + _ => {} + } + } + + // propagate sign extension to output + // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get input values + let op: u32 = simulator.get_input_value(&self.op_in).try_into().unwrap(); + let rs: u32 = simulator.get_input_value(&self.rs_in).try_into().unwrap(); + let rt: u32 = simulator.get_input_value(&self.rt_in).try_into().unwrap(); + let funct: u32 = simulator + .get_input_value(&self.funct_in) + .try_into() + .unwrap(); + let rs_value: u32 = simulator + .get_input_value(&self.rs_value) + .try_into() + .unwrap(); + let rt_value: u32 = simulator + .get_input_value(&self.rt_value) + .try_into() + .unwrap(); + + let out: u32; + + match op { + 0 => { + if (funct != 8) & (funct != 9) { + out = BRANCH_ADD4; + } else { + // JR, JARL + out = BRANCH_REGISTER; + } + } + 1 => { + if (rt != 0) & (rt != 16) { + // not BLTZ, BLTZAL + if (rt != 1) & (rt != 17) { + //not BGEZ, BGEZAL + // error + out = BRANCH_ADD4; + } else if (rs_value as i32) >= 0 { + // BGEZ, BGEZAL + out = BRANCH_OFFSET; + } else { + out = BRANCH_ADD4; + } + } else if (rs_value as i32) < 0 { + // BLTZ, BLTZAL + out = BRANCH_OFFSET; + } else { + out = BRANCH_ADD4; + } + } + 2 => { + // J + out = BRANCH_TARGET; + } + 3 => { + // JAL + out = BRANCH_TARGET; + } + 4 => { + if rs_value == rt_value { + // BEQ + out = BRANCH_OFFSET; + } else { + out = BRANCH_ADD4; + } + } + 5 => { + if rs_value == rt_value { + // BNE + out = BRANCH_ADD4; + } else { + out = BRANCH_OFFSET; + } + } + 6 => { + if (rs_value as i32) <= 0 { + // BLEZ + out = BRANCH_OFFSET; + } else { + out = BRANCH_ADD4; + } + } + 7 => { + if (rs_value as i32) > 0 { + // BGTZ + out = BRANCH_OFFSET; + } else { + out = BRANCH_ADD4; + } + } + _ => { + out = BRANCH_ADD4; + } + } + + simulator.set_out_value(&self.id, BRANCH_OUT_ID, SignalValue::Data(out)); + Ok(()) + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl BranchLogic { + pub fn new( + id: &str, + pos: (f32, f32), + op_in: Input, + rs_in: Input, + rt_in: Input, + funct_in: Input, + rs_value: Input, + rt_value: Input, + ) -> Self { + BranchLogic { + id: id.to_string(), + pos, + op_in, + rs_in, + rt_in, + funct_in, + rs_value, + rt_value, + } + } + + pub fn rc_new( + id: &str, + pos: (f32, f32), + op_in: Input, + rs_in: Input, + rt_in: Input, + funct_in: Input, + rs_value: Input, + rt_value: Input, + ) -> Rc { + Rc::new(BranchLogic::new( + id, pos, op_in, rs_in, rt_in, funct_in, rs_value, rt_value, + )) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index ccdb1993..85a46341 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -4,6 +4,7 @@ mod constant; mod cross; mod full_adder; mod mem; +mod mips_branch_logic; mod mips_controll_unit; mod mips_im; mod mips_instruction_splitter; @@ -25,6 +26,7 @@ pub use constant::*; pub use cross::*; pub use full_adder::*; pub use mem::*; +pub use mips_branch_logic::*; pub use mips_controll_unit::*; pub use mips_im::*; pub use mips_instruction_splitter::*; From a368567d27c710daef706ea056acc31ee4663c7f Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Mon, 5 Aug 2024 14:27:00 +0200 Subject: [PATCH 029/126] fixed warnings --- src/components/clk.rs | 5 ++--- src/components/full_adder.rs | 21 +++++++++---------- src/components/mips_branch_logic.rs | 18 +++------------- src/components/mips_controll_unit.rs | 5 ++--- src/components/mips_instruction_splitter.rs | 5 ++--- src/components/mips_jump_merge.rs | 3 +-- src/gui_egui/components/clk.rs | 2 +- src/gui_egui/components/full_adder.rs | 8 +++---- src/gui_egui/components/mips_controll_unit.rs | 2 +- .../components/mips_instruction_splitter.rs | 2 +- src/gui_egui/components/mips_jump_merge.rs | 2 +- src/gui_egui/components/mips_reg_file.rs | 2 +- 12 files changed, 29 insertions(+), 46 deletions(-) diff --git a/src/components/clk.rs b/src/components/clk.rs index bf03b4b2..13619988 100644 --- a/src/components/clk.rs +++ b/src/components/clk.rs @@ -2,8 +2,7 @@ #[cfg(feature = "gui-egui")] use crate::common::EguiComponent; use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, - SignalValue, Simulator, + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; use log::*; use serde::{Deserialize, Serialize}; @@ -27,7 +26,7 @@ impl Component for MIPSCLK { trace!("pc+4"); } #[cfg(feature = "gui-egui")] - fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { let dummy_input = Input::new("dummy", "out"); Box::new(Rc::new(MIPSCLK { id: "dummy".to_string(), diff --git a/src/components/full_adder.rs b/src/components/full_adder.rs index 6597e1a3..65a8e7e4 100644 --- a/src/components/full_adder.rs +++ b/src/components/full_adder.rs @@ -2,8 +2,7 @@ #[cfg(feature = "gui-egui")] use crate::common::EguiComponent; use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, - SignalValue, Simulator, + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; use log::*; use serde::{Deserialize, Serialize}; @@ -47,7 +46,7 @@ impl Component for FullAdd { trace!("full_adder"); } #[cfg(feature = "gui-egui")] - fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { let dummy_input = Input::new("dummy", "out"); Box::new(Rc::new(FullAdd { id: "dummy".to_string(), @@ -112,13 +111,13 @@ impl Component for FullAdd { return Err(Condition::Error("SUBU not implemented".to_string())); } alu_op::AND => { - output = (a & b); + output = a & b; } alu_op::OR => { - output = (a | b); + output = a | b; } alu_op::XOR => { - output = (a ^ b); + output = a ^ b; } alu_op::NOR => { output = !(a | b); @@ -176,7 +175,7 @@ mod test { use super::*; use crate::{ - common::{ComponentStore, Input, SignalUnsigned, Simulator}, + common::{ComponentStore, Input, Simulator}, components::ProbeOut, }; use std::rc::Rc; @@ -223,7 +222,7 @@ mod test { ); println!(""); - simulator.set_out_value("a", "out", (-100i32 as u32)); + simulator.set_out_value("a", "out", -100i32 as u32); simulator.set_out_value("b", "out", 1337); simulator.set_out_value("op", "out", alu_op::ADD); println!("sim_state {:?}", simulator.sim_state); @@ -237,7 +236,7 @@ mod test { ); println!(""); - simulator.set_out_value("a", "out", (-100i32 as u32)); + simulator.set_out_value("a", "out", -100i32 as u32); simulator.set_out_value("b", "out", 1337); simulator.set_out_value("op", "out", alu_op::SUB); println!("sim_state {:?}", simulator.sim_state); @@ -251,7 +250,7 @@ mod test { ); println!(""); - simulator.set_out_value("a", "out", (-100i32 as u32)); + simulator.set_out_value("a", "out", -100i32 as u32); simulator.set_out_value("b", "out", 1337); simulator.set_out_value("op", "out", alu_op::SLT); println!("sim_state {:?}", simulator.sim_state); @@ -265,7 +264,7 @@ mod test { ); println!(""); - simulator.set_out_value("a", "out", (-100i32 as u32)); + simulator.set_out_value("a", "out", -100i32 as u32); simulator.set_out_value("b", "out", 1337); simulator.set_out_value("op", "out", alu_op::SLTU); println!("sim_state {:?}", simulator.sim_state); diff --git a/src/components/mips_branch_logic.rs b/src/components/mips_branch_logic.rs index c7c37a38..f96bf75e 100644 --- a/src/components/mips_branch_logic.rs +++ b/src/components/mips_branch_logic.rs @@ -2,8 +2,7 @@ #[cfg(feature = "gui-egui")] use crate::common::EguiComponent; use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, - SignalValue, Simulator, + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; use log::*; use serde::{Deserialize, Serialize}; @@ -11,7 +10,6 @@ use std::any::Any; use std::rc::Rc; pub const BRANCH_OP_ID: &str = "branch_op_in"; -pub const BRANCH_RS_ID: &str = "branch_rs_in"; pub const BRANCH_RT_ID: &str = "branch_rt_in"; pub const BRANCH_FUNCT_ID: &str = "branch_funct_in"; @@ -30,7 +28,6 @@ pub struct BranchLogic { pub(crate) id: Id, pub(crate) pos: (f32, f32), pub(crate) op_in: Input, - pub(crate) rs_in: Input, pub(crate) rt_in: Input, pub(crate) funct_in: Input, pub(crate) rs_value: Input, @@ -43,7 +40,7 @@ impl Component for BranchLogic { trace!("branch_logic"); } // #[cfg(feature = "gui-egui")] - // fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + // fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { // let dummy_input = Input::new("dummy", "out"); // Box::new(Rc::new(BranchLogic { // id: "dummy".to_string(), @@ -60,10 +57,6 @@ impl Component for BranchLogic { port_id: BRANCH_OP_ID.to_string(), input: self.op_in.clone(), }, - &InputPort { - port_id: BRANCH_RS_ID.to_string(), - input: self.rs_in.clone(), - }, &InputPort { port_id: BRANCH_RT_ID.to_string(), input: self.rt_in.clone(), @@ -90,7 +83,6 @@ impl Component for BranchLogic { fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { match target_port_id.as_str() { BRANCH_OP_ID => self.op_in = new_input, - BRANCH_RS_ID => self.rs_in = new_input, BRANCH_RT_ID => self.rt_in = new_input, BRANCH_FUNCT_ID => self.funct_in = new_input, BRANCH_RS_VALUE_ID => self.rs_value = new_input, @@ -104,7 +96,6 @@ impl Component for BranchLogic { fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { // get input values let op: u32 = simulator.get_input_value(&self.op_in).try_into().unwrap(); - let rs: u32 = simulator.get_input_value(&self.rs_in).try_into().unwrap(); let rt: u32 = simulator.get_input_value(&self.rt_in).try_into().unwrap(); let funct: u32 = simulator .get_input_value(&self.funct_in) @@ -209,7 +200,6 @@ impl BranchLogic { id: &str, pos: (f32, f32), op_in: Input, - rs_in: Input, rt_in: Input, funct_in: Input, rs_value: Input, @@ -219,7 +209,6 @@ impl BranchLogic { id: id.to_string(), pos, op_in, - rs_in, rt_in, funct_in, rs_value, @@ -231,14 +220,13 @@ impl BranchLogic { id: &str, pos: (f32, f32), op_in: Input, - rs_in: Input, rt_in: Input, funct_in: Input, rs_value: Input, rt_value: Input, ) -> Rc { Rc::new(BranchLogic::new( - id, pos, op_in, rs_in, rt_in, funct_in, rs_value, rt_value, + id, pos, op_in, rt_in, funct_in, rs_value, rt_value, )) } } diff --git a/src/components/mips_controll_unit.rs b/src/components/mips_controll_unit.rs index 0f5c632c..1f907eef 100644 --- a/src/components/mips_controll_unit.rs +++ b/src/components/mips_controll_unit.rs @@ -2,8 +2,7 @@ #[cfg(feature = "gui-egui")] use crate::common::EguiComponent; use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, - SignalValue, Simulator, + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; use log::trace; use serde::{Deserialize, Serialize}; @@ -189,7 +188,7 @@ impl Component for ControlUnit { trace!("control_unit"); } #[cfg(feature = "gui-egui")] - fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { let dummy_input = Input::new("dummy", "out"); Box::new(Rc::new(ControlUnit { id: "dummy".to_string(), diff --git a/src/components/mips_instruction_splitter.rs b/src/components/mips_instruction_splitter.rs index 03a37397..e606096a 100644 --- a/src/components/mips_instruction_splitter.rs +++ b/src/components/mips_instruction_splitter.rs @@ -2,8 +2,7 @@ #[cfg(feature = "gui-egui")] use crate::common::EguiComponent; use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, - SignalValue, Simulator, + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; use log::*; use serde::{Deserialize, Serialize}; @@ -34,7 +33,7 @@ impl Component for InstrSplit { trace!("pc+4"); } #[cfg(feature = "gui-egui")] - fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { let dummy_input = Input::new("dummy", "out"); Box::new(Rc::new(InstrSplit { id: "dummy".to_string(), diff --git a/src/components/mips_jump_merge.rs b/src/components/mips_jump_merge.rs index 993ebff6..4ba06023 100644 --- a/src/components/mips_jump_merge.rs +++ b/src/components/mips_jump_merge.rs @@ -2,8 +2,7 @@ #[cfg(feature = "gui-egui")] use crate::common::EguiComponent; use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, - SignalValue, Simulator, + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; use log::*; use serde::{Deserialize, Serialize}; diff --git a/src/gui_egui/components/clk.rs b/src/gui_egui/components/clk.rs index eacc23f7..f820c136 100644 --- a/src/gui_egui/components/clk.rs +++ b/src/gui_egui/components/clk.rs @@ -7,7 +7,7 @@ use crate::gui_egui::component_ui::{ use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; -use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; +use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for MIPSCLK { diff --git a/src/gui_egui/components/full_adder.rs b/src/gui_egui/components/full_adder.rs index bcf132d7..1288153b 100644 --- a/src/gui_egui/components/full_adder.rs +++ b/src/gui_egui/components/full_adder.rs @@ -1,4 +1,4 @@ -use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::common::{EguiComponent, Ports, Simulator}; use crate::components::{alu_op, FullAdd}; use crate::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, @@ -8,8 +8,8 @@ use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; use egui::{ - Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Slider, Stroke, - TextWrapMode, Ui, Vec2, + Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Stroke, TextWrapMode, Ui, + Vec2, }; #[typetag::serde] @@ -79,7 +79,7 @@ impl EguiComponent for FullAdd { "no sim".to_string() }; - let area = Area::new(egui::Id::from(self.id.to_string())) + let _area = Area::new(egui::Id::from(self.id.to_string())) .order(Order::Middle) .current_pos(offset.to_pos2() + Vec2::new(5.0, 0.0) * scale) .movable(false) diff --git a/src/gui_egui/components/mips_controll_unit.rs b/src/gui_egui/components/mips_controll_unit.rs index 79c3e07c..a38d6c4c 100644 --- a/src/gui_egui/components/mips_controll_unit.rs +++ b/src/gui_egui/components/mips_controll_unit.rs @@ -7,7 +7,7 @@ use crate::gui_egui::component_ui::{ use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; -use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; +use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for ControlUnit { diff --git a/src/gui_egui/components/mips_instruction_splitter.rs b/src/gui_egui/components/mips_instruction_splitter.rs index cfe834f8..64232b8e 100644 --- a/src/gui_egui/components/mips_instruction_splitter.rs +++ b/src/gui_egui/components/mips_instruction_splitter.rs @@ -7,7 +7,7 @@ use crate::gui_egui::component_ui::{ use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; -use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; +use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for InstrSplit { diff --git a/src/gui_egui/components/mips_jump_merge.rs b/src/gui_egui/components/mips_jump_merge.rs index 0fccb7c9..72ae28c9 100644 --- a/src/gui_egui/components/mips_jump_merge.rs +++ b/src/gui_egui/components/mips_jump_merge.rs @@ -7,7 +7,7 @@ use crate::gui_egui::component_ui::{ use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; -use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; +use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for JumpMerge { diff --git a/src/gui_egui/components/mips_reg_file.rs b/src/gui_egui/components/mips_reg_file.rs index b7089b43..10819d8c 100644 --- a/src/gui_egui/components/mips_reg_file.rs +++ b/src/gui_egui/components/mips_reg_file.rs @@ -7,7 +7,7 @@ use crate::gui_egui::component_ui::{ use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; -use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; +use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for RegFile { From 9e05022ab4ee495782bbff265344e00e1c5de57d Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Mon, 5 Aug 2024 16:19:24 +0200 Subject: [PATCH 030/126] updated autowire func and moved it to separete file --- examples/clk.rs | 103 +------------------------- examples/mips_controll_unit.rs | 41 ---------- examples/mips_instruction_splitter.rs | 41 ---------- examples/mips_jump_merge.rs | 41 ---------- examples/mips_reg_file.rs | 83 --------------------- src/lib.rs | 1 + src/mips_helper_functions.rs | 39 ++++++++++ 7 files changed, 43 insertions(+), 306 deletions(-) create mode 100644 src/mips_helper_functions.rs diff --git a/examples/clk.rs b/examples/clk.rs index 8001952c..15fafbd1 100644 --- a/examples/clk.rs +++ b/examples/clk.rs @@ -7,33 +7,19 @@ use syncrim::{ common::{ComponentStore, Input}, components::*, fern::fern_setup, + mips_helper_functions::autowire, }; fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - MIPSCLK::rc_new("clk", (200.0, 120.0), Input::new("reg2", "out")), + MIPSCLK::rc_new("clk", (200.0, 120.0), Input::new("reg", "out")), //Constant::rc_new("c1", (60.0, 100.0), 10), // ProbeEdit::rc_new("c1", (60.0, 100.0)), Register::rc_new("reg", (150.0, 250.0), Input::new("clk", "out")), - Register::rc_new("reg2", (250.0, 250.0), Input::new("reg", "out")), + //Register::rc_new("reg2", (250.0, 250.0), Input::new("reg", "reg_out")), // Probe::rc_new("p1", (270.0, 120.0), Input::new("clk", CLK_OUT_ID)), - // Wire::rc_new( - // "w2", - // vec![(200.0 - 50.0, 250.0), (200.0 - 50.0, 120.0)], - // Input::new("reg", "out"), - // ), - // Wire::rc_new( - // "w1", - // vec![(200.0, 120.0), (200.0, 250.0)], - // Input::new("clk", "out"), - // ), - // Wire::rc_new( - // "w2", - // vec![(220.0, 120.0), (260.0, 120.0)], - // Input::new("clk", CLK_OUT_ID), - // ), ], }; @@ -48,86 +34,3 @@ fn main() { #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); } - -fn autowire(mut cs: ComponentStore) -> ComponentStore { - let mut x = 1; - let mut tmp_vec: Vec> = vec![]; - - for c in &cs.store { - let (id, ports) = c.get_id_ports(); - println!("{}", id); - - let number_of_inputs = ports.inputs.len(); - - for n in 0..number_of_inputs { - println!("{:?}", ports.inputs[n].input.id); - println!("{:?}", ports); - - let id_tmp = format!("{id}_w{n}"); - //let pos_temp = vec![]; - let input = ports.inputs[n].input.clone(); - - let starting_pos = c.get_pos(); - - let mut destination_pos = (starting_pos.0 - 50.0, starting_pos.1); - - let default_input = Input::new(&format!("c{n}"), "out"); - let mut w = Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], default_input); - - for d in &cs.store { - let (id2, ports2) = d.get_id_ports(); - let input = Input::new(&id2, "out"); - if id2 == ports.inputs[n].input.id { - destination_pos = d.get_pos(); - w = Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], input.clone()); - } - } - tmp_vec.push(w); - - //TODO: get pos and set to destination, look through list of components a second time, then add that as starting pos. - - //println!("{}", id_tmp); - //let w = Wire::rc_new("w{}", pos, input) - } - - //cs_copy.store.push("wow"); - - // Wire::rc_new( - // "w4", - // vec![(220.0, 120.0), (260.0, 120.0)], - // Input::new("full_adder", FULL_ADD_OUT_ID), - // ), - - // Ports { - // inputs: [ - // InputPort { - // port_id: "full_add_a_in", - // input: Input { - // id: "c1", - // field: "out", - // }, - // }, - // InputPort { - // port_id: "full_add_b_in", - // input: Input { - // id: "c2", - // field: "out", - // }, - // }, - // InputPort { - // port_id: "full_add_op_in", - // input: Input { - // id: "c3", - // field: "out", - // }, - // }, - // ], - - // out_type: Combinatorial, - // outputs: ["out"], - // } - } - cs.store.append(&mut tmp_vec); - - return cs; -} diff --git a/examples/mips_controll_unit.rs b/examples/mips_controll_unit.rs index 6461e18f..5a381ca6 100644 --- a/examples/mips_controll_unit.rs +++ b/examples/mips_controll_unit.rs @@ -78,44 +78,3 @@ fn main() { #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); } - -fn autowire(mut cs: ComponentStore) -> ComponentStore { - let mut tmp_vec: Vec> = vec![]; - - // look through the list of components - for c in &cs.store { - let (id, ports) = c.get_id_ports(); - println!("{}", id); - - let number_of_inputs = ports.inputs.len(); - - for n in 0..number_of_inputs { - // println!("{:?}", ports.inputs[n].input.id); - // println!("{:?}", ports.inputs[n]); - - let id_tmp = format!("{id}_w{n}"); - let input = ports.inputs[n].input.clone(); - let starting_pos = c.get_pos(); - - // creates temporary vales to use when constatnt inputs are there for testing - let mut destination_pos = (starting_pos.0 - 50.0, starting_pos.1); - let default_input = Input::new(&ports.inputs[n].input.id, "out"); - - // look through the list again and act when you find a matching id - for d in &cs.store { - let (id2, ports2) = d.get_id_ports(); - // look if the id matches the one you are looking for - if id2 == ports.inputs[n].input.id { - // collect the components destination and use it to make a complete wire - destination_pos = d.get_pos(); - let w = - Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], input.clone()); - tmp_vec.push(w); - } - } - } - } - cs.store.append(&mut tmp_vec); - - return cs; -} diff --git a/examples/mips_instruction_splitter.rs b/examples/mips_instruction_splitter.rs index 2f9a3146..cbcb10e5 100644 --- a/examples/mips_instruction_splitter.rs +++ b/examples/mips_instruction_splitter.rs @@ -77,44 +77,3 @@ fn main() { #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); } - -fn autowire(mut cs: ComponentStore) -> ComponentStore { - let mut tmp_vec: Vec> = vec![]; - - // look through the list of components - for c in &cs.store { - let (id, ports) = c.get_id_ports(); - println!("{}", id); - - let number_of_inputs = ports.inputs.len(); - - for n in 0..number_of_inputs { - // println!("{:?}", ports.inputs[n].input.id); - // println!("{:?}", ports.inputs[n]); - - let id_tmp = format!("{id}_w{n}"); - let input = ports.inputs[n].input.clone(); - let starting_pos = c.get_pos(); - - // creates temporary vales to use when constatnt inputs are there for testing - let mut destination_pos = (starting_pos.0 - 50.0, starting_pos.1); - let default_input = Input::new(&ports.inputs[n].input.id, "out"); - - // look through the list again and act when you find a matching id - for d in &cs.store { - let (id2, ports2) = d.get_id_ports(); - // look if the id matches the one you are looking for - if id2 == ports.inputs[n].input.id { - // collect the components destination and use it to make a complete wire - destination_pos = d.get_pos(); - let w = - Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], input.clone()); - tmp_vec.push(w); - } - } - } - } - cs.store.append(&mut tmp_vec); - - return cs; -} diff --git a/examples/mips_jump_merge.rs b/examples/mips_jump_merge.rs index 4629677a..a12762c6 100644 --- a/examples/mips_jump_merge.rs +++ b/examples/mips_jump_merge.rs @@ -43,44 +43,3 @@ fn main() { #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); } - -fn autowire(mut cs: ComponentStore) -> ComponentStore { - let mut tmp_vec: Vec> = vec![]; - - // look through the list of components - for c in &cs.store { - let (id, ports) = c.get_id_ports(); - println!("{}", id); - - let number_of_inputs = ports.inputs.len(); - - for n in 0..number_of_inputs { - // println!("{:?}", ports.inputs[n].input.id); - // println!("{:?}", ports.inputs[n]); - - let id_tmp = format!("{id}_w{n}"); - let input = ports.inputs[n].input.clone(); - let starting_pos = c.get_pos(); - - // creates temporary vales to use when constatnt inputs are there for testing - let mut destination_pos = (starting_pos.0 - 50.0, starting_pos.1); - let default_input = Input::new(&ports.inputs[n].input.id, "out"); - - // look through the list again and act when you find a matching id - for d in &cs.store { - let (id2, ports2) = d.get_id_ports(); - // look if the id matches the one you are looking for - if id2 == ports.inputs[n].input.id { - // collect the components destination and use it to make a complete wire - destination_pos = d.get_pos(); - let w = - Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], input.clone()); - tmp_vec.push(w); - } - } - } - } - cs.store.append(&mut tmp_vec); - - return cs; -} diff --git a/examples/mips_reg_file.rs b/examples/mips_reg_file.rs index a8ba9954..42380e78 100644 --- a/examples/mips_reg_file.rs +++ b/examples/mips_reg_file.rs @@ -52,86 +52,3 @@ fn main() { #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); } - -fn autowire(mut cs: ComponentStore) -> ComponentStore { - let mut x = 1; - let mut tmp_vec: Vec> = vec![]; - - for c in &cs.store { - let (id, ports) = c.get_id_ports(); - println!("{}", id); - - let number_of_inputs = ports.inputs.len(); - - for n in 0..number_of_inputs { - println!("{:?}", ports.inputs[n].input.id); - println!("{:?}", ports); - - let id_tmp = format!("{id}_w{n}"); - //let pos_temp = vec![]; - let input = ports.inputs[n].input.clone(); - - let starting_pos = c.get_pos(); - - let mut destination_pos = (starting_pos.0 - 50.0, starting_pos.1); - - let default_input = Input::new(&format!("c{n}"), "out"); - let mut w = Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], default_input); - - for d in &cs.store { - let (id2, ports2) = d.get_id_ports(); - let input = Input::new(&id2, "out"); - if id2 == ports.inputs[n].input.id { - destination_pos = d.get_pos(); - w = Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], input.clone()); - } - } - tmp_vec.push(w); - - //TODO: get pos and set to destination, look through list of components a second time, then add that as starting pos. - - //println!("{}", id_tmp); - //let w = Wire::rc_new("w{}", pos, input) - } - - //cs_copy.store.push("wow"); - - // Wire::rc_new( - // "w4", - // vec![(220.0, 120.0), (260.0, 120.0)], - // Input::new("full_adder", FULL_ADD_OUT_ID), - // ), - - // Ports { - // inputs: [ - // InputPort { - // port_id: "full_add_a_in", - // input: Input { - // id: "c1", - // field: "out", - // }, - // }, - // InputPort { - // port_id: "full_add_b_in", - // input: Input { - // id: "c2", - // field: "out", - // }, - // }, - // InputPort { - // port_id: "full_add_op_in", - // input: Input { - // id: "c3", - // field: "out", - // }, - // }, - // ], - - // out_type: Combinatorial, - // outputs: ["out"], - // } - } - cs.store.append(&mut tmp_vec); - - return cs; -} diff --git a/src/lib.rs b/src/lib.rs index 1578e478..74a9fa91 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ pub mod common; pub mod component_store; pub mod fern; +pub mod mips_helper_functions; pub mod signal; pub mod simulator; diff --git a/src/mips_helper_functions.rs b/src/mips_helper_functions.rs new file mode 100644 index 00000000..e1899329 --- /dev/null +++ b/src/mips_helper_functions.rs @@ -0,0 +1,39 @@ +use std::rc::Rc; + +use crate::common::{ComponentStore, EguiComponent}; +use crate::components::Wire; + +pub fn autowire(mut cs: ComponentStore) -> ComponentStore { + let mut wires: Vec> = vec![]; + + // for each component + for destination_component in &cs.store { + let dest_comp_id = destination_component.get_id_ports().0; + // for each port in destination component + for input_port in destination_component.get_id_ports().1.inputs.iter() { + let source_port = &input_port.input; + let dest_comp_field = &input_port.port_id; + + // find component with correct source id + let source_component = cs + .store + .iter() + .filter(|comp| comp.get_id_ports().0 == source_port.id) // compare id + .next() + .unwrap(); + + // create wire with correct source destination and positions + let s_id = &source_port.id; + let s_field = &source_port.field; + let d_id = &dest_comp_id; + let d_field = &dest_comp_field; + wires.push(Wire::rc_new( + &format!("from {}:{} to {}:{}", s_id, s_field, d_id, d_field), + vec![source_component.get_pos(), destination_component.get_pos()], + source_port.clone(), + )) + } + } + cs.store.append(&mut wires); + return cs; +} From 7f8810e58f86a3cf101e99b4bfb778a139c4f03e Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Mon, 5 Aug 2024 17:25:17 +0200 Subject: [PATCH 031/126] started working first mips version --- examples/mips_example_1.rs | 67 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 examples/mips_example_1.rs diff --git a/examples/mips_example_1.rs b/examples/mips_example_1.rs new file mode 100644 index 00000000..00ba472f --- /dev/null +++ b/examples/mips_example_1.rs @@ -0,0 +1,67 @@ +use std::path::PathBuf; +use std::rc::Rc; +use syncrim::common::EguiComponent; +#[cfg(feature = "gui-egui")] +use syncrim::gui_egui::editor::Library; +use syncrim::{ + common::{ComponentStore, Input}, + components::*, + fern::fern_setup, + mips_helper_functions::autowire, +}; + +fn main() { + fern_setup(); + let cs = ComponentStore { + store: vec![ + ProbeEdit::rc_new("c0", (50.0, 100.0)), + // register that holds instr addr + Register::rc_new("reg", (150.0, 100.0), Input::new("c0", "out")), + // step addr from reg by 4 + Constant::rc_new("+4", (200.0, 150.0), 4), + Add::rc_new( + "pc+4", + (250.0, 100.0), + Input::new("reg", "out"), + Input::new("+4", "out"), + ), + // + // + ProbeEdit::rc_new("ctrl", (200.0, 250.0)), + // MUX to choose what intruction addr to choose from, branch jump, reg, pc+4 + Mux::rc_new( + "mux", + (200.0, 200.0), + Input::new("ctrl", "out"), + vec![ + // Input::new("clk", CLK_OUT_ID), + //Input::new("c2", "out"), + Input::new("jump_merge", MERGE_OUT_ID), + Input::new("pc+4", CLK_OUT_ID), + ], + ), // + // + // merges to find out jump location + Constant::rc_new("c1", (100.0, 350.0), 0), + JumpMerge::rc_new( + "jump_merge", + (100.0, 300.0), + Input::new("reg", "out"), //input from reg before pc+4 + Input::new("c1", "out"), //input from instruction mem + ), + // + // + ], + }; + + let cs = autowire(cs); + + let path = PathBuf::from("add.json"); + cs.save_file(&path); + + #[cfg(feature = "gui-egui")] + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + + #[cfg(feature = "gui-vizia")] + syncrim::gui_vizia::gui(cs, &path); +} From 3bd4b3780c935827d74ad3e51449f62318c2e4d1 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Mon, 5 Aug 2024 17:26:51 +0200 Subject: [PATCH 032/126] changed code to provide error message --- src/mips_helper_functions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mips_helper_functions.rs b/src/mips_helper_functions.rs index e1899329..1125512e 100644 --- a/src/mips_helper_functions.rs +++ b/src/mips_helper_functions.rs @@ -20,7 +20,7 @@ pub fn autowire(mut cs: ComponentStore) -> ComponentStore { .iter() .filter(|comp| comp.get_id_ports().0 == source_port.id) // compare id .next() - .unwrap(); + .expect(&format!("can't find comonent with id {}", source_port.id)); // create wire with correct source destination and positions let s_id = &source_port.id; From 2b3ba5bc853503dfd0b4333026e621c33e62bb78 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Mon, 5 Aug 2024 17:27:31 +0200 Subject: [PATCH 033/126] changed names of labels etc --- src/components/mips_jump_merge.rs | 2 +- src/gui_egui/components/mips_jump_merge.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/mips_jump_merge.rs b/src/components/mips_jump_merge.rs index 4ba06023..f35f1606 100644 --- a/src/components/mips_jump_merge.rs +++ b/src/components/mips_jump_merge.rs @@ -25,7 +25,7 @@ pub struct JumpMerge { #[typetag::serde] impl Component for JumpMerge { fn to_(&self) { - trace!("merge"); + trace!("jump_merge"); } // #[cfg(feature = "gui-egui")] // fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { diff --git a/src/gui_egui/components/mips_jump_merge.rs b/src/gui_egui/components/mips_jump_merge.rs index 72ae28c9..b04532e7 100644 --- a/src/gui_egui/components/mips_jump_merge.rs +++ b/src/gui_egui/components/mips_jump_merge.rs @@ -71,7 +71,7 @@ impl EguiComponent for JumpMerge { } format!("{}", s) }); - ui.label("Merge"); + ui.label("jump_merge"); } }); match editor_mode { From 70605d5646534a7e8d631a8395441e71e98559fe Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:47:31 +0200 Subject: [PATCH 034/126] add component to sing/zero extend depending on ctrl --- src/components/mod.rs | 2 + src/components/sz_extend.rs | 125 +++++++++++++++++++ src/gui_egui/components/mod.rs | 1 + src/gui_egui/components/sz_extend.rs | 174 +++++++++++++++++++++++++++ 4 files changed, 302 insertions(+) create mode 100644 src/components/sz_extend.rs create mode 100644 src/gui_egui/components/sz_extend.rs diff --git a/src/components/mod.rs b/src/components/mod.rs index 85a46341..09de55f7 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -18,6 +18,7 @@ mod probe_out; mod probe_stim; mod register; mod sext; +mod sz_extend; mod wire; pub use add::*; @@ -40,4 +41,5 @@ pub use probe_out::*; pub use probe_stim::*; pub use register::*; pub use sext::*; +pub use sz_extend::*; pub use wire::*; diff --git a/src/components/sz_extend.rs b/src/components/sz_extend.rs new file mode 100644 index 00000000..400b0e6b --- /dev/null +++ b/src/components/sz_extend.rs @@ -0,0 +1,125 @@ +// use std::fmt::Alignment; +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, +}; +use crate::components::cntr_unit_signals; +use crate::signal; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::rc::Rc; + +pub const SIGNZEROEXTEND_SIGNAL_IN_ID: &str = "signzero_signal_in"; +pub const SIGNZEROEXTEND_CTRL_IN_ID: &str = "signzero_ctrl_in"; + +pub const SIGNZEROEXTEND_OUT_ID: &str = "out"; + +#[derive(Serialize, Deserialize, Clone)] +pub struct SignZeroExtend { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) signzero_signal_in: Input, + pub(crate) signzero_ctrl_in: Input, +} + +#[typetag::serde] +impl Component for SignZeroExtend { + fn to_(&self) { + trace!("pc+4"); + } + #[cfg(feature = "gui-egui")] + // fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { + // let dummy_input = Input::new("dummy", "out"); + // Box::new(Rc::new(SignZeroExtend { + // id: "dummy".to_string(), + // pos: (0.0, 0.0), + // signzero_extend_in: dummy_input.clone(), + // })) + // } + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![ + &InputPort { + port_id: SIGNZEROEXTEND_SIGNAL_IN_ID.to_string(), + input: self.signzero_signal_in.clone(), + } & InputPort { + port_id: SIGNZEROEXTEND_CTRL_IN_ID.to_string(), + input: self.signzero_ctrl_in.clone(), + }, + ], + OutputType::Combinatorial, + vec![SIGNZEROEXTEND_OUT_ID], + ), + ) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + SIGNZEROEXTEND_SIGNAL_IN_ID => self.signzero_signal_in = new_input, + SIGNZEROEXTEND_CTRL_IN_ID => self.signzero_ctrl_in = new_input, + _ => {} + } + } + + // propagate sign extension to output + // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get input values + let mut signal: u32 = simulator + .get_input_value(&self.signzero_signal_in) + .try_into() + .unwrap(); + + let ctrl: u32 = simulator + .get_input_value(&self.signzero_ctrl_in) + .try_into() + .unwrap(); + + if ctrl == cntr_unit_signals::EXTEND_SIGNED { + if (signal >> 15) == 1 { + signal = signal | 0xffff_0000; + } + } + + simulator.set_out_value(&self.id, SIGNZEROEXTEND_OUT_ID, SignalValue::Data(signal)); + Ok(()) + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl SignZeroExtend { + pub fn new( + id: &str, + pos: (f32, f32), + signzero_signal_in: Input, + signzero_ctrl_in: Input, + ) -> Self { + SignZeroExtend { + id: id.to_string(), + pos, + signzero_signal_in, + signzero_ctrl_in, + } + } + + pub fn rc_new( + id: &str, + pos: (f32, f32), + signzero_signal_in: Input, + signzero_ctrl_in: Input, + ) -> Rc { + Rc::new(SignZeroExtend::new( + id, + pos, + signzero_signal_in, + signzero_ctrl_in, + )) + } +} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index d053676a..a88d37e1 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -17,4 +17,5 @@ mod probe_out; mod probe_stim; mod register; mod sext; +mod sz_extend; mod wire; diff --git a/src/gui_egui/components/sz_extend.rs b/src/gui_egui/components/sz_extend.rs new file mode 100644 index 00000000..c2d6cb8d --- /dev/null +++ b/src/gui_egui/components/sz_extend.rs @@ -0,0 +1,174 @@ +use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::components::{InstrSplit, SignZeroExtend}; +use crate::gui_egui::component_ui::{ + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::offset_helper; +use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; + +#[typetag::serde] +impl EguiComponent for SignZeroExtend { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + // 81x41 + // middle: 41x 21y (0 0) + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + // The shape + ui.painter().add(Shape::closed_line( + vec![ + oh((-40f32, 0f32), s, o), + oh((40f32, 0f32), s, o), + oh((40f32, 20f32), s, o), + oh((-40f32, 20f32), s, o), + ], + Stroke { + width: scale, + color: Color32::RED, + }, + )); + + let rect = Rect { + min: oh((-40f32, -20f32), s, o), + max: oh((40f32, 20f32), s, o), + }; + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + // todo: is this actually correct? + if let Some(s) = &simulator { + ui.label({ + let a_r: Result = + s.get_input_value(&self.signzero_ctrl_in).try_into(); + let mut s: String = "".to_string(); + let b_r: Result = + s.get_input_value(&self.signzero_signal_in).try_into(); + let mut s: String = "".to_string(); + + match a_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", a_r), + } + match b_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", b_r), + } + format!("{}", s) + }); + ui.label("signzero_extend"); + } + }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let r_vec = InstrSplit::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_drag_value(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.signzero_signal_in, + crate::components::SIGNZEROEXTEND_SIGNAL_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.signzero_ctrl_in, + crate::components::SIGNZEROEXTEND_CTRL_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown + }, + ); + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + crate::components::SEXT_IN_ID.to_string(), + Pos2::new(-40f32, 0f32) + own_pos, + ), + ( + crate::components::SEXT_OUT_ID.to_string(), + Pos2::new(40f32, 0f32) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + 20f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } +} From f816a8b7385a5256a161e7e5a9c4f645fcd26f18 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:50:10 +0200 Subject: [PATCH 035/126] fixed code errors --- src/gui_egui/components/sz_extend.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gui_egui/components/sz_extend.rs b/src/gui_egui/components/sz_extend.rs index c2d6cb8d..31abcca1 100644 --- a/src/gui_egui/components/sz_extend.rs +++ b/src/gui_egui/components/sz_extend.rs @@ -1,5 +1,5 @@ use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; -use crate::components::{InstrSplit, SignZeroExtend}; +use crate::components::SignZeroExtend; use crate::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, visualize_ports, @@ -55,7 +55,6 @@ impl EguiComponent for SignZeroExtend { ui.label({ let a_r: Result = s.get_input_value(&self.signzero_ctrl_in).try_into(); - let mut s: String = "".to_string(); let b_r: Result = s.get_input_value(&self.signzero_signal_in).try_into(); let mut s: String = "".to_string(); @@ -92,7 +91,7 @@ impl EguiComponent for SignZeroExtend { grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { - let r_vec = InstrSplit::render( + let r_vec = SignZeroExtend::render( self, ui, context, From 11d9e7f025f4f2bc2532b35c0f55473579ca17ab Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Wed, 7 Aug 2024 13:25:31 +0200 Subject: [PATCH 036/126] made component and --- src/components/and.rs | 97 ++++++++++++++++++ src/components/mod.rs | 2 + src/gui_egui/components/and.rs | 175 +++++++++++++++++++++++++++++++++ src/gui_egui/components/mod.rs | 1 + 4 files changed, 275 insertions(+) create mode 100644 src/components/and.rs create mode 100644 src/gui_egui/components/and.rs diff --git a/src/components/and.rs b/src/components/and.rs new file mode 100644 index 00000000..dae2cd1f --- /dev/null +++ b/src/components/and.rs @@ -0,0 +1,97 @@ +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, + SignalValue, Simulator, +}; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::rc::Rc; +pub const AND_A_IN_ID: &str = "a_in"; +pub const AND_B_IN_ID: &str = "b_in"; + +pub const AND_OUT_ID: &str = "out"; + +#[derive(Serialize, Deserialize, Clone)] +pub struct And { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) a_in: Input, + pub(crate) b_in: Input, +} + +#[typetag::serde] +impl Component for And { + fn to_(&self) { + trace!("And"); + } + #[cfg(feature = "gui-egui")] + fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + let dummy_input = Input::new("dummy", "out"); + Box::new(Rc::new(And { + id: id.to_string(), + pos: (pos.0, pos.1), + a_in: dummy_input.clone(), + b_in: dummy_input.clone(), + })) + } + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![ + &InputPort { + port_id: AND_A_IN_ID.to_string(), + input: self.a_in.clone(), + }, + &InputPort { + port_id: AND_B_IN_ID.to_string(), + input: self.b_in.clone(), + }, + ], + OutputType::Combinatorial, + vec![AND_OUT_ID], + ), + ) + } + + // propagate addition to output + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get input values + let a_in: u32 = simulator.get_input_value(&self.a_in).try_into().unwrap(); + let b_in: u32 = simulator.get_input_value(&self.b_in).try_into().unwrap(); + + let result: u32 = a_in & b_in; + + simulator.set_out_value(&self.id, AND_OUT_ID, SignalValue::Data(result)); + Ok(()) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + AND_A_IN_ID => self.a_in = new_input, + AND_B_IN_ID => self.b_in = new_input, + _ => (), + } + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl And { + pub fn new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input) -> Self { + And { + id: id.to_string(), + pos, + a_in, + b_in, + } + } + + pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input) -> Rc { + Rc::new(And::new(id, pos, a_in, b_in)) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index 09de55f7..523f94c0 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,4 +1,5 @@ mod add; +mod and; mod clk; mod constant; mod cross; @@ -22,6 +23,7 @@ mod sz_extend; mod wire; pub use add::*; +pub use and::*; pub use clk::*; pub use constant::*; pub use cross::*; diff --git a/src/gui_egui/components/and.rs b/src/gui_egui/components/and.rs new file mode 100644 index 00000000..8137fbe6 --- /dev/null +++ b/src/gui_egui/components/and.rs @@ -0,0 +1,175 @@ +use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::components::And; +use crate::gui_egui::component_ui::{ + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::offset_helper; +use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; + +#[typetag::serde] +impl EguiComponent for And { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + // 81x41 + // middle: 41x 21y (0 0) + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + // The shape + ui.painter().add(Shape::closed_line( + vec![ + oh((-40f32, 0f32), s, o), + oh((40f32, 0f32), s, o), + oh((40f32, 20f32), s, o), + oh((-40f32, 20f32), s, o), + ], + Stroke { + width: scale, + color: Color32::RED, + }, + )); + + let rect = Rect { + min: oh((-40f32, -20f32), s, o), + max: oh((40f32, 20f32), s, o), + }; + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + // todo: is this actually correct? + if let Some(s) = &simulator { + ui.label({ + let a_r: Result = + s.get_input_value(&self.a_in).try_into(); + + let b_r: Result = + s.get_input_value(&self.b_in).try_into(); + + let mut s: String = "".to_string(); + + match a_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", a_r), + } + match b_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", b_r), + } + format!("{}", s) + }); + ui.label("and"); + } + }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let r_vec = And::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_drag_value(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.a_in, + crate::components::AND_A_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.b_in, + crate::components::AND_B_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown + }, + ); + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + crate::components::SEXT_IN_ID.to_string(), + Pos2::new(-40f32, 0f32) + own_pos, + ), + ( + crate::components::SEXT_OUT_ID.to_string(), + Pos2::new(40f32, 0f32) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + 20f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } +} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index a88d37e1..cbe9cb63 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -1,4 +1,5 @@ mod add; +mod and; mod clk; mod constant; mod cross; From fc981e3e593727d23a10de3f9b59a80e86fac6b9 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Wed, 7 Aug 2024 13:29:58 +0200 Subject: [PATCH 037/126] fixed warining --- src/components/clk.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/clk.rs b/src/components/clk.rs index 13619988..a0ae9f71 100644 --- a/src/components/clk.rs +++ b/src/components/clk.rs @@ -50,7 +50,7 @@ impl Component for MIPSCLK { fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { match target_port_id.as_str() { - CLK_A_IN_ID => self.clk_in = new_input, + CLK_IN_ID => self.clk_in = new_input, _ => {} } } From 3755fe0d614cdf3e9c5c2ca9b17cfdf3f3f215c5 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Wed, 7 Aug 2024 13:55:33 +0200 Subject: [PATCH 038/126] added component to shift left by a const --- src/components/mod.rs | 2 + src/components/shift_left_const.rs | 93 ++++++++++++ src/components/sz_extend.rs | 3 +- src/gui_egui/components/mod.rs | 1 + src/gui_egui/components/shift_left_const.rs | 160 ++++++++++++++++++++ 5 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 src/components/shift_left_const.rs create mode 100644 src/gui_egui/components/shift_left_const.rs diff --git a/src/components/mod.rs b/src/components/mod.rs index 523f94c0..2620d448 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -19,6 +19,7 @@ mod probe_out; mod probe_stim; mod register; mod sext; +mod shift_left_const; mod sz_extend; mod wire; @@ -43,5 +44,6 @@ pub use probe_out::*; pub use probe_stim::*; pub use register::*; pub use sext::*; +pub use shift_left_const::*; pub use sz_extend::*; pub use wire::*; diff --git a/src/components/shift_left_const.rs b/src/components/shift_left_const.rs new file mode 100644 index 00000000..153bcf41 --- /dev/null +++ b/src/components/shift_left_const.rs @@ -0,0 +1,93 @@ +// use std::fmt::Alignment; +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, +}; +use crate::signal; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::rc::Rc; + +pub const SHIFT_SIGNAL_IN_ID: &str = "shift_in"; + +pub const SHIFT_OUT_ID: &str = "out"; + +#[derive(Serialize, Deserialize, Clone)] +pub struct ShiftConst { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) signal_in: Input, + shift_by: u32, +} + +#[typetag::serde] +impl Component for ShiftConst { + fn to_(&self) { + trace!("shift"); + } + #[cfg(feature = "gui-egui")] + fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { + let dummy_input = Input::new("dummy", "out"); + Box::new(Rc::new(ShiftConst { + id: "dummy".to_string(), + pos: (0.0, 0.0), + signal_in: dummy_input.clone(), + shift_by: 0, + })) + } + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![&InputPort { + port_id: SHIFT_SIGNAL_IN_ID.to_string(), + input: self.signal_in.clone(), + }], + OutputType::Combinatorial, + vec![SHIFT_OUT_ID], + ), + ) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + SHIFT_SIGNAL_IN_ID => self.signal_in = new_input, + _ => {} + } + } + + // propagate sign extension to output + // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get input values + let signal_in: u32 = simulator + .get_input_value(&self.signal_in) + .try_into() + .unwrap(); + + let output: u32 = signal_in << self.shift_by; + simulator.set_out_value(&self.id, SHIFT_OUT_ID, SignalValue::Data(output)); + Ok(()) + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl ShiftConst { + pub fn new(id: &str, pos: (f32, f32), signal_in: Input, shift_by: u32) -> Self { + ShiftConst { + id: id.to_string(), + pos, + signal_in, + shift_by, + } + } + + pub fn rc_new(id: &str, pos: (f32, f32), signal_in: Input, shift_by: u32) -> Rc { + Rc::new(ShiftConst::new(id, pos, signal_in, shift_by)) + } +} diff --git a/src/components/sz_extend.rs b/src/components/sz_extend.rs index 400b0e6b..6b4b58bc 100644 --- a/src/components/sz_extend.rs +++ b/src/components/sz_extend.rs @@ -46,7 +46,8 @@ impl Component for SignZeroExtend { &InputPort { port_id: SIGNZEROEXTEND_SIGNAL_IN_ID.to_string(), input: self.signzero_signal_in.clone(), - } & InputPort { + }, + &InputPort { port_id: SIGNZEROEXTEND_CTRL_IN_ID.to_string(), input: self.signzero_ctrl_in.clone(), }, diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index cbe9cb63..9615df16 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -18,5 +18,6 @@ mod probe_out; mod probe_stim; mod register; mod sext; +mod shift_left_const; mod sz_extend; mod wire; diff --git a/src/gui_egui/components/shift_left_const.rs b/src/gui_egui/components/shift_left_const.rs new file mode 100644 index 00000000..939646bd --- /dev/null +++ b/src/gui_egui/components/shift_left_const.rs @@ -0,0 +1,160 @@ +use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::components::ShiftConst; +use crate::gui_egui::component_ui::{ + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::offset_helper; +use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; + +#[typetag::serde] +impl EguiComponent for ShiftConst { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + // 81x41 + // middle: 41x 21y (0 0) + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + // The shape + ui.painter().add(Shape::closed_line( + vec![ + oh((-40f32, 0f32), s, o), + oh((40f32, 0f32), s, o), + oh((40f32, 20f32), s, o), + oh((-40f32, 20f32), s, o), + ], + Stroke { + width: scale, + color: Color32::RED, + }, + )); + + let rect = Rect { + min: oh((-40f32, -20f32), s, o), + max: oh((40f32, 20f32), s, o), + }; + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + // todo: is this actually correct? + if let Some(s) = &simulator { + ui.label({ + let a_r: Result = + s.get_input_value(&self.signal_in).try_into(); + let mut s: String = "".to_string(); + + match a_r { + Ok(data) => s += &format!("{:#x}", data), + _ => s += &format!("{:?}", a_r), + } + format!("{}", s) + }); + ui.label("shift_left"); + } + }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let r_vec = ShiftConst::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_drag_value(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.signal_in, + crate::components::SHIFT_SIGNAL_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown + }, + ); + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + crate::components::SEXT_IN_ID.to_string(), + Pos2::new(-40f32, 0f32) + own_pos, + ), + ( + crate::components::SEXT_OUT_ID.to_string(), + Pos2::new(40f32, 0f32) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + 20f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } +} From a05e8a4a9a40905c38fbeb15b43c6b2203480671 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 7 Aug 2024 14:16:52 +0200 Subject: [PATCH 039/126] Updated mips regfile with new internals and added UI --- examples/mips_reg_file.rs | 141 +++----- src/components/mips_reg_file.rs | 406 +++++++---------------- src/gui_egui/components/mips_reg_file.rs | 246 ++++++-------- src/gui_egui/helper.rs | 21 +- 4 files changed, 288 insertions(+), 526 deletions(-) diff --git a/examples/mips_reg_file.rs b/examples/mips_reg_file.rs index a8ba9954..417cd620 100644 --- a/examples/mips_reg_file.rs +++ b/examples/mips_reg_file.rs @@ -13,35 +13,34 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ + ProbeEdit::rc_new("rs_addr", (60.0, 100.0)), + ProbeEdit::rc_new("rt_addr", (60.0, 140.0)), + ProbeEdit::rc_new("write_addr", (60.0, 180.0)), + ProbeEdit::rc_new("write_data", (60.0, 220.0)), + ProbeEdit::rc_new("write_enable", (60.0, 260.0)), RegFile::rc_new( "reg_file", (200.0, 200.0), - Input::new("c0", "out"), - Input::new("c1", "out"), - Input::new("c2", "out"), - Input::new("c3", "out"), - Input::new("c4", "out"), - true, + Input::new("rs_addr", "out"), + Input::new("rt_addr", "out"), + Input::new("write_addr", "out"), + Input::new("write_data", "out"), + Input::new("write_enable", "out"), ), - ProbeEdit::rc_new("c0", (60.0, 100.0)), - ProbeEdit::rc_new("c1", (60.0, 140.0)), - ProbeEdit::rc_new("c2", (60.0, 160.0)), - ProbeEdit::rc_new("c3", (60.0, 200.0)), - ProbeEdit::rc_new("c4", (60.0, 240.0)), Probe::rc_new( - "p1", - (270.0, 120.0), - Input::new("reg_file", REG_FILE_RD1_OUT_ID), + "rs", + (300.0, 120.0), + Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), ), Probe::rc_new( - "p2", - (270.0, 160.0), - Input::new("reg_file", REG_FILE_RD2_OUT_ID), + "rt", + (300.0, 160.0), + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), ), ], }; - let cs = autowire(cs); + // let cs = autowire(cs); let path = PathBuf::from("add.json"); cs.save_file(&path); @@ -54,84 +53,36 @@ fn main() { } fn autowire(mut cs: ComponentStore) -> ComponentStore { - let mut x = 1; - let mut tmp_vec: Vec> = vec![]; - - for c in &cs.store { - let (id, ports) = c.get_id_ports(); - println!("{}", id); - - let number_of_inputs = ports.inputs.len(); - - for n in 0..number_of_inputs { - println!("{:?}", ports.inputs[n].input.id); - println!("{:?}", ports); - - let id_tmp = format!("{id}_w{n}"); - //let pos_temp = vec![]; - let input = ports.inputs[n].input.clone(); - - let starting_pos = c.get_pos(); - - let mut destination_pos = (starting_pos.0 - 50.0, starting_pos.1); - - let default_input = Input::new(&format!("c{n}"), "out"); - let mut w = Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], default_input); - - for d in &cs.store { - let (id2, ports2) = d.get_id_ports(); - let input = Input::new(&id2, "out"); - if id2 == ports.inputs[n].input.id { - destination_pos = d.get_pos(); - w = Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], input.clone()); - } - } - tmp_vec.push(w); - - //TODO: get pos and set to destination, look through list of components a second time, then add that as starting pos. - - //println!("{}", id_tmp); - //let w = Wire::rc_new("w{}", pos, input) + let mut wires: Vec> = vec![]; + + // for each component + for destination_component in &cs.store { + let dest_comp_id = destination_component.get_id_ports().0; + // for each port in destination component + for input_port in destination_component.get_id_ports().1.inputs.iter() { + let source_port = &input_port.input; + let dest_port_id = &input_port.port_id; + + // find component with correct source id + let source_component = cs + .store + .iter() + .filter(|comp| comp.get_id_ports().0 == source_port.id) // compare id + .next() + .unwrap(); + + // create wire with correct source destination and positions + let s_id = &source_port.id; + let s_field = &source_port.field; + let d_id = &dest_comp_id; + let d_field = &dest_port_id; + wires.push(Wire::rc_new( + &format!("from_{}:{}_to_{}:{}", s_id, s_field, d_id, d_field), + vec![source_component.get_pos(), destination_component.get_pos()], + source_port.clone(), + )) } - - //cs_copy.store.push("wow"); - - // Wire::rc_new( - // "w4", - // vec![(220.0, 120.0), (260.0, 120.0)], - // Input::new("full_adder", FULL_ADD_OUT_ID), - // ), - - // Ports { - // inputs: [ - // InputPort { - // port_id: "full_add_a_in", - // input: Input { - // id: "c1", - // field: "out", - // }, - // }, - // InputPort { - // port_id: "full_add_b_in", - // input: Input { - // id: "c2", - // field: "out", - // }, - // }, - // InputPort { - // port_id: "full_add_op_in", - // input: Input { - // id: "c3", - // field: "out", - // }, - // }, - // ], - - // out_type: Combinatorial, - // outputs: ["out"], - // } } - cs.store.append(&mut tmp_vec); - + cs.store.append(&mut wires); return cs; } diff --git a/src/components/mips_reg_file.rs b/src/components/mips_reg_file.rs index ec8313ed..45ffb152 100644 --- a/src/components/mips_reg_file.rs +++ b/src/components/mips_reg_file.rs @@ -13,182 +13,54 @@ use std::collections::BTreeMap; use std::ops::Deref; use std::rc::Rc; -pub const REG_FILE_A1_IN_ID: &str = "reg_file_a1_in"; -pub const REG_FILE_A2_IN_ID: &str = "reg_file_a2_in"; -pub const REG_FILE_A3_IN_ID: &str = "reg_file_a3_in"; -pub const REG_FILE_WD3_IN_ID: &str = "reg_file_wd3_in"; -pub const REG_FILE_WE3_IN_ID: &str = "reg_file_we3_in"; - -pub const REG_FILE_RD1_OUT_ID: &str = "rd1_out"; -pub const REG_FILE_RD2_OUT_ID: &str = "rd2_out"; +pub mod reg_file_fields { + pub const RS_ADDRESS_IN_ID: &str = "rs_address_in"; + pub const RT_ADDRESS_IN_ID: &str = "rt_address_in"; + pub const WRITE_ADDRESS_IN_ID: &str = "write_address_in"; + pub const WRITE_DATA_IN_ID: &str = "write_data_in"; + pub const WRITE_ENABLE_IN_ID: &str = "write_enable_in"; + + pub const RT_VALUE_OUT_ID: &str = "rt_value_out"; + pub const RS_VALUE_OUT_ID: &str = "rs_value_out"; +} #[derive(Serialize, Deserialize, Clone)] pub struct RegFile { pub(crate) id: Id, pub(crate) pos: (f32, f32), - pub(crate) a1_in: Input, - pub(crate) a2_in: Input, - pub(crate) a3_in: Input, - pub(crate) wd3_in: Input, - pub(crate) we3_in: Input, - - pub big_endian: bool, + pub(crate) rs_address_in: Input, + pub(crate) rt_address_in: Input, + pub(crate) write_address_in: Input, + pub(crate) write_data_in: Input, + pub(crate) write_enable_in: Input, #[serde(skip)] - pub memory: Memory, - history: RefCell>, + pub registers: RefCell<[u32; 32]>, // all 32 registers, in future, we might save the whole signal #[serde(skip)] - pub init_state: BTreeMap, -} - -#[derive(Serialize, Deserialize, Clone)] -struct MemOp { - pub data: Option, - pub addr: usize, - pub size: u8, -} + history: RefCell>, // contains the value before it was modified used for unclock. -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct Memory(pub Rc>>); + //used for gui + #[serde(skip)] + pub show_reg_names: RefCell, -impl Default for Memory { - fn default() -> Self { - Self::new(BTreeMap::new()) - } + #[serde(skip)] + pub reg_format: RefCell, +} +#[derive(Clone, Default, PartialEq, PartialOrd, Debug)] +pub enum RegFormat { + #[default] + Hex, + Bin, + DecSigned, + DecUnsigned, + UTF8BE, + UTF8LE, } -impl Memory { - pub fn new(data: BTreeMap) -> Self { - Memory(Rc::new(RefCell::new(data))) - } - - fn align(&self, addr: usize, size: usize) -> SignalValue { - ((addr % size != 0) as SignalUnsigned).into() - } - - pub fn read(&self, addr: usize, size: usize, sign: bool, big_endian: bool) -> SignalValue { - let data: Vec = (0..size) - .map(|i| *self.0.borrow().get(&(addr + i)).unwrap_or(&0)) - .collect(); - - let data = data.as_slice(); - - //trace!("{:x?}", data); - - match size { - 1 => { - if sign { - data[0] as i8 as SignalSigned as SignalUnsigned - } else { - data[0] as SignalUnsigned - } - } - 2 => { - if sign { - if big_endian { - trace!("read signed half word be"); - let i_16 = i16::from_be_bytes(data.try_into().unwrap()); - trace!("i_16 {:x?}", i_16); - let i_32 = i_16 as i32; - trace!("i_32 {:x?}", i_32); - i_32 as SignalUnsigned - } else { - trace!("read signed half word le"); - let i_16 = i16::from_le_bytes(data.try_into().unwrap()); - trace!("i_16 {:x?}", i_16); - let i_32 = i_16 as i32; - trace!("i_32 {:x?}", i_32); - i_32 as SignalUnsigned - } - } else if big_endian { - trace!("read unsigned half word be"); - let u_16 = u16::from_be_bytes(data.try_into().unwrap()); - trace!("u_16 {:x?}", u_16); - let u_32 = u_16 as u32; - trace!("u_32 {:x?}", u_32); - u_32 as SignalUnsigned - } else { - trace!("read unsigned half word le"); - let u_16 = u16::from_le_bytes(data.try_into().unwrap()); - trace!("u_16 {:x?}", u_16); - let u_32 = u_16 as u32; - trace!("u_32 {:x?}", u_32); - u_32 as SignalUnsigned - } - } - 4 => { - if sign { - if big_endian { - i32::from_be_bytes(data.try_into().unwrap()) as SignalUnsigned - } else { - i32::from_le_bytes(data.try_into().unwrap()) as SignalUnsigned - } - } else if big_endian { - u32::from_be_bytes(data.try_into().unwrap()) as SignalUnsigned - } else { - u32::from_le_bytes(data.try_into().unwrap()) as SignalUnsigned - } - } - _ => panic!("illegal sized memory operation"), - } - .into() - } - - pub fn write(&self, addr: usize, size: usize, big_endian: bool, data: SignalValue) { - let data: SignalUnsigned = data.try_into().unwrap(); - trace!("we = 1, now writing {:?} at addr {:?}", data, addr); - - match size { - 1 => { - trace!("write byte"); - self.0.borrow_mut().insert(addr, data as u8); - } - 2 => { - if big_endian { - trace!("write half word be"); - (data as u16) - .to_be_bytes() - .iter() - .enumerate() - .for_each(|(i, bytes)| { - self.0.borrow_mut().insert(addr + i, *bytes); - }) - } else { - trace!("write half word le"); - (data as u16) - .to_le_bytes() - .iter() - .enumerate() - .for_each(|(i, bytes)| { - self.0.borrow_mut().insert(addr + i, *bytes); - }) - } - } - - 4 => { - if big_endian { - trace!("write word be"); - data.to_be_bytes() - .iter() - .enumerate() - .for_each(|(i, bytes)| { - self.0.borrow_mut().insert(addr + i, *bytes); - }) - } else { - trace!("write word le"); - data.to_le_bytes() - .iter() - .enumerate() - .for_each(|(i, bytes)| { - self.0.borrow_mut().insert(addr + i, *bytes); - }) - } - } - _ => { - panic!("illegal sized memory operation, size = {}", size) - } - }; - } +#[derive(Serialize, Deserialize, Clone)] +struct RegOp { + pub addr: u8, + pub data: u32, // might save whole signal in future } #[typetag::serde] @@ -215,118 +87,106 @@ impl Component for RegFile { Ports::new( vec![ &InputPort { - port_id: REG_FILE_A1_IN_ID.to_string(), - input: self.a1_in.clone(), + port_id: reg_file_fields::RS_ADDRESS_IN_ID.to_string(), + input: self.rs_address_in.clone(), }, &InputPort { - port_id: REG_FILE_A2_IN_ID.to_string(), - input: self.a2_in.clone(), + port_id: reg_file_fields::RT_ADDRESS_IN_ID.to_string(), + input: self.rt_address_in.clone(), }, &InputPort { - port_id: REG_FILE_A3_IN_ID.to_string(), - input: self.a3_in.clone(), + port_id: reg_file_fields::WRITE_ADDRESS_IN_ID.to_string(), + input: self.write_address_in.clone(), }, &InputPort { - port_id: REG_FILE_WD3_IN_ID.to_string(), - input: self.wd3_in.clone(), + port_id: reg_file_fields::WRITE_DATA_IN_ID.to_string(), + input: self.write_data_in.clone(), }, &InputPort { - port_id: REG_FILE_WE3_IN_ID.to_string(), - input: self.we3_in.clone(), + port_id: reg_file_fields::WRITE_ENABLE_IN_ID.to_string(), + input: self.write_enable_in.clone(), }, ], OutputType::Combinatorial, - vec![REG_FILE_RD1_OUT_ID, REG_FILE_RD2_OUT_ID], + vec![ + reg_file_fields::RS_VALUE_OUT_ID, + reg_file_fields::RT_VALUE_OUT_ID, + ], ), ) } fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { match target_port_id.as_str() { - REG_FILE_A1_IN_ID => self.a1_in = new_input, - REG_FILE_A2_IN_ID => self.a2_in = new_input, - REG_FILE_A3_IN_ID => self.a3_in = new_input, - REG_FILE_WD3_IN_ID => self.wd3_in = new_input, - REG_FILE_WE3_IN_ID => self.we3_in = new_input, + reg_file_fields::RS_ADDRESS_IN_ID => self.rs_address_in = new_input, + reg_file_fields::RT_ADDRESS_IN_ID => self.rt_address_in = new_input, + reg_file_fields::WRITE_ADDRESS_IN_ID => self.write_address_in = new_input, + reg_file_fields::WRITE_DATA_IN_ID => self.write_data_in = new_input, + reg_file_fields::WRITE_ENABLE_IN_ID => self.write_enable_in = new_input, _ => {} } } - // propagate sign extension to output - // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { - // get input values - let mut history_entry = MemOp { - data: None, - addr: 0, - size: 0, - }; - - let a1: u32 = simulator.get_input_value(&self.a1_in).try_into().unwrap(); - let a2: u32 = simulator.get_input_value(&self.a2_in).try_into().unwrap(); - let a3: u32 = simulator.get_input_value(&self.a3_in).try_into().unwrap(); - let wd3: SignalValue = simulator.get_input_value(&self.wd3_in); - let we3: u32 = simulator.get_input_value(&self.we3_in).try_into().unwrap(); - - let size = 4; - let sign: bool = false; // in the mips, always read as unsigned - - let a1_addr = a1; // rs - let a2_addr = a2; // rt - let a3_addr = a3; // rt or rd depending on mux output, operation type - - // since the addr is only 5 bits, it cant be out of bounds, 2^5 = 32 + //TODO check if inputs are invalid and return error + // type of signal + // address within bounds etc - // read RD1 and RD2 - trace!("read addr {:?} size {:?}", a1_addr, size); - let value1 = self - .memory - .read(a1_addr as usize, size as usize, sign, self.big_endian) + let rs_addr: usize = simulator + .get_input_value(&self.rs_address_in) .try_into() .unwrap(); - - trace!("read addr {:?} size {:?}", a2_addr, size); - let value2 = self - .memory - .read(a2_addr as usize, size as usize, sign, self.big_endian) + let rt_addr: usize = simulator + .get_input_value(&self.rt_address_in) + .try_into() + .unwrap(); + let w_addr: usize = simulator + .get_input_value(&self.write_address_in) + .try_into() + .unwrap(); + let w_data: u32 = simulator + .get_input_value(&self.write_data_in) + .try_into() + .unwrap(); + let w_enable: u32 = simulator + .get_input_value(&self.write_enable_in) .try_into() .unwrap(); - // if we, write to reg - if we3 == 1 { - let size = 4; - history_entry = MemOp { - data: match self.memory.read( - a3_addr as usize, - size as usize, - false, - self.big_endian, - ) { - SignalValue::Data(d) => Some(d as usize), - _ => None, - }, + //save value to history before write, no need for {} as borrows is dropped after operation? + self.history.borrow_mut().push(RegOp { + addr: w_addr as u8, + data: self + .registers + .borrow() + .get(w_addr as usize) + .unwrap() + .clone(), + }); + + // write data + if w_enable == 1 && w_addr != 0 { + self.registers.borrow_mut()[w_addr] = w_data; + }; - addr: a3_addr as usize, - size: size as u8, - }; - trace!("write addr {:?} size {:?}", a3_addr, size); + // update out signals, no {} since self.registers are dropped at end of function + let regs = self.registers.borrow(); + simulator.set_out_value(&self.id, reg_file_fields::RS_VALUE_OUT_ID, regs[rs_addr]); + simulator.set_out_value(&self.id, reg_file_fields::RT_VALUE_OUT_ID, regs[rt_addr]); - if a3_addr != 0 { - self.memory - .write(a3_addr as usize, size as usize, self.big_endian, wd3); - } else { - // does nothing and reg remains 0 - } + Ok(()) + } - let value = self.memory.align(a3_addr as usize, size as usize); - trace!("align {:?}", value); + fn un_clock(&self) { + if let Some(last_op) = self.history.borrow_mut().pop() { + let mut regs = self.registers.borrow_mut(); + regs[last_op.addr as usize] = last_op.data; } + } - simulator.set_out_value(&self.id, REG_FILE_RD1_OUT_ID, SignalValue::Data(value1)); - simulator.set_out_value(&self.id, REG_FILE_RD2_OUT_ID, SignalValue::Data(value2)); - - self.history.borrow_mut().push(history_entry); - Ok(()) + fn reset(&self) { + *self.registers.borrow_mut() = [0; 32]; + *self.history.borrow_mut() = vec![]; } fn as_any(&self) -> &dyn Any { @@ -334,58 +194,48 @@ impl Component for RegFile { } } -impl Deref for Memory { - type Target = RefCell>; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - impl RegFile { pub fn new( id: &str, pos: (f32, f32), - a1_in: Input, - a2_in: Input, - a3_in: Input, - wd3_in: Input, - we3_in: Input, - big_endian: bool, - memory: BTreeMap, + rs_address_in: Input, + rt_address_in: Input, + write_address_in: Input, + write_data_in: Input, + write_enable_in: Input, ) -> Self { RegFile { id: id.to_string(), pos, - a1_in, - a2_in, - a3_in, - wd3_in, - we3_in, - big_endian, - memory: Memory::new(memory.clone()), + rs_address_in, + rt_address_in, + write_address_in, + write_data_in, + write_enable_in, + registers: RefCell::new([0; 32]), // create 32 zeros history: RefCell::new(vec![]), - init_state: memory.clone(), + show_reg_names: RefCell::default(), + reg_format: RefCell::default(), } } pub fn rc_new( id: &str, pos: (f32, f32), - a1_in: Input, - a2_in: Input, - a3_in: Input, - wd3_in: Input, - we3_in: Input, - big_endian: bool, + rs_address_in: Input, + rt_address_in: Input, + write_address_in: Input, + write_data_in: Input, + write_enable_in: Input, ) -> Rc { - let mut mem = BTreeMap::new(); - //fill the defined memory range with zeroes - for i in 0..32.clone() { - mem.insert(i as usize, 0u8); - } Rc::new(RegFile::new( - id, pos, a1_in, a2_in, a3_in, wd3_in, we3_in, big_endian, mem, + id, + pos, + rs_address_in, + rt_address_in, + write_address_in, + write_data_in, + write_enable_in, )) } } diff --git a/src/gui_egui/components/mips_reg_file.rs b/src/gui_egui/components/mips_reg_file.rs index b7089b43..b9047340 100644 --- a/src/gui_egui/components/mips_reg_file.rs +++ b/src/gui_egui/components/mips_reg_file.rs @@ -1,13 +1,19 @@ use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; -use crate::components::RegFile; -use crate::gui_egui::component_ui::{ - drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, - rect_with_hover, visualize_ports, -}; +use crate::components::{RegFile, RegFormat}; +use crate::gui_egui::component_ui::{rect_with_hover, visualize_ports}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::offset_helper; -use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; +use crate::gui_egui::helper::{component_area, offset_helper}; +use egui::{ + scroll_area, Color32, ComboBox, Pos2, Rect, Response, RichText, ScrollArea, Shape, Slider, + Stroke, Ui, Vec2, +}; + +const REG_NAMES: [&str; 32] = [ + "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", + "s7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "t8", "t9", "k0", "k1", "gp", "sp", "fp", + "ra", +]; #[typetag::serde] impl EguiComponent for RegFile { @@ -21,8 +27,6 @@ impl EguiComponent for RegFile { clip_rect: Rect, editor_mode: EditorMode, ) -> Option> { - // 81x41 - // middle: 41x 21y (0 0) let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; let offset_old = offset; let mut offset = offset; @@ -30,159 +34,97 @@ impl EguiComponent for RegFile { offset.y += self.pos.1 * scale; let s = scale; let o = offset; - // The shape - ui.painter().add(Shape::closed_line( - vec![ - oh((-40f32, 0f32), s, o), - oh((40f32, 0f32), s, o), - oh((40f32, 20f32), s, o), - oh((-40f32, 20f32), s, o), - ], - Stroke { - width: scale, - color: Color32::RED, - }, - )); + let rs: u32; + let rt: u32; + if let Some(sim) = simulator { + rs = sim.get_input_value(&self.rs_address_in).try_into().unwrap(); + rt = sim.get_input_value(&self.rt_address_in).try_into().unwrap(); + } else { + rs = 32; // register that dont exist + rt = 32; // + } + // The shape let rect = Rect { - min: oh((-40f32, -20f32), s, o), - max: oh((40f32, 20f32), s, o), + min: oh((-60f32, -90f32), s, o), + max: oh((60f32, 90f32), s, o), }; - let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - ui.label(format!("Id: {}", self.id.clone())); - // todo: is this actually correct? - if let Some(s) = &simulator { - ui.label({ - let a1_r: Result = - s.get_input_value(&self.a1_in).try_into(); - let a2_r: Result = - s.get_input_value(&self.a2_in).try_into(); - let a3_r: Result = - s.get_input_value(&self.a3_in).try_into(); - let wd3_r: Result = - s.get_input_value(&self.wd3_in).try_into(); - let we3_r: Result = - s.get_input_value(&self.we3_in).try_into(); - let mut s: String = "".to_string(); + component_area(self.id.to_string(), ui.ctx(), offset.to_pos2(), |ui| { + ui.style_mut().visuals.panel_fill = Color32::LIGHT_BLUE; + ui.set_height(rect.height()); + ui.set_width(rect.width()); + ui.group(|ui| { + let mut tmp: RegFormat = self.reg_format.borrow().clone(); + ui.label(RichText::new("Register File").size(12f32 * scale)); + ui.toggle_value( + &mut *self.show_reg_names.borrow_mut(), + RichText::new("Show names").size(12f32 * scale), + ); + ComboBox::from_id_source(&self.id) + .selected_text(RichText::new(format!("{:?}", tmp)).size(12f32 * scale)) + .show_ui(ui, |ui| { + ui.selectable_value(&mut tmp, RegFormat::Hex, "Hex"); + ui.selectable_value(&mut tmp, RegFormat::DecUnsigned, "Decimal"); + ui.selectable_value(&mut tmp, RegFormat::DecSigned, "Decimal signed"); + ui.selectable_value(&mut tmp, RegFormat::Bin, "Binary"); + ui.selectable_value(&mut tmp, RegFormat::UTF8BE, "UTF-8 big endian"); + ui.selectable_value(&mut tmp, RegFormat::UTF8LE, "UTF-8 little endian"); + }); + *self.reg_format.borrow_mut() = tmp; - match a1_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", a1_r), - } - match a2_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", a2_r), - } - match a3_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", a3_r), - } - match wd3_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", wd3_r), - } - match we3_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", we3_r), - } - format!("{}", s) - }); - ui.label("reg_file"); - } + ui.separator(); + ScrollArea::vertical() + .max_height(rect.height()) + .max_width(rect.width()) + .show(ui, |ui| { + ui.set_width(ui.available_width()); + let mut str: String = "".into(); + for (i, val) in self.registers.borrow().iter().enumerate() { + str.push_str( + match *self.show_reg_names.borrow() { + true => format!("{:<4}", REG_NAMES[i]), + false => format!("r{:<3}", i), + } + .as_str(), + ); + str.push_str( + match *self.reg_format.borrow() { + RegFormat::Hex => format!("{:#010x}", val), + RegFormat::DecSigned => format!("{}", (*val) as i32), + RegFormat::DecUnsigned => format!("{}", val), + RegFormat::Bin => format!("{:#034b}", val), + RegFormat::UTF8BE => { + String::from_utf8_lossy(&val.to_be_bytes()) + .escape_debug() + .to_string() + } + RegFormat::UTF8LE => { + String::from_utf8_lossy(&val.to_le_bytes()) + .escape_debug() + .to_string() + } + } + .as_str(), + ); + str.push_str("\n") + } + ui.label(RichText::new(str).size(12f32 * scale).monospace()) + }) + }); }); + // r1.union(r2.) + // .inner + // .response + // .on_hover_ui(|ui| { + // ui.label("on_hover"); + // }); + match editor_mode { EditorMode::Simulator => (), _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), } - Some(vec![r]) - } - - fn render_editor( - &mut self, - ui: &mut Ui, - context: &mut EguiExtra, - simulator: Option<&mut Simulator>, - offset: Vec2, - scale: f32, - clip_rect: Rect, - id_ports: &[(crate::common::Id, Ports)], - grid: &GridOptions, - editor_mode: EditorMode, - ) -> EditorRenderReturn { - let r_vec = RegFile::render( - self, - ui, - context, - simulator, - offset, - scale, - clip_rect, - editor_mode, - ) - .unwrap(); - let resp = &r_vec[0]; - let delete = drag_logic( - ui.ctx(), - resp, - &mut self.pos, - &mut context.pos_tmp, - scale, - offset, - grid, - ); - - properties_window( - ui, - self.id.clone(), - resp, - &mut context.properties_window, - |ui| { - let mut clicked_dropdown = false; - input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_drag_value(ui, &mut self.pos); - clicked_dropdown |= input_selector( - ui, - &mut self.a1_in, - crate::components::REG_FILE_A1_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown |= input_selector( - ui, - &mut self.a2_in, - crate::components::REG_FILE_A2_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown |= input_selector( - ui, - &mut self.a3_in, - crate::components::REG_FILE_A3_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown |= input_selector( - ui, - &mut self.wd3_in, - crate::components::REG_FILE_WD3_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown |= input_selector( - ui, - &mut self.we3_in, - crate::components::REG_FILE_WE3_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown - }, - ); - EditorRenderReturn { - delete, - resp: Some(r_vec), - } + None } fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index 2652fffe..03ae4329 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -1,6 +1,8 @@ use crate::common::{Components, Ports}; use crate::gui_egui::editor::{EditorMode, SnapPriority}; -use egui::{Color32, Pos2, Rect, Sense, Vec2}; +use egui::{ + Align2, Area, Color32, Context, InnerResponse, Order, Pos2, Rect, RichText, Sense, Ui, Vec2, +}; use epaint::Shadow; pub fn offset_reverse_helper_pos2(xy: Pos2, scale: f32, offset: Vec2) -> Pos2 { @@ -116,3 +118,20 @@ pub fn shadow_small_dark() -> Shadow { color: Color32::BLACK, } } + +pub fn component_area( + id: String, + ctx: &Context, + pos: impl Into, + content: impl FnOnce(&mut Ui) -> R, +) -> InnerResponse { + Area::new(egui::Id::from(id)) + .order(Order::Middle) + .current_pos(pos) + .movable(false) + .enabled(true) + .interactable(false) + .pivot(Align2::CENTER_CENTER) + .constrain(false) + .show(ctx, content) +} From 03dfdb2a6cbf488ec4db78f782e5c451a427b01b Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Wed, 7 Aug 2024 15:27:35 +0200 Subject: [PATCH 040/126] added component zero extend, only for gui representation --- src/components/mod.rs | 2 + src/components/zero_extend.rs | 91 ++++++++++++++++++++++++++ src/gui_egui/components/mod.rs | 1 + src/gui_egui/components/zero_extend.rs | 54 +++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 src/components/zero_extend.rs create mode 100644 src/gui_egui/components/zero_extend.rs diff --git a/src/components/mod.rs b/src/components/mod.rs index 2620d448..a026d07d 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -22,6 +22,7 @@ mod sext; mod shift_left_const; mod sz_extend; mod wire; +mod zero_extend; pub use add::*; pub use and::*; @@ -47,3 +48,4 @@ pub use sext::*; pub use shift_left_const::*; pub use sz_extend::*; pub use wire::*; +pub use zero_extend::*; diff --git a/src/components/zero_extend.rs b/src/components/zero_extend.rs new file mode 100644 index 00000000..e196ff0b --- /dev/null +++ b/src/components/zero_extend.rs @@ -0,0 +1,91 @@ +// use std::fmt::Alignment; +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, +}; +use crate::signal; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::rc::Rc; + +pub const ZEROEXTEND_SIGNAL_IN_ID: &str = "signal_in"; + +pub const ZEROEXTEND_OUT_ID: &str = "out"; + +#[derive(Serialize, Deserialize, Clone)] +pub struct ZeroExtend { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) signal_in: Input, +} + +#[typetag::serde] +impl Component for ZeroExtend { + fn to_(&self) { + trace!("zero_extend"); + } + #[cfg(feature = "gui-egui")] + fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { + let dummy_input = Input::new("dummy", "out"); + Box::new(Rc::new(ZeroExtend { + id: "dummy".to_string(), + pos: (0.0, 0.0), + signal_in: dummy_input.clone(), + })) + } + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![&InputPort { + port_id: ZEROEXTEND_SIGNAL_IN_ID.to_string(), + input: self.signal_in.clone(), + }], + OutputType::Combinatorial, + vec![ZEROEXTEND_OUT_ID], + ), + ) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + ZEROEXTEND_SIGNAL_IN_ID => self.signal_in = new_input, + _ => {} + } + } + + // propagate sign extension to output + // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get input values + let signal_in: u32 = simulator + .get_input_value(&self.signal_in) + .try_into() + .unwrap(); + + let output: u32 = signal_in & 0x0000_FFFF; // already zero exrtended + + simulator.set_out_value(&self.id, ZEROEXTEND_OUT_ID, SignalValue::Data(output)); + Ok(()) + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl ZeroExtend { + pub fn new(id: &str, pos: (f32, f32), signal_in: Input) -> Self { + ZeroExtend { + id: id.to_string(), + pos, + signal_in, + } + } + + pub fn rc_new(id: &str, pos: (f32, f32), signal_in: Input) -> Rc { + Rc::new(ZeroExtend::new(id, pos, signal_in)) + } +} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index 9615df16..cb384d83 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -21,3 +21,4 @@ mod sext; mod shift_left_const; mod sz_extend; mod wire; +mod zero_extend; diff --git a/src/gui_egui/components/zero_extend.rs b/src/gui_egui/components/zero_extend.rs new file mode 100644 index 00000000..6d8310c4 --- /dev/null +++ b/src/gui_egui/components/zero_extend.rs @@ -0,0 +1,54 @@ +use crate::common::{EguiComponent, Simulator}; +use crate::components::ZeroExtend; +use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::{component_area, offset_helper}; +use egui::{Label, Pos2, Rect, Response, RichText, Ui, Vec2}; + +#[typetag::serde] +impl EguiComponent for ZeroExtend { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + _simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + _clip_rect: Rect, + _editor_mode: EditorMode, + ) -> Option> { + // size of the component + let width = 200f32; + let height: f32 = 20f32; + let rect = Rect::from_center_size( + (Pos2::from(self.pos) * scale + offset), + Vec2 { + x: width, + y: height, + } * scale, + ); + let r = component_area(self.id.to_string(), ui.ctx(), rect.center(), |ui| { + ui.set_height(rect.height()); + ui.set_width(rect.width()); + ui.group(|ui| { + ui.add_sized( + ui.available_size_before_wrap(), + // Change string here for another name + Label::new(RichText::new("zero_extend").size(12f32 * scale)), + ) + }) + .response + }) + .inner; + + Some(vec![r]) + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } +} From 74fc9b723ef88ce84e27d96690f0969d8988e080 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Wed, 7 Aug 2024 15:37:17 +0200 Subject: [PATCH 041/126] added gui for branch logic component --- src/gui_egui/components/mips_branch_logic.rs | 54 ++++++++++++++++++++ src/gui_egui/components/mod.rs | 1 + 2 files changed, 55 insertions(+) create mode 100644 src/gui_egui/components/mips_branch_logic.rs diff --git a/src/gui_egui/components/mips_branch_logic.rs b/src/gui_egui/components/mips_branch_logic.rs new file mode 100644 index 00000000..a3292471 --- /dev/null +++ b/src/gui_egui/components/mips_branch_logic.rs @@ -0,0 +1,54 @@ +use crate::common::{EguiComponent, Simulator}; +use crate::components::BranchLogic; +use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::{component_area, offset_helper}; +use egui::{Label, Pos2, Rect, Response, RichText, Ui, Vec2}; + +#[typetag::serde] +impl EguiComponent for BranchLogic { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + _simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + _clip_rect: Rect, + _editor_mode: EditorMode, + ) -> Option> { + // size of the component + let width = 200f32; + let height: f32 = 20f32; + let rect = Rect::from_center_size( + (Pos2::from(self.pos) * scale + offset), + Vec2 { + x: width, + y: height, + } * scale, + ); + let r = component_area(self.id.to_string(), ui.ctx(), rect.center(), |ui| { + ui.set_height(rect.height()); + ui.set_width(rect.width()); + ui.group(|ui| { + ui.add_sized( + ui.available_size_before_wrap(), + // Change string here for another name + Label::new(RichText::new("branch_logic").size(12f32 * scale)), + ) + }) + .response + }) + .inner; + + Some(vec![r]) + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } +} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index cb384d83..ec25de84 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -5,6 +5,7 @@ mod constant; mod cross; mod full_adder; mod mem; +mod mips_branch_logic; mod mips_controll_unit; mod mips_im; mod mips_instruction_splitter; From 22e90a0269390fcb72130edca127c06126872b4a Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Wed, 7 Aug 2024 16:46:40 +0200 Subject: [PATCH 042/126] added first vertion of mips cpu, missing dm and im --- examples/mips_example_1.rs | 175 +++++++++++++++++++++++++++++++++---- src/gui_egui/gui.rs | 2 +- 2 files changed, 159 insertions(+), 18 deletions(-) diff --git a/examples/mips_example_1.rs b/examples/mips_example_1.rs index 00ba472f..a4ec2cc2 100644 --- a/examples/mips_example_1.rs +++ b/examples/mips_example_1.rs @@ -1,3 +1,4 @@ +// use crate::src::components::cntr_unit_signals; use std::path::PathBuf; use std::rc::Rc; use syncrim::common::EguiComponent; @@ -14,43 +15,183 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - ProbeEdit::rc_new("c0", (50.0, 100.0)), // register that holds instr addr - Register::rc_new("reg", (150.0, 100.0), Input::new("c0", "out")), + Register::rc_new("pc", (2000.0, 5000.0), Input::new("mux_jump_merge", "out")), // step addr from reg by 4 - Constant::rc_new("+4", (200.0, 150.0), 4), + Constant::rc_new("+4", (2000.0, 5100.0), 4), Add::rc_new( "pc+4", - (250.0, 100.0), - Input::new("reg", "out"), + (2200.0, 5000.0), + Input::new("pc", "out"), Input::new("+4", "out"), ), // // - ProbeEdit::rc_new("ctrl", (200.0, 250.0)), // MUX to choose what intruction addr to choose from, branch jump, reg, pc+4 Mux::rc_new( - "mux", - (200.0, 200.0), - Input::new("ctrl", "out"), + "mux_jump_merge", + (1800.0, 5000.0), + Input::new("branch", BRANCH_OUT_ID), vec![ - // Input::new("clk", CLK_OUT_ID), - //Input::new("c2", "out"), - Input::new("jump_merge", MERGE_OUT_ID), + Input::new("pc_add_branch", FULL_ADD_OUT_ID), //TODO: describe origin + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), // goes to addr, RD2 + Input::new("jump_merge", MERGE_OUT_ID), // Input::new("pc+4", CLK_OUT_ID), ], - ), // + ), // // merges to find out jump location - Constant::rc_new("c1", (100.0, 350.0), 0), JumpMerge::rc_new( "jump_merge", - (100.0, 300.0), - Input::new("reg", "out"), //input from reg before pc+4 - Input::new("c1", "out"), //input from instruction mem + (1700.0, 5300.0), + Input::new("pc", REGISTER_OUT_ID), //input from reg before pc+4 + Input::new("dummy", "out"), //input from instruction mem + ), + // + // splits intructions from ir to fields + InstrSplit::rc_new( + "instruction_split", + (2400.0, 4000.0), + Input::new("dummy", "out"), + ), //TODO: take im input + // + // + ControlUnit::rc_new("control_unit", (5000.0, 500.0), Input::new("dummy", "out")), //TODO: take im input + // + // + Register::rc_new( + "reg_we", + (4400.0, 500.0), + Input::new("control_unit", cntr_field::REG_WRITE_ENABLE_OUT), + ), + // + // extends immediate field + SignZeroExtend::rc_new( + "signzero_extend", + (2600.0, 5000.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_IMMEDIATE_ID), + Input::new("control_unit", cntr_field::EXTEND_SELECT_OUT), // cu tells it to either sing- or zero- extend + ), + // + // + RegFile::rc_new( + "reg_file", + (3100.0, 2000.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + Input::new("mux_write_addr", REGISTER_OUT_ID), //write address + Input::new("result_reg", REGISTER_OUT_ID), //write data + Input::new("reg_we", REGISTER_OUT_ID), + ), + // + // + BranchLogic::rc_new( + "branch", + (3300.0, 2000.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_OP_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_FUNCT_ID), + Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), + ), + // + // + ZeroExtend::rc_new( + "zero_extend_for_chamt", + (3700.0, 1600.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_SHAMT_ID), + ), + // + // + Constant::rc_new("0_a_inp", (3800.0, 1700.0), 0), + Mux::rc_new( + "mux_source_a", + (3800.0, 1800.0), + Input::new("control_unit", cntr_field::ALU_SRC_A_OUT), + vec![ + Input::new("zero_extend_for_chamt", SIGNZEROEXTEND_OUT_ID), + Input::new("0_a_inp", "out"), + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), + ], + ), + // + // + Mux::rc_new( + "mux_source_b", + (3800.0, 2200.0), + Input::new("control_unit", cntr_field::ALU_SRC_B_OUT), + vec![ + Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), + Input::new("pc+4", ADD_OUT_ID), + Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), + ], + ), + // + // + FullAdd::rc_new( + "alu", + (4100.0, 2000.0), + Input::new("mux_source_a", MUX_OUT_ID), + Input::new("mux_source_b", MUX_OUT_ID), + Input::new("control_unit", cntr_field::ALU_OP_OUT), + ), + // + // + Mux::rc_new( + "mux_write_back", + (4300.0, 2200.0), + Input::new("control_unit", cntr_field::REG_WRITE_SRC_OUT), + vec![ + Input::new("alu", FULL_ADD_OUT_ID), + Input::new("dummy", "out"), //TODO: data meme output + ], + ), + // + // + Register::rc_new( + "result_reg", + (4400.0, 2200.0), + Input::new("mux_write_back", MUX_OUT_ID), + ), + // + // + ShiftConst::rc_new( + "branch_shift", + (2900.0, 5250.0), + Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), + 2, + ), + // + // + Add::rc_new( + "pc_add_branch", + (3000.0, 5200.0), + Input::new("pc+4", ADD_OUT_ID), + Input::new("branch_shift", SHIFT_OUT_ID), + ), + // + // + Constant::rc_new("0x_1F", (3750.0, 5500.0), 0), + Mux::rc_new( + "mux_write_addr", + (3800.0, 5500.0), + Input::new("control_unit", cntr_field::REG_DEST_OUT), + vec![ + Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + Input::new("0x_1F", "out"), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RD_ID), + ], + ), + // + // + Register::rc_new( + "reg_write_addr", + (4400.0, 5500.0), + Input::new("mux_write_addr", MUX_OUT_ID), ), // // + Constant::rc_new("dummy", (6000.0, 3000.0), 0), ], }; diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index 07f377bd..5453c905 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -147,7 +147,7 @@ impl Gui { } }); let cpr = central_panel.response.interact(Sense::drag()); - if cpr.dragged_by(PointerButton::Middle) { + if cpr.dragged_by(PointerButton::Primary) { self.pan += cpr.drag_delta(); } if central_panel.response.hovered() { From 9c8d286bf135ff7035bb23776850f484b0b6096b Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Thu, 8 Aug 2024 15:59:06 +0200 Subject: [PATCH 043/126] alu now handles overflow --- src/components/full_adder.rs | 41 ++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/src/components/full_adder.rs b/src/components/full_adder.rs index 65a8e7e4..33afdbd6 100644 --- a/src/components/full_adder.rs +++ b/src/components/full_adder.rs @@ -12,7 +12,8 @@ use std::rc::Rc; pub const FULL_ADD_A_IN_ID: &str = "full_add_a_in"; pub const FULL_ADD_B_IN_ID: &str = "full_add_b_in"; pub const FULL_ADD_OP_IN_ID: &str = "full_add_op_in"; -pub const FULL_ADD_OUT_ID: &str = "out"; +pub const FULL_ADD_OUT_ID: &str = "alu_out"; +pub const FULL_ADD_OVERFLOW_OUT_ID: &str = "alu_overflow_out"; pub mod alu_op { pub const ADD: u32 = 0; @@ -75,7 +76,7 @@ impl Component for FullAdd { }, ], OutputType::Combinatorial, - vec![FULL_ADD_OUT_ID], + vec![FULL_ADD_OUT_ID, FULL_ADD_OVERFLOW_OUT_ID], ), ) } @@ -96,19 +97,42 @@ impl Component for FullAdd { let op: u32 = simulator.get_input_value(&self.op_in).try_into().unwrap(); let output: u32; + let overflow: u32; match op { alu_op::ADD => { - output = a.wrapping_add(b); + // output = a.wrapping_add(b); + + let tmp = (a as i32).checked_add(b as i32); + overflow = match tmp { + Some(val) => { + output = val as u32; + 0 + } + None => { + output = a.wrapping_add(b); + 1 + } + }; } alu_op::ADDU => { - return Err(Condition::Error("ADDU not implemented".to_string())); + output = a.wrapping_add(b); } alu_op::SUB => { - output = a.wrapping_add(b ^ 0xffffffff).wrapping_add(1); + let tmp = (a as i32).checked_sub(b); + overflow = match tmp { + Some(val) => { + output = val as u32; + 0 + } + None => { + output = a.wrapping_sub(b); + 1 + } + } } alu_op::SUBU => { - return Err(Condition::Error("SUBU not implemented".to_string())); + output = a.wrapping_sub(b); } alu_op::AND => { output = a & b; @@ -147,6 +171,11 @@ impl Component for FullAdd { } } simulator.set_out_value(&self.id, FULL_ADD_OUT_ID, SignalValue::Data(output)); + simulator.set_out_value( + &self.id, + FULL_ADD_OVERFLOW_OUT_ID, + SignalValue::Data(overflow), + ); Ok(()) } From e23a7955b9ef124043cb65682335717e6d06ebb4 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 8 Aug 2024 16:13:41 +0200 Subject: [PATCH 044/126] Implemented basic gui function and added it to components Implemented basic gui function and added it to components --- examples/mips_controll_unit.rs | 1 + src/components/shift_left_const.rs | 2 +- src/gui_egui/components/and.rs | 164 ++++----------- src/gui_egui/components/mips_controll_unit.rs | 149 ++++---------- src/gui_egui/components/mips_jump_merge.rs | 164 ++++----------- src/gui_egui/components/shift_left_const.rs | 149 ++++---------- src/gui_egui/components/sz_extend.rs | 186 ++++++------------ src/gui_egui/helper.rs | 132 ++++++++++++- 8 files changed, 322 insertions(+), 625 deletions(-) diff --git a/examples/mips_controll_unit.rs b/examples/mips_controll_unit.rs index 5a381ca6..091e8448 100644 --- a/examples/mips_controll_unit.rs +++ b/examples/mips_controll_unit.rs @@ -6,6 +6,7 @@ use std::{ use syncrim::common::EguiComponent; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; +use syncrim::mips_helper_functions::autowire; use syncrim::{ common::{ComponentStore, Input}, component_store, diff --git a/src/components/shift_left_const.rs b/src/components/shift_left_const.rs index 153bcf41..af1a78b4 100644 --- a/src/components/shift_left_const.rs +++ b/src/components/shift_left_const.rs @@ -19,7 +19,7 @@ pub struct ShiftConst { pub(crate) id: Id, pub(crate) pos: (f32, f32), pub(crate) signal_in: Input, - shift_by: u32, + pub shift_by: u32, } #[typetag::serde] diff --git a/src/gui_egui/components/and.rs b/src/gui_egui/components/and.rs index 8137fbe6..e16e6f54 100644 --- a/src/gui_egui/components/and.rs +++ b/src/gui_egui/components/and.rs @@ -1,13 +1,9 @@ -use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::common::{EguiComponent, Id, Ports, Simulator}; use crate::components::And; -use crate::gui_egui::component_ui::{ - drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, - rect_with_hover, visualize_ports, -}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::offset_helper; -use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; +use crate::gui_egui::helper::basic_component_gui; +use egui::{Rect, Response, RichText, Ui, Vec2}; #[typetag::serde] impl EguiComponent for And { @@ -18,83 +14,41 @@ impl EguiComponent for And { simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, - clip_rect: Rect, - editor_mode: EditorMode, + _clip_rect: Rect, + _editor_mode: EditorMode, ) -> Option> { - // 81x41 - // middle: 41x 21y (0 0) - let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; - let offset_old = offset; - let mut offset = offset; - offset.x += self.pos.0 * scale; - offset.y += self.pos.1 * scale; - let s = scale; - let o = offset; - // The shape - ui.painter().add(Shape::closed_line( - vec![ - oh((-40f32, 0f32), s, o), - oh((40f32, 0f32), s, o), - oh((40f32, 20f32), s, o), - oh((-40f32, 20f32), s, o), - ], - Stroke { - width: scale, - color: Color32::RED, + // size of the component + let width = 100f32; + let height: f32 = 0f32; + basic_component_gui( + self, + &simulator, + ui.ctx(), + (width, height), + offset, + scale, + |ui| { + ui.label(RichText::new("And").size(12f32 * scale)); }, - )); - - let rect = Rect { - min: oh((-40f32, -20f32), s, o), - max: oh((40f32, 20f32), s, o), - }; - let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - ui.label(format!("Id: {}", self.id.clone())); - // todo: is this actually correct? - if let Some(s) = &simulator { - ui.label({ - let a_r: Result = - s.get_input_value(&self.a_in).try_into(); - - let b_r: Result = - s.get_input_value(&self.b_in).try_into(); - - let mut s: String = "".to_string(); - - match a_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", a_r), - } - match b_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", b_r), - } - format!("{}", s) - }); - ui.label("and"); - } - }); - match editor_mode { - EditorMode::Simulator => (), - _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), - } - Some(vec![r]) + // This is a hack to stop the compiler from complaining + // will hopefully be optimized away + None::>, + ) } fn render_editor( &mut self, - ui: &mut Ui, + ui: &mut egui::Ui, context: &mut EguiExtra, simulator: Option<&mut Simulator>, - offset: Vec2, + offset: egui::Vec2, scale: f32, - clip_rect: Rect, - id_ports: &[(crate::common::Id, Ports)], - grid: &GridOptions, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { - let r_vec = And::render( - self, + self.render( ui, context, simulator, @@ -102,69 +56,13 @@ impl EguiComponent for And { scale, clip_rect, editor_mode, - ) - .unwrap(); - let resp = &r_vec[0]; - let delete = drag_logic( - ui.ctx(), - resp, - &mut self.pos, - &mut context.pos_tmp, - scale, - offset, - grid, - ); - - properties_window( - ui, - self.id.clone(), - resp, - &mut context.properties_window, - |ui| { - let mut clicked_dropdown = false; - input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_drag_value(ui, &mut self.pos); - clicked_dropdown |= input_selector( - ui, - &mut self.a_in, - crate::components::AND_A_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown |= input_selector( - ui, - &mut self.b_in, - crate::components::AND_B_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown - }, ); EditorRenderReturn { - delete, - resp: Some(r_vec), + delete: false, + resp: None, } } - fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { - let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![ - ( - crate::components::SEXT_IN_ID.to_string(), - Pos2::new(-40f32, 0f32) + own_pos, - ), - ( - crate::components::SEXT_OUT_ID.to_string(), - Pos2::new(40f32, 0f32) + own_pos, - ), - ] - } - - fn top_padding(&self) -> f32 { - 20f32 - } - fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } @@ -172,4 +70,8 @@ impl EguiComponent for And { fn get_pos(&self) -> (f32, f32) { self.pos } + + fn top_padding(&self) -> f32 { + 20f32 + } } diff --git a/src/gui_egui/components/mips_controll_unit.rs b/src/gui_egui/components/mips_controll_unit.rs index a38d6c4c..91e5e621 100644 --- a/src/gui_egui/components/mips_controll_unit.rs +++ b/src/gui_egui/components/mips_controll_unit.rs @@ -1,13 +1,9 @@ -use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::common::{EguiComponent, Id, Ports, Simulator}; use crate::components::ControlUnit; -use crate::gui_egui::component_ui::{ - drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, - rect_with_hover, visualize_ports, -}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::offset_helper; -use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; +use crate::gui_egui::helper::basic_component_gui; +use egui::{Rect, Response, RichText, Ui, Vec2}; #[typetag::serde] impl EguiComponent for ControlUnit { @@ -18,75 +14,41 @@ impl EguiComponent for ControlUnit { simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, - clip_rect: Rect, - editor_mode: EditorMode, + _clip_rect: Rect, + _editor_mode: EditorMode, ) -> Option> { - // 81x41 - // middle: 41x 21y (0 0) - let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; - let offset_old = offset; - let mut offset = offset; - offset.x += self.pos.0 * scale; - offset.y += self.pos.1 * scale; - let s = scale; - let o = offset; - // The shape - ui.painter().add(Shape::closed_line( - vec![ - oh((-40f32, 0f32), s, o), - oh((40f32, 0f32), s, o), - oh((40f32, 20f32), s, o), - oh((-40f32, 20f32), s, o), - ], - Stroke { - width: scale, - color: Color32::RED, + // size of the component + let width = 400f32; + let height: f32 = 0f32; + basic_component_gui( + self, + &simulator, + ui.ctx(), + (width, height), + offset, + scale, + |ui| { + ui.label(RichText::new("Control Unit").size(12f32 * scale)); }, - )); - - let rect = Rect { - min: oh((-40f32, -20f32), s, o), - max: oh((40f32, 20f32), s, o), - }; - let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - ui.label(format!("Id: {}", self.id.clone())); - // todo: is this actually correct? - if let Some(s) = &simulator { - ui.label({ - let a_r: Result = - s.get_input_value(&self.a_in).try_into(); - let mut s: String = "".to_string(); - - match a_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", a_r), - } - format!("{}", s) - }); - ui.label("ControlUnit"); - } - }); - match editor_mode { - EditorMode::Simulator => (), - _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), - } - Some(vec![r]) + // This is a hack to stop the compiler from complaining + // will hopefully be optimized away + None::>, + ) } fn render_editor( &mut self, - ui: &mut Ui, + ui: &mut egui::Ui, context: &mut EguiExtra, simulator: Option<&mut Simulator>, - offset: Vec2, + offset: egui::Vec2, scale: f32, - clip_rect: Rect, - id_ports: &[(crate::common::Id, Ports)], - grid: &GridOptions, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { - let r_vec = ControlUnit::render( - self, + self.render( ui, context, simulator, @@ -94,62 +56,13 @@ impl EguiComponent for ControlUnit { scale, clip_rect, editor_mode, - ) - .unwrap(); - let resp = &r_vec[0]; - let delete = drag_logic( - ui.ctx(), - resp, - &mut self.pos, - &mut context.pos_tmp, - scale, - offset, - grid, - ); - - properties_window( - ui, - self.id.clone(), - resp, - &mut context.properties_window, - |ui| { - let mut clicked_dropdown = false; - input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_drag_value(ui, &mut self.pos); - clicked_dropdown |= input_selector( - ui, - &mut self.a_in, - crate::components::CLK_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown - }, ); EditorRenderReturn { - delete, - resp: Some(r_vec), + delete: false, + resp: None, } } - fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { - let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![ - ( - crate::components::SEXT_IN_ID.to_string(), - Pos2::new(-40f32, 0f32) + own_pos, - ), - ( - crate::components::SEXT_OUT_ID.to_string(), - Pos2::new(40f32, 0f32) + own_pos, - ), - ] - } - - fn top_padding(&self) -> f32 { - 20f32 - } - fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } @@ -157,4 +70,8 @@ impl EguiComponent for ControlUnit { fn get_pos(&self) -> (f32, f32) { self.pos } + + fn top_padding(&self) -> f32 { + 20f32 + } } diff --git a/src/gui_egui/components/mips_jump_merge.rs b/src/gui_egui/components/mips_jump_merge.rs index b04532e7..f8c24c7e 100644 --- a/src/gui_egui/components/mips_jump_merge.rs +++ b/src/gui_egui/components/mips_jump_merge.rs @@ -1,13 +1,9 @@ -use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::common::{EguiComponent, Id, Ports, Simulator}; use crate::components::JumpMerge; -use crate::gui_egui::component_ui::{ - drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, - rect_with_hover, visualize_ports, -}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::offset_helper; -use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; +use crate::gui_egui::helper::basic_component_gui; +use egui::{Rect, Response, RichText, Ui, Vec2}; #[typetag::serde] impl EguiComponent for JumpMerge { @@ -18,83 +14,41 @@ impl EguiComponent for JumpMerge { simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, - clip_rect: Rect, - editor_mode: EditorMode, + _clip_rect: Rect, + _editor_mode: EditorMode, ) -> Option> { - // 81x41 - // middle: 41x 21y (0 0) - let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; - let offset_old = offset; - let mut offset = offset; - offset.x += self.pos.0 * scale; - offset.y += self.pos.1 * scale; - let s = scale; - let o = offset; - // The shape - ui.painter().add(Shape::closed_line( - vec![ - oh((-40f32, 0f32), s, o), - oh((40f32, 0f32), s, o), - oh((40f32, 20f32), s, o), - oh((-40f32, 20f32), s, o), - ], - Stroke { - width: scale, - color: Color32::RED, + // size of the component + let width = 100f32; + let height: f32 = 0f32; + basic_component_gui( + self, + &simulator, + ui.ctx(), + (width, height), + offset, + scale, + |ui| { + ui.label(RichText::new("Jump Merge").size(12f32 * scale)); }, - )); - - let rect = Rect { - min: oh((-40f32, -20f32), s, o), - max: oh((40f32, 20f32), s, o), - }; - let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - ui.label(format!("Id: {}", self.id.clone())); - // todo: is this actually correct? - if let Some(s) = &simulator { - ui.label({ - let a_r: Result = - s.get_input_value(&self.instr_addr_in).try_into(); - - let b_r: Result = - s.get_input_value(&self.jump_addr_in).try_into(); - - let mut s: String = "".to_string(); - - match a_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", a_r), - } - match b_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", b_r), - } - format!("{}", s) - }); - ui.label("jump_merge"); - } - }); - match editor_mode { - EditorMode::Simulator => (), - _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), - } - Some(vec![r]) + // This is a hack to stop the compiler from complaining + // will hopefully be optimized away + None::>, + ) } fn render_editor( &mut self, - ui: &mut Ui, + ui: &mut egui::Ui, context: &mut EguiExtra, simulator: Option<&mut Simulator>, - offset: Vec2, + offset: egui::Vec2, scale: f32, - clip_rect: Rect, - id_ports: &[(crate::common::Id, Ports)], - grid: &GridOptions, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { - let r_vec = JumpMerge::render( - self, + self.render( ui, context, simulator, @@ -102,69 +56,13 @@ impl EguiComponent for JumpMerge { scale, clip_rect, editor_mode, - ) - .unwrap(); - let resp = &r_vec[0]; - let delete = drag_logic( - ui.ctx(), - resp, - &mut self.pos, - &mut context.pos_tmp, - scale, - offset, - grid, - ); - - properties_window( - ui, - self.id.clone(), - resp, - &mut context.properties_window, - |ui| { - let mut clicked_dropdown = false; - input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_drag_value(ui, &mut self.pos); - clicked_dropdown |= input_selector( - ui, - &mut self.instr_addr_in, - crate::components::MERGE_INSTR_ADDR_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown |= input_selector( - ui, - &mut self.jump_addr_in, - crate::components::MERGE_JUMP_ADDR_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown - }, ); EditorRenderReturn { - delete, - resp: Some(r_vec), + delete: false, + resp: None, } } - fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { - let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![ - ( - crate::components::SEXT_IN_ID.to_string(), - Pos2::new(-40f32, 0f32) + own_pos, - ), - ( - crate::components::SEXT_OUT_ID.to_string(), - Pos2::new(40f32, 0f32) + own_pos, - ), - ] - } - - fn top_padding(&self) -> f32 { - 20f32 - } - fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } @@ -172,4 +70,8 @@ impl EguiComponent for JumpMerge { fn get_pos(&self) -> (f32, f32) { self.pos } + + fn top_padding(&self) -> f32 { + 20f32 + } } diff --git a/src/gui_egui/components/shift_left_const.rs b/src/gui_egui/components/shift_left_const.rs index 939646bd..43fcb0d3 100644 --- a/src/gui_egui/components/shift_left_const.rs +++ b/src/gui_egui/components/shift_left_const.rs @@ -1,13 +1,9 @@ -use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::common::{EguiComponent, Id, Ports, Simulator}; use crate::components::ShiftConst; -use crate::gui_egui::component_ui::{ - drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, - rect_with_hover, visualize_ports, -}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::offset_helper; -use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; +use crate::gui_egui::helper::basic_component_gui; +use egui::{Rect, Response, RichText, Ui, Vec2}; #[typetag::serde] impl EguiComponent for ShiftConst { @@ -18,75 +14,41 @@ impl EguiComponent for ShiftConst { simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, - clip_rect: Rect, - editor_mode: EditorMode, + _clip_rect: Rect, + _editor_mode: EditorMode, ) -> Option> { - // 81x41 - // middle: 41x 21y (0 0) - let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; - let offset_old = offset; - let mut offset = offset; - offset.x += self.pos.0 * scale; - offset.y += self.pos.1 * scale; - let s = scale; - let o = offset; - // The shape - ui.painter().add(Shape::closed_line( - vec![ - oh((-40f32, 0f32), s, o), - oh((40f32, 0f32), s, o), - oh((40f32, 20f32), s, o), - oh((-40f32, 20f32), s, o), - ], - Stroke { - width: scale, - color: Color32::RED, + // size of the component + let width = 100f32; + let height: f32 = 0f32; + basic_component_gui( + self, + &simulator, + ui.ctx(), + (width, height), + offset, + scale, + |ui| { + ui.label(RichText::new(format!("Shift << {}", self.shift_by)).size(12f32 * scale)); }, - )); - - let rect = Rect { - min: oh((-40f32, -20f32), s, o), - max: oh((40f32, 20f32), s, o), - }; - let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - ui.label(format!("Id: {}", self.id.clone())); - // todo: is this actually correct? - if let Some(s) = &simulator { - ui.label({ - let a_r: Result = - s.get_input_value(&self.signal_in).try_into(); - let mut s: String = "".to_string(); - - match a_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", a_r), - } - format!("{}", s) - }); - ui.label("shift_left"); - } - }); - match editor_mode { - EditorMode::Simulator => (), - _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), - } - Some(vec![r]) + // This is a hack to stop the compiler from complaining + // will hopefully be optimized away + None::>, + ) } fn render_editor( &mut self, - ui: &mut Ui, + ui: &mut egui::Ui, context: &mut EguiExtra, simulator: Option<&mut Simulator>, - offset: Vec2, + offset: egui::Vec2, scale: f32, - clip_rect: Rect, - id_ports: &[(crate::common::Id, Ports)], - grid: &GridOptions, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { - let r_vec = ShiftConst::render( - self, + self.render( ui, context, simulator, @@ -94,62 +56,13 @@ impl EguiComponent for ShiftConst { scale, clip_rect, editor_mode, - ) - .unwrap(); - let resp = &r_vec[0]; - let delete = drag_logic( - ui.ctx(), - resp, - &mut self.pos, - &mut context.pos_tmp, - scale, - offset, - grid, - ); - - properties_window( - ui, - self.id.clone(), - resp, - &mut context.properties_window, - |ui| { - let mut clicked_dropdown = false; - input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_drag_value(ui, &mut self.pos); - clicked_dropdown |= input_selector( - ui, - &mut self.signal_in, - crate::components::SHIFT_SIGNAL_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown - }, ); EditorRenderReturn { - delete, - resp: Some(r_vec), + delete: false, + resp: None, } } - fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { - let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![ - ( - crate::components::SEXT_IN_ID.to_string(), - Pos2::new(-40f32, 0f32) + own_pos, - ), - ( - crate::components::SEXT_OUT_ID.to_string(), - Pos2::new(40f32, 0f32) + own_pos, - ), - ] - } - - fn top_padding(&self) -> f32 { - 20f32 - } - fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } @@ -157,4 +70,8 @@ impl EguiComponent for ShiftConst { fn get_pos(&self) -> (f32, f32) { self.pos } + + fn top_padding(&self) -> f32 { + 20f32 + } } diff --git a/src/gui_egui/components/sz_extend.rs b/src/gui_egui/components/sz_extend.rs index 31abcca1..14d5f542 100644 --- a/src/gui_egui/components/sz_extend.rs +++ b/src/gui_egui/components/sz_extend.rs @@ -1,13 +1,10 @@ -use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::common::{EguiComponent, Id, Ports, SignalValue, Simulator}; use crate::components::SignZeroExtend; -use crate::gui_egui::component_ui::{ - drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, - rect_with_hover, visualize_ports, -}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::offset_helper; -use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; +use crate::gui_egui::helper::basic_component_gui; +use crate::simulator; +use egui::{Rect, Response, RichText, Ui, Vec2}; #[typetag::serde] impl EguiComponent for SignZeroExtend { @@ -18,81 +15,66 @@ impl EguiComponent for SignZeroExtend { simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, - clip_rect: Rect, - editor_mode: EditorMode, + _clip_rect: Rect, + _editor_mode: EditorMode, ) -> Option> { - // 81x41 - // middle: 41x 21y (0 0) - let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; - let offset_old = offset; - let mut offset = offset; - offset.x += self.pos.0 * scale; - offset.y += self.pos.1 * scale; - let s = scale; - let o = offset; - // The shape - ui.painter().add(Shape::closed_line( - vec![ - oh((-40f32, 0f32), s, o), - oh((40f32, 0f32), s, o), - oh((40f32, 20f32), s, o), - oh((-40f32, 20f32), s, o), - ], - Stroke { - width: scale, - color: Color32::RED, - }, - )); - - let rect = Rect { - min: oh((-40f32, -20f32), s, o), - max: oh((40f32, 20f32), s, o), - }; - let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - ui.label(format!("Id: {}", self.id.clone())); - // todo: is this actually correct? - if let Some(s) = &simulator { - ui.label({ - let a_r: Result = - s.get_input_value(&self.signzero_ctrl_in).try_into(); - let b_r: Result = - s.get_input_value(&self.signzero_signal_in).try_into(); - let mut s: String = "".to_string(); - - match a_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", a_r), + // size of the component + let width = 100f32; + let height: f32 = 0f32; + basic_component_gui( + self, + &simulator, + ui.ctx(), + (width, height), + offset, + scale, + |ui| { + match &simulator { + Some(sim) => { + ui.label( + RichText::new(match sim.get_input_value(&self.signzero_ctrl_in) { + SignalValue::Uninitialized => { + " Sign/Zero extend: Uninitialized cntr".to_string() + } + SignalValue::Unknown => "Sign/Zero extendUnknown".to_string(), + SignalValue::DontCare => "Sign/Zero extend: Don't Care".to_string(), + SignalValue::Data(v) => match v { + 0 => "Sign/Zero extend: Zero", + 1 => "Sign/Zero extend: Sign", + _ => "Sign/Zero extend: Invalid cntr", + } + .to_string(), + }) + .size(12f32 * scale), + ); } - match b_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", b_r), + + None => { + ui.label(RichText::new("Signal Extender: No Sim").size(12f32 * scale)); } - format!("{}", s) - }); - ui.label("signzero_extend"); - } - }); - match editor_mode { - EditorMode::Simulator => (), - _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), - } - Some(vec![r]) + } + + ui.label(RichText::new("Jump Merge").size(12f32 * scale)); + }, + // This is a hack to stop the compiler from complaining + // will hopefully be optimized away + None::>, + ) } fn render_editor( &mut self, - ui: &mut Ui, + ui: &mut egui::Ui, context: &mut EguiExtra, simulator: Option<&mut Simulator>, - offset: Vec2, + offset: egui::Vec2, scale: f32, - clip_rect: Rect, - id_ports: &[(crate::common::Id, Ports)], - grid: &GridOptions, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { - let r_vec = SignZeroExtend::render( - self, + self.render( ui, context, simulator, @@ -100,69 +82,13 @@ impl EguiComponent for SignZeroExtend { scale, clip_rect, editor_mode, - ) - .unwrap(); - let resp = &r_vec[0]; - let delete = drag_logic( - ui.ctx(), - resp, - &mut self.pos, - &mut context.pos_tmp, - scale, - offset, - grid, - ); - - properties_window( - ui, - self.id.clone(), - resp, - &mut context.properties_window, - |ui| { - let mut clicked_dropdown = false; - input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_drag_value(ui, &mut self.pos); - clicked_dropdown |= input_selector( - ui, - &mut self.signzero_signal_in, - crate::components::SIGNZEROEXTEND_SIGNAL_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown |= input_selector( - ui, - &mut self.signzero_ctrl_in, - crate::components::SIGNZEROEXTEND_CTRL_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown - }, ); EditorRenderReturn { - delete, - resp: Some(r_vec), + delete: false, + resp: None, } } - fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { - let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![ - ( - crate::components::SEXT_IN_ID.to_string(), - Pos2::new(-40f32, 0f32) + own_pos, - ), - ( - crate::components::SEXT_OUT_ID.to_string(), - Pos2::new(40f32, 0f32) + own_pos, - ), - ] - } - - fn top_padding(&self) -> f32 { - 20f32 - } - fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } @@ -170,4 +96,8 @@ impl EguiComponent for SignZeroExtend { fn get_pos(&self) -> (f32, f32) { self.pos } + + fn top_padding(&self) -> f32 { + 20f32 + } } diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index 03ae4329..58e595f9 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -1,7 +1,8 @@ -use crate::common::{Components, Ports}; +use crate::common::{Components, EguiComponent, Input, Ports, SignalValue, Simulator}; use crate::gui_egui::editor::{EditorMode, SnapPriority}; use egui::{ - Align2, Area, Color32, Context, InnerResponse, Order, Pos2, Rect, RichText, Sense, Ui, Vec2, + Align2, Area, Color32, Context, InnerResponse, Order, Pos2, Rect, Response, RichText, Sense, + Ui, Vec2, }; use epaint::Shadow; @@ -135,3 +136,130 @@ pub fn component_area( .constrain(false) .show(ctx, content) } + +/// This renders a basic component +/// Use Content to add label or other graphical info +/// and if desired implement a custom on hover function. +/// The default hover function displays component id and in/out signals formatet as hex +/// +/// # Arguments +/// - content: Note the function don't size the components, +/// that is the responsibility of the content closure +/// - on_hover: if this is some this overides the on hover function and displays that instead +/// +/// # Example +/// This renders a box with the size of 100 by 20, this is scaled with the passed scaled. +/// It is also moved according to the offset argument. +/// +/// In the box the label "Jump Merge" is displayed. +/// +/// And an possible default on hover label might be +/// +/// id: jump_merge +/// +/// merge_instr_addr_in <- reg:out (0x00000000) +/// +/// merge_jump_addr_in <- c1:out (0x00000000) +/// +/// out-> 0x00000000 +/// +/// ``` +/// impl EguiComponent for JumpMerge { +/// fn render( +/// &self, +/// ui: &mut Ui, +/// _context: &mut EguiExtra, +/// simulator: Option<&mut Simulator>, +/// offset: Vec2, +/// scale: f32, +/// _clip_rect: Rect, +/// _editor_mode: EditorMode, +/// ) -> Option> { +/// // size of the component +/// let width = 100f32; +/// let height: f32 = 20f32; +/// basic_component_gui( +/// self, +/// &simulator, +/// ui.ctx(), +/// (width, height), +/// offset, +/// scale, +/// |ui| { +/// ui.label(RichText::new("Jump Merge").size(12f32 * scale)); +/// }, +/// // This is a hack to stop the compiler from complaining +/// // will hopefully be optimized away +/// None::>, +/// ) +/// } +/// } +/// ``` +pub fn basic_component_gui( + component: &dyn EguiComponent, + simulator: &Option<&mut Simulator>, + ctx: &Context, + size: impl Into, + offset: impl Into, + scale: f32, + content: impl FnOnce(&mut Ui), + on_hover: Option, +) -> Option> { + let size: Vec2 = size.into(); + let offset: Vec2 = offset.into(); + + let r = component_area( + component.get_id_ports().0, + ctx, + Pos2::from(component.get_pos()) * scale + offset, + |ui| { + ui.group(|ui| { + ui.set_height(size.y * scale); + ui.set_width(size.x * scale); + ui.centered_and_justified(content); + }) + .response + }, + ) + .inner; + + r.clone().on_hover_ui(|ui| match on_hover { + Some(hover_content) => hover_content(ui), + None => { + ui.label(format!("id: {}", component.get_id_ports().0)); + if let Some(sim) = simulator { + ui.separator(); + for port in component.get_id_ports().1.inputs { + ui.label(format!( + "{} <- {}:{} ({})", + port.port_id, + port.input.id, + port.input.field, + match sim.get_input_value(&port.input) { + SignalValue::Uninitialized => "Uninitialized".to_string(), + SignalValue::Unknown => "Unknown".to_string(), + SignalValue::DontCare => "don't care".to_string(), + SignalValue::Data(v) => format!("{:#010x}", v), + }, + )); + } + ui.separator(); + for port_id in component.get_id_ports().1.outputs { + ui.label(format!( + "{} -> {}", + port_id, + match sim + .get_input_value(&Input::new(&component.get_id_ports().0, &port_id)) + { + SignalValue::Uninitialized => "Uninitialized".to_string(), + SignalValue::Unknown => "Unknown".to_string(), + SignalValue::DontCare => "Don't care".to_string(), + SignalValue::Data(v) => format!("{:#010x}", v), + }, + )); + } + }; + } + }); + Some(vec![r]) +} From 50b3b545428a23b314db0611cacaa9d1acc1c04d Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Fri, 9 Aug 2024 14:37:44 +0200 Subject: [PATCH 045/126] fixed compiling error with code --- src/components/full_adder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/full_adder.rs b/src/components/full_adder.rs index 33afdbd6..17377a81 100644 --- a/src/components/full_adder.rs +++ b/src/components/full_adder.rs @@ -97,7 +97,7 @@ impl Component for FullAdd { let op: u32 = simulator.get_input_value(&self.op_in).try_into().unwrap(); let output: u32; - let overflow: u32; + let mut overflow: u32 = 0; match op { alu_op::ADD => { @@ -119,7 +119,7 @@ impl Component for FullAdd { output = a.wrapping_add(b); } alu_op::SUB => { - let tmp = (a as i32).checked_sub(b); + let tmp = (a as i32).checked_sub(b as i32); overflow = match tmp { Some(val) => { output = val as u32; From 4f25ec0274ede3f781b42ec487d14c02a83814b5 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Fri, 9 Aug 2024 17:48:31 +0200 Subject: [PATCH 046/126] Updated helpers with an use full component gui function --- src/gui_egui/helper.rs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index 58e595f9..5347feef 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -202,23 +202,36 @@ pub fn basic_component_gui( size: impl Into, offset: impl Into, scale: f32, + clip_rect: Rect, content: impl FnOnce(&mut Ui), on_hover: Option, ) -> Option> { let size: Vec2 = size.into(); let offset: Vec2 = offset.into(); + let component_rect = Rect::from_center_size( + Pos2::from(component.get_pos()) * scale + offset, + size * scale, + ); + let r = component_area( component.get_id_ports().0, ctx, - Pos2::from(component.get_pos()) * scale + offset, + component_rect.center(), |ui| { - ui.group(|ui| { - ui.set_height(size.y * scale); - ui.set_width(size.x * scale); - ui.centered_and_justified(content); - }) - .response + ui.set_clip_rect(clip_rect); + let mut group = egui::containers::Frame::group(ui.style()); + group.inner_margin *= scale; + group.rounding *= scale; + // group.fill = Color32::LIGHT_RED; // Use this ween component background is implemented, probably when we implement dark mode + group + .show(ui, |ui| { + ui.set_height(component_rect.height()); + ui.set_width(component_rect.width()); + ui.set_clip_rect(component_rect.intersect(clip_rect)); + content(ui); + }) + .response }, ) .inner; From 444ac8d6612ec4e37be5d705b5a9a17974af82d3 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Fri, 9 Aug 2024 17:49:16 +0200 Subject: [PATCH 047/126] updated components to sue component gui helper --- src/gui_egui/components/and.rs | 7 +- src/gui_egui/components/mips_branch_logic.rs | 84 ++++++--- src/gui_egui/components/mips_controll_unit.rs | 9 +- .../components/mips_instruction_splitter.rs | 150 ++++------------ src/gui_egui/components/mips_jump_merge.rs | 9 +- src/gui_egui/components/mips_reg_file.rs | 165 +++++++----------- src/gui_egui/components/shift_left_const.rs | 11 +- src/gui_egui/components/sz_extend.rs | 6 +- src/gui_egui/components/zero_extend.rs | 84 ++++++--- 9 files changed, 237 insertions(+), 288 deletions(-) diff --git a/src/gui_egui/components/and.rs b/src/gui_egui/components/and.rs index e16e6f54..2496a85d 100644 --- a/src/gui_egui/components/and.rs +++ b/src/gui_egui/components/and.rs @@ -14,7 +14,7 @@ impl EguiComponent for And { simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, - _clip_rect: Rect, + clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { // size of the component @@ -27,8 +27,11 @@ impl EguiComponent for And { (width, height), offset, scale, + clip_rect, |ui| { - ui.label(RichText::new("And").size(12f32 * scale)); + ui.centered_and_justified(|ui| { + ui.label(RichText::new("And").size(12f32 * scale)); + }); }, // This is a hack to stop the compiler from complaining // will hopefully be optimized away diff --git a/src/gui_egui/components/mips_branch_logic.rs b/src/gui_egui/components/mips_branch_logic.rs index a3292471..fa5eb662 100644 --- a/src/gui_egui/components/mips_branch_logic.rs +++ b/src/gui_egui/components/mips_branch_logic.rs @@ -1,9 +1,9 @@ -use crate::common::{EguiComponent, Simulator}; +use crate::common::{EguiComponent, Id, Ports, Simulator}; use crate::components::BranchLogic; -use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::{component_area, offset_helper}; -use egui::{Label, Pos2, Rect, Response, RichText, Ui, Vec2}; +use crate::gui_egui::helper::basic_component_gui; +use egui::{Rect, Response, RichText, Ui, Vec2}; #[typetag::serde] impl EguiComponent for BranchLogic { @@ -11,37 +11,59 @@ impl EguiComponent for BranchLogic { &self, ui: &mut Ui, _context: &mut EguiExtra, - _simulator: Option<&mut Simulator>, + simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, - _clip_rect: Rect, + clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { // size of the component - let width = 200f32; - let height: f32 = 20f32; - let rect = Rect::from_center_size( - (Pos2::from(self.pos) * scale + offset), - Vec2 { - x: width, - y: height, - } * scale, - ); - let r = component_area(self.id.to_string(), ui.ctx(), rect.center(), |ui| { - ui.set_height(rect.height()); - ui.set_width(rect.width()); - ui.group(|ui| { - ui.add_sized( - ui.available_size_before_wrap(), - // Change string here for another name - Label::new(RichText::new("branch_logic").size(12f32 * scale)), - ) - }) - .response - }) - .inner; + let width = 100f32; + let height: f32 = 12f32; + basic_component_gui( + self, + &simulator, + ui.ctx(), + (width, height), + offset, + scale, + clip_rect, + |ui| { + ui.centered_and_justified(|ui| { + ui.label(RichText::new("Branch Logic").size(12f32 * scale)); + }); + }, + // This is a hack to stop the compiler from complaining + // will hopefully be optimized away + None::>, + ) + } - Some(vec![r]) + fn render_editor( + &mut self, + ui: &mut egui::Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: egui::Vec2, + scale: f32, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + self.render( + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ); + EditorRenderReturn { + delete: false, + resp: None, + } } fn set_pos(&mut self, pos: (f32, f32)) { @@ -51,4 +73,8 @@ impl EguiComponent for BranchLogic { fn get_pos(&self) -> (f32, f32) { self.pos } + + fn top_padding(&self) -> f32 { + 20f32 + } } diff --git a/src/gui_egui/components/mips_controll_unit.rs b/src/gui_egui/components/mips_controll_unit.rs index 91e5e621..1b3786c4 100644 --- a/src/gui_egui/components/mips_controll_unit.rs +++ b/src/gui_egui/components/mips_controll_unit.rs @@ -14,12 +14,12 @@ impl EguiComponent for ControlUnit { simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, - _clip_rect: Rect, + clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { // size of the component let width = 400f32; - let height: f32 = 0f32; + let height: f32 = 12f32; basic_component_gui( self, &simulator, @@ -27,8 +27,11 @@ impl EguiComponent for ControlUnit { (width, height), offset, scale, + clip_rect, |ui| { - ui.label(RichText::new("Control Unit").size(12f32 * scale)); + ui.centered_and_justified(|ui| { + ui.label(RichText::new("Control Unit").size(12f32 * scale)); + }); }, // This is a hack to stop the compiler from complaining // will hopefully be optimized away diff --git a/src/gui_egui/components/mips_instruction_splitter.rs b/src/gui_egui/components/mips_instruction_splitter.rs index 64232b8e..d9531a1d 100644 --- a/src/gui_egui/components/mips_instruction_splitter.rs +++ b/src/gui_egui/components/mips_instruction_splitter.rs @@ -1,13 +1,9 @@ -use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::common::{EguiComponent, Id, Ports, Simulator}; use crate::components::InstrSplit; -use crate::gui_egui::component_ui::{ - drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, - rect_with_hover, visualize_ports, -}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::offset_helper; -use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; +use crate::gui_egui::helper::basic_component_gui; +use egui::{Rect, Response, RichText, Ui, Vec2}; #[typetag::serde] impl EguiComponent for InstrSplit { @@ -19,74 +15,43 @@ impl EguiComponent for InstrSplit { offset: Vec2, scale: f32, clip_rect: Rect, - editor_mode: EditorMode, + _editor_mode: EditorMode, ) -> Option> { - // 81x41 - // middle: 41x 21y (0 0) - let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; - let offset_old = offset; - let mut offset = offset; - offset.x += self.pos.0 * scale; - offset.y += self.pos.1 * scale; - let s = scale; - let o = offset; - // The shape - ui.painter().add(Shape::closed_line( - vec![ - oh((-40f32, 0f32), s, o), - oh((40f32, 0f32), s, o), - oh((40f32, 20f32), s, o), - oh((-40f32, 20f32), s, o), - ], - Stroke { - width: scale, - color: Color32::RED, - }, - )); - - let rect = Rect { - min: oh((-40f32, -20f32), s, o), - max: oh((40f32, 20f32), s, o), - }; - let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - ui.label(format!("Id: {}", self.id.clone())); - // todo: is this actually correct? - if let Some(s) = &simulator { - ui.label({ - let a_r: Result = - s.get_input_value(&self.instruction_in).try_into(); - let mut s: String = "".to_string(); - - match a_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", a_r), - } - format!("{}", s) + // size of the component + let width = 50f32; + let height: f32 = 300f32; + basic_component_gui( + self, + &simulator, + ui.ctx(), + (width, height), + offset, + scale, + clip_rect, + |ui| { + ui.centered_and_justified(|ui| { + ui.label(RichText::new("instruction\nspliter").size(12f32 * scale)); }); - ui.label("InstrSplit"); - } - }); - match editor_mode { - EditorMode::Simulator => (), - _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), - } - Some(vec![r]) + }, + // This is a hack to stop the compiler from complaining + // will hopefully be optimized away + None::>, + ) } fn render_editor( &mut self, - ui: &mut Ui, + ui: &mut egui::Ui, context: &mut EguiExtra, simulator: Option<&mut Simulator>, - offset: Vec2, + offset: egui::Vec2, scale: f32, - clip_rect: Rect, - id_ports: &[(crate::common::Id, Ports)], - grid: &GridOptions, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { - let r_vec = InstrSplit::render( - self, + self.render( ui, context, simulator, @@ -94,62 +59,13 @@ impl EguiComponent for InstrSplit { scale, clip_rect, editor_mode, - ) - .unwrap(); - let resp = &r_vec[0]; - let delete = drag_logic( - ui.ctx(), - resp, - &mut self.pos, - &mut context.pos_tmp, - scale, - offset, - grid, - ); - - properties_window( - ui, - self.id.clone(), - resp, - &mut context.properties_window, - |ui| { - let mut clicked_dropdown = false; - input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_drag_value(ui, &mut self.pos); - clicked_dropdown |= input_selector( - ui, - &mut self.instruction_in, - crate::components::CLK_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown - }, ); EditorRenderReturn { - delete, - resp: Some(r_vec), + delete: false, + resp: None, } } - fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { - let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![ - ( - crate::components::SEXT_IN_ID.to_string(), - Pos2::new(-40f32, 0f32) + own_pos, - ), - ( - crate::components::SEXT_OUT_ID.to_string(), - Pos2::new(40f32, 0f32) + own_pos, - ), - ] - } - - fn top_padding(&self) -> f32 { - 20f32 - } - fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } @@ -157,4 +73,8 @@ impl EguiComponent for InstrSplit { fn get_pos(&self) -> (f32, f32) { self.pos } + + fn top_padding(&self) -> f32 { + 20f32 + } } diff --git a/src/gui_egui/components/mips_jump_merge.rs b/src/gui_egui/components/mips_jump_merge.rs index f8c24c7e..b992f316 100644 --- a/src/gui_egui/components/mips_jump_merge.rs +++ b/src/gui_egui/components/mips_jump_merge.rs @@ -14,12 +14,12 @@ impl EguiComponent for JumpMerge { simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, - _clip_rect: Rect, + clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { // size of the component let width = 100f32; - let height: f32 = 0f32; + let height: f32 = 12f32; basic_component_gui( self, &simulator, @@ -27,8 +27,11 @@ impl EguiComponent for JumpMerge { (width, height), offset, scale, + clip_rect, |ui| { - ui.label(RichText::new("Jump Merge").size(12f32 * scale)); + ui.centered_and_justified(|ui| { + ui.label(RichText::new("Jump Merge").size(12f32 * scale)); + }); }, // This is a hack to stop the compiler from complaining // will hopefully be optimized away diff --git a/src/gui_egui/components/mips_reg_file.rs b/src/gui_egui/components/mips_reg_file.rs index b9047340..564345df 100644 --- a/src/gui_egui/components/mips_reg_file.rs +++ b/src/gui_egui/components/mips_reg_file.rs @@ -1,13 +1,9 @@ -use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::common::{EguiComponent, Simulator}; use crate::components::{RegFile, RegFormat}; -use crate::gui_egui::component_ui::{rect_with_hover, visualize_ports}; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::editor::EditorMode; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::{component_area, offset_helper}; -use egui::{ - scroll_area, Color32, ComboBox, Pos2, Rect, Response, RichText, ScrollArea, Shape, Slider, - Stroke, Ui, Vec2, -}; +use crate::gui_egui::helper::basic_component_gui; +use egui::{ComboBox, Rect, Response, RichText, ScrollArea, Ui, Vec2}; const REG_NAMES: [&str; 32] = [ "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", @@ -25,42 +21,27 @@ impl EguiComponent for RegFile { offset: Vec2, scale: f32, clip_rect: Rect, - editor_mode: EditorMode, + _editor_mode: EditorMode, ) -> Option> { - let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; - let offset_old = offset; - let mut offset = offset; - offset.x += self.pos.0 * scale; - offset.y += self.pos.1 * scale; - let s = scale; - let o = offset; - - let rs: u32; - let rt: u32; - if let Some(sim) = simulator { - rs = sim.get_input_value(&self.rs_address_in).try_into().unwrap(); - rt = sim.get_input_value(&self.rt_address_in).try_into().unwrap(); - } else { - rs = 32; // register that dont exist - rt = 32; // - } - // The shape - let rect = Rect { - min: oh((-60f32, -90f32), s, o), - max: oh((60f32, 90f32), s, o), - }; - - component_area(self.id.to_string(), ui.ctx(), offset.to_pos2(), |ui| { - ui.style_mut().visuals.panel_fill = Color32::LIGHT_BLUE; - ui.set_height(rect.height()); - ui.set_width(rect.width()); - ui.group(|ui| { - let mut tmp: RegFormat = self.reg_format.borrow().clone(); + basic_component_gui( + self, + &simulator, + ui.ctx(), + (120f32, 400f32), + offset, + scale, + clip_rect, + |ui| { ui.label(RichText::new("Register File").size(12f32 * scale)); + + // A toggle button for showing register names ui.toggle_value( &mut *self.show_reg_names.borrow_mut(), RichText::new("Show names").size(12f32 * scale), ); + + // showsing the display format of the register + let mut tmp: RegFormat = self.reg_format.borrow().clone(); ComboBox::from_id_source(&self.id) .selected_text(RichText::new(format!("{:?}", tmp)).size(12f32 * scale)) .show_ui(ui, |ui| { @@ -74,71 +55,53 @@ impl EguiComponent for RegFile { *self.reg_format.borrow_mut() = tmp; ui.separator(); - ScrollArea::vertical() - .max_height(rect.height()) - .max_width(rect.width()) - .show(ui, |ui| { - ui.set_width(ui.available_width()); - let mut str: String = "".into(); - for (i, val) in self.registers.borrow().iter().enumerate() { - str.push_str( - match *self.show_reg_names.borrow() { - true => format!("{:<4}", REG_NAMES[i]), - false => format!("r{:<3}", i), - } - .as_str(), - ); - str.push_str( - match *self.reg_format.borrow() { - RegFormat::Hex => format!("{:#010x}", val), - RegFormat::DecSigned => format!("{}", (*val) as i32), - RegFormat::DecUnsigned => format!("{}", val), - RegFormat::Bin => format!("{:#034b}", val), - RegFormat::UTF8BE => { - String::from_utf8_lossy(&val.to_be_bytes()) - .escape_debug() - .to_string() - } - RegFormat::UTF8LE => { - String::from_utf8_lossy(&val.to_le_bytes()) - .escape_debug() - .to_string() - } - } - .as_str(), - ); - str.push_str("\n") - } - ui.label(RichText::new(str).size(12f32 * scale).monospace()) - }) - }); - }); - // r1.union(r2.) - // .inner - // .response - // .on_hover_ui(|ui| { - // ui.label("on_hover"); - // }); - match editor_mode { - EditorMode::Simulator => (), - _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), - } - None - } + // A scroll area with all the registers in one label + ScrollArea::vertical().show(ui, |ui| { + ui.set_width(ui.available_width()); + ui.set_height(ui.available_height()); + + // for each register format the u32 and pus that formatted sting onto + // the string representing all registers + let mut str: String = "".into(); + for (i, val) in self.registers.borrow().iter().enumerate() { + // add reg name or reg number to the formatted string + str.push_str( + match *self.show_reg_names.borrow() { + true => format!("{:<4}", REG_NAMES[i]), + false => format!("r{:<3}", i), + } + .as_str(), + ); + + // add a formatted register to the string + // TODO move to separate function + str.push_str( + match *self.reg_format.borrow() { + RegFormat::Hex => format!("{:#010x}", val), + RegFormat::DecSigned => format!("{}", (*val) as i32), + RegFormat::DecUnsigned => format!("{}", val), + RegFormat::Bin => format!("{:#034b}", val), + RegFormat::UTF8BE => String::from_utf8_lossy(&val.to_be_bytes()) + .escape_debug() + .to_string(), + RegFormat::UTF8LE => String::from_utf8_lossy(&val.to_le_bytes()) + .escape_debug() + .to_string(), + } + .as_str(), + ); + str.push_str("\n") + } - fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { - let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![ - ( - crate::components::SEXT_IN_ID.to_string(), - Pos2::new(-40f32, 0f32) + own_pos, - ), - ( - crate::components::SEXT_OUT_ID.to_string(), - Pos2::new(40f32, 0f32) + own_pos, - ), - ] + // push the string as monospace to the ui + ui.label(RichText::new(str).size(12f32 * scale).monospace()) + }); + }, + // compiler hack to allow None + // will hopefully be optimized away + None::>, + ) } fn top_padding(&self) -> f32 { diff --git a/src/gui_egui/components/shift_left_const.rs b/src/gui_egui/components/shift_left_const.rs index 43fcb0d3..41c6eba6 100644 --- a/src/gui_egui/components/shift_left_const.rs +++ b/src/gui_egui/components/shift_left_const.rs @@ -14,12 +14,12 @@ impl EguiComponent for ShiftConst { simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, - _clip_rect: Rect, + clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { // size of the component let width = 100f32; - let height: f32 = 0f32; + let height: f32 = 12f32; basic_component_gui( self, &simulator, @@ -27,8 +27,13 @@ impl EguiComponent for ShiftConst { (width, height), offset, scale, + clip_rect, |ui| { - ui.label(RichText::new(format!("Shift << {}", self.shift_by)).size(12f32 * scale)); + ui.centered_and_justified(|ui| { + ui.label( + RichText::new(format!("Shift << {}", self.shift_by)).size(12f32 * scale), + ); + }); }, // This is a hack to stop the compiler from complaining // will hopefully be optimized away diff --git a/src/gui_egui/components/sz_extend.rs b/src/gui_egui/components/sz_extend.rs index 14d5f542..205d2857 100644 --- a/src/gui_egui/components/sz_extend.rs +++ b/src/gui_egui/components/sz_extend.rs @@ -3,7 +3,6 @@ use crate::components::SignZeroExtend; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::basic_component_gui; -use crate::simulator; use egui::{Rect, Response, RichText, Ui, Vec2}; #[typetag::serde] @@ -15,12 +14,12 @@ impl EguiComponent for SignZeroExtend { simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, - _clip_rect: Rect, + clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { // size of the component let width = 100f32; - let height: f32 = 0f32; + let height: f32 = 12f32; basic_component_gui( self, &simulator, @@ -28,6 +27,7 @@ impl EguiComponent for SignZeroExtend { (width, height), offset, scale, + clip_rect, |ui| { match &simulator { Some(sim) => { diff --git a/src/gui_egui/components/zero_extend.rs b/src/gui_egui/components/zero_extend.rs index 6d8310c4..a6e1a7c5 100644 --- a/src/gui_egui/components/zero_extend.rs +++ b/src/gui_egui/components/zero_extend.rs @@ -1,9 +1,9 @@ -use crate::common::{EguiComponent, Simulator}; +use crate::common::{EguiComponent, Id, Ports, Simulator}; use crate::components::ZeroExtend; -use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::{component_area, offset_helper}; -use egui::{Label, Pos2, Rect, Response, RichText, Ui, Vec2}; +use crate::gui_egui::helper::basic_component_gui; +use egui::{Rect, Response, RichText, Ui, Vec2}; #[typetag::serde] impl EguiComponent for ZeroExtend { @@ -11,37 +11,59 @@ impl EguiComponent for ZeroExtend { &self, ui: &mut Ui, _context: &mut EguiExtra, - _simulator: Option<&mut Simulator>, + simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, - _clip_rect: Rect, + clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { // size of the component - let width = 200f32; - let height: f32 = 20f32; - let rect = Rect::from_center_size( - (Pos2::from(self.pos) * scale + offset), - Vec2 { - x: width, - y: height, - } * scale, - ); - let r = component_area(self.id.to_string(), ui.ctx(), rect.center(), |ui| { - ui.set_height(rect.height()); - ui.set_width(rect.width()); - ui.group(|ui| { - ui.add_sized( - ui.available_size_before_wrap(), - // Change string here for another name - Label::new(RichText::new("zero_extend").size(12f32 * scale)), - ) - }) - .response - }) - .inner; + let width = 100f32; + let height: f32 = 12f32; + basic_component_gui( + self, + &simulator, + ui.ctx(), + (width, height), + offset, + scale, + clip_rect, + |ui| { + ui.centered_and_justified(|ui| { + ui.label(RichText::new("Zero Extend").size(12f32 * scale)); + }); + }, + // This is a hack to stop the compiler from complaining + // will hopefully be optimized away + None::>, + ) + } - Some(vec![r]) + fn render_editor( + &mut self, + ui: &mut egui::Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: egui::Vec2, + scale: f32, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + self.render( + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ); + EditorRenderReturn { + delete: false, + resp: None, + } } fn set_pos(&mut self, pos: (f32, f32)) { @@ -51,4 +73,8 @@ impl EguiComponent for ZeroExtend { fn get_pos(&self) -> (f32, f32) { self.pos } + + fn top_padding(&self) -> f32 { + 20f32 + } } From b463d5c3d69ff84f14de905a84cf77a084a81b3e Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 14 Aug 2024 13:49:42 +0200 Subject: [PATCH 048/126] added a struct that can read from an elf --- src/components/mips_mem_struct.rs | 206 ++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 src/components/mips_mem_struct.rs diff --git a/src/components/mips_mem_struct.rs b/src/components/mips_mem_struct.rs new file mode 100644 index 00000000..7e6f864b --- /dev/null +++ b/src/components/mips_mem_struct.rs @@ -0,0 +1,206 @@ +use elf::{endian::AnyEndian, ElfBytes}; +use std::{ + collections::{BTreeMap, HashMap}, + fs, + path::PathBuf, +}; + +/// A men contains two fields. One with the memory mapped data in a BTreeMap. +/// And a hashmap with symbols. +#[derive(Default)] +pub struct Mem { + symbols: HashMap, + data: BTreeMap, +} +pub enum MemGetSize { + Byte, + Half, + Word, +} + +impl Mem { + /// This function constructs a Mem struct using the elf sections to load the data. + /// This may be un-reliable as the Elf might not always contain the sections, + /// or contain un-relevant sections and no relevant ones + /// # TODO fix result error. currently panics + pub fn from_sections(elf_bytes: &[u8]) -> Result { + let mut mem: Mem = Mem { + symbols: HashMap::new(), + data: BTreeMap::new(), + }; + + let file = ElfBytes::::minimal_parse(elf_bytes).unwrap(); + + // for each section in elf + for sect in file.section_headers().unwrap() { + // if the section has flag alloc(0x2), aka lives in memory + // if the section has a size larger than zero + if sect.sh_flags & 0x2 == 0x2 && sect.sh_size != 0 { + let elf_address = sect.sh_offset; // offset into elf file where data is stored (note inside of elf Segment) + let elf_end_address = elf_address + sect.sh_size; // end address of data + let v_address = sect.sh_addr as u32; + let sect_data = &elf_bytes[elf_address as usize..elf_end_address as usize]; + for (i, byte) in sect_data.into_iter().enumerate() { + mem.data.insert(v_address + i as u32, byte.to_owned()); + } + } + } + mem.get_symbols(&file); + Ok(mem) + } + + /// This function gets the data at that location + pub fn get_unaligned( + &self, + address: u32, + size: MemGetSize, + sign_extend: bool, + big_endian: bool, + ) -> u32 { + let size_int: usize = match size { + MemGetSize::Byte => 1, + MemGetSize::Half => 2, + MemGetSize::Word => 4, + }; + let bytes: Vec = (0..size_int) + .map(|i| *self.data.get(&(address + i as u32)).unwrap_or(&0)) + .collect(); + + match size { + MemGetSize::Byte => { + if sign_extend { + // first make byte an i8 + // then when cast to i32 to sign extends + // convert to u32 as final return + bytes[0] as i8 as i32 as u32 + } else { + bytes[0] as u32 + } + } + MemGetSize::Half => { + if sign_extend { + let int_16 = if big_endian { + i16::from_be_bytes(bytes.try_into().unwrap()) + } else { + i16::from_le_bytes(bytes.try_into().unwrap()) + }; + // as i32 to get sign extended i32, and as u32 to get return type + int_16 as i32 as u32 + } else { + let uint_16: u16 = if big_endian { + u16::from_be_bytes(bytes.try_into().unwrap()) + } else { + u16::from_le_bytes(bytes.try_into().unwrap()) + }; + uint_16 as u32 + } + } + MemGetSize::Word => { + if sign_extend { + let int_32 = if big_endian { + i32::from_be_bytes(bytes.try_into().unwrap()) + } else { + i32::from_le_bytes(bytes.try_into().unwrap()) + }; + int_32 as u32 + } else { + if big_endian { + u32::from_be_bytes(bytes.try_into().unwrap()) + } else { + u32::from_le_bytes(bytes.try_into().unwrap()) + } + } + } + } + } + + /// This function gets the data at that location, return error on miss aligned address + pub fn get( + &self, + address: u32, + size: MemGetSize, + sign_extend: bool, + big_endian: bool, + ) -> Result { + let size_int: u32 = match size { + MemGetSize::Byte => 1, + MemGetSize::Half => 2, + MemGetSize::Word => 4, + }; + if address % size_int != 0 { + Err(()) + } else { + Ok(self.get_unaligned(address, size, sign_extend, big_endian)) + } + } + + /// Gets the elf symbol table, and set the self hashmap + fn get_symbols(&mut self, elf_file: &ElfBytes) { + match elf_file.symbol_table().unwrap() { + Some((sym_table, string_table)) => { + let mut sym_hash_map: HashMap = HashMap::new(); + + // for each symbol entry + for sym_entry in sym_table { + let sym_name = string_table.get(sym_entry.st_name as usize).unwrap(); + + // if the symboltype is NOTYPE and has a string add it + if sym_entry.st_symtype() == 0x0 && sym_name != "" { + sym_hash_map.insert(sym_entry.st_value as u32, sym_name.to_string()); + } + } + self.symbols = sym_hash_map + } + None => (), + } + } + /// Will truncate the data to the given size and write the data to memory + pub fn write(&mut self, address: u32, data: u32, size: MemGetSize, big_endian: bool) { + match size { + MemGetSize::Byte => { + self.data.insert(address, data as u8); + } + MemGetSize::Half => { + let uint_16 = data as u16; + let bytes = if big_endian { + uint_16.to_be_bytes() + } else { + uint_16.to_le_bytes() + }; + self.data.insert(address, bytes[0]); + self.data.insert(address + 1, bytes[1]); + } + MemGetSize::Word => { + let bytes = if big_endian { + data.to_be_bytes() + } else { + data.to_le_bytes() + }; + bytes.iter().enumerate().for_each(|(i, byte)| { + self.data.insert(address + i as u32, byte.to_owned()); + }); + } + } + } + /// will return error if the data is not aligned + /// will truncate the data to size and write to memory + pub fn write_aligned( + &mut self, + address: u32, + data: u32, + size: MemGetSize, + big_endian: bool, + ) -> Result<(), ()> { + let size_int: u32 = match size { + MemGetSize::Byte => 1, + MemGetSize::Half => 2, + MemGetSize::Word => 4, + }; + if address % size_int != 0 { + Err(()) + } else { + self.write(address, data, size, big_endian); + Ok(()) + } + } +} From aa0e5e54306d2e3386a84236d8a7aafc3d33f0d8 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 15 Aug 2024 15:07:56 +0200 Subject: [PATCH 049/126] added comments to memory implementation --- src/components/mem.rs | 44 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/src/components/mem.rs b/src/components/mem.rs index a3f7e617..a5d7daf0 100644 --- a/src/components/mem.rs +++ b/src/components/mem.rs @@ -136,21 +136,44 @@ impl Memory { Memory(Rc::new(RefCell::new(data))) } - fn align(&self, addr: usize, size: usize) -> SignalValue { + /// Aligns a memory address to the size + /// # Example + /// ``` + /// use syncrim::components::Memory; + /// use syncrim::signal::SignalValue; + /// + /// let mem = Memory::default(); // creates a memory with only zeros + /// + /// let align_addrs = mem.align(0xa3f5, 4); + /// assert_eq!(SignalValue::from(0xa3f4), align_addrs) + /// ``` + pub fn align(&self, addr: usize, size: usize) -> SignalValue { ((addr % size != 0) as SignalUnsigned).into() } - fn read(&self, addr: usize, size: usize, sign: bool, big_endian: bool) -> SignalValue { + /// This function reads 1, 2, 4 bytes from the memory, + /// and converts them to a SignalValue using the a big_endian and sign arguments + /// + /// # Panics + /// This function panics if the argument size is NOT 1, 2 or 4 + /// # TODO + /// - maybe make size an enum? + pub fn read(&self, addr: usize, size: usize, sign: bool, big_endian: bool) -> SignalValue { + // Read amount of bytes determined by size, and add them them a vector let data: Vec = (0..size) .map(|i| *self.0.borrow().get(&(addr + i)).unwrap_or(&0)) .collect(); + // why convert to a slice? let data = data.as_slice(); trace!("{:x?}", data); + let tmp: SignalValue = 0x34.into(); + match size { 1 => { + // Loading one byte if sign { data[0] as i8 as SignalSigned as SignalUnsigned } else { @@ -158,8 +181,10 @@ impl Memory { } } 2 => { + // Loading half word, most stuff here is for tracing and degbuggning if sign { if big_endian { + // sign big endian trace!("read signed half word be"); let i_16 = i16::from_be_bytes(data.try_into().unwrap()); trace!("i_16 {:x?}", i_16); @@ -167,6 +192,7 @@ impl Memory { trace!("i_32 {:x?}", i_32); i_32 as SignalUnsigned } else { + // sign little endian trace!("read signed half word le"); let i_16 = i16::from_le_bytes(data.try_into().unwrap()); trace!("i_16 {:x?}", i_16); @@ -175,6 +201,7 @@ impl Memory { i_32 as SignalUnsigned } } else if big_endian { + // unsigned big endian trace!("read unsigned half word be"); let u_16 = u16::from_be_bytes(data.try_into().unwrap()); trace!("u_16 {:x?}", u_16); @@ -182,6 +209,7 @@ impl Memory { trace!("u_32 {:x?}", u_32); u_32 as SignalUnsigned } else { + // unsigned little endian trace!("read unsigned half word le"); let u_16 = u16::from_le_bytes(data.try_into().unwrap()); trace!("u_16 {:x?}", u_16); @@ -191,6 +219,7 @@ impl Memory { } } 4 => { + // Load full word if sign { if big_endian { i32::from_be_bytes(data.try_into().unwrap()) as SignalUnsigned @@ -205,10 +234,17 @@ impl Memory { } _ => panic!("illegal sized memory operation"), } - .into() + .into() // Convert to SignalValue } - fn write(&self, addr: usize, size: usize, big_endian: bool, data: SignalValue) { + /// This function writes 1, 2, 4 bytes from the memory, + /// using the a big_endian arguments + /// + /// # Panics + /// This function panics if the argument size is NOT 1, 2 or 4 + /// # TODO + /// - maybe make size an enum? + pub fn write(&self, addr: usize, size: usize, big_endian: bool, data: SignalValue) { let data: SignalUnsigned = data.try_into().unwrap(); match size { 1 => { From bfe23f10c9d81cd5301cf75b475ee8c0e0a249ee Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Fri, 16 Aug 2024 11:27:20 +0200 Subject: [PATCH 050/126] added component to see if 2 signals are equal --- src/components/equals.rs | 89 ++++++++++++++++++++++++++++++++ src/components/mod.rs | 2 + src/gui_egui/components/equal.rs | 80 ++++++++++++++++++++++++++++ src/gui_egui/components/mod.rs | 1 + 4 files changed, 172 insertions(+) create mode 100644 src/components/equals.rs create mode 100644 src/gui_egui/components/equal.rs diff --git a/src/components/equals.rs b/src/components/equals.rs new file mode 100644 index 00000000..02b07228 --- /dev/null +++ b/src/components/equals.rs @@ -0,0 +1,89 @@ +//TODO: add so it can take undefiend number of inputs +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, + SignalValue, Simulator, +}; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::rc::Rc; +pub const EQUAL_A_IN_ID: &str = "a_in"; +pub const EQUAL_B_IN_ID: &str = "b_in"; + +pub const EQUAL_OUT_ID: &str = "out"; + +#[derive(Serialize, Deserialize, Clone)] +pub struct Equal { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) a_in: Input, + pub(crate) b_in: Input, +} + +#[typetag::serde] +impl Component for Equal { + fn to_(&self) { + trace!("Equal"); + } + + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![ + &InputPort { + port_id: EQUAL_A_IN_ID.to_string(), + input: self.a_in.clone(), + }, + &InputPort { + port_id: EQUAL_B_IN_ID.to_string(), + input: self.b_in.clone(), + }, + ], + OutputType::Combinatorial, + vec![EQUAL_OUT_ID], + ), + ) + } + + // propagate addition to output + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get input values + let a_in: u32 = simulator.get_input_value(&self.a_in).try_into().unwrap(); + let b_in: u32 = simulator.get_input_value(&self.b_in).try_into().unwrap(); + + let result: u32 = (a_in == b_in) as u32; + + simulator.set_out_value(&self.id, EQUAL_OUT_ID, SignalValue::Data(result)); + Ok(()) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + EQUAL_A_IN_ID => self.a_in = new_input, + EQUAL_B_IN_ID => self.b_in = new_input, + _ => (), + } + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl Equal { + pub fn new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input) -> Self { + Equal { + id: id.to_string(), + pos, + a_in, + b_in, + } + } + + pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input) -> Rc { + Rc::new(Equal::new(id, pos, a_in, b_in)) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index a026d07d..453b1345 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -3,6 +3,7 @@ mod and; mod clk; mod constant; mod cross; +mod equals; mod full_adder; mod mem; mod mips_branch_logic; @@ -29,6 +30,7 @@ pub use and::*; pub use clk::*; pub use constant::*; pub use cross::*; +pub use equals::*; pub use full_adder::*; pub use mem::*; pub use mips_branch_logic::*; diff --git a/src/gui_egui/components/equal.rs b/src/gui_egui/components/equal.rs new file mode 100644 index 00000000..b3af8026 --- /dev/null +++ b/src/gui_egui/components/equal.rs @@ -0,0 +1,80 @@ +use crate::common::{EguiComponent, Id, Ports, Simulator}; +use crate::components::Equal; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::basic_component_gui; +use egui::{Rect, Response, RichText, Ui, Vec2}; + +#[typetag::serde] +impl EguiComponent for Equal { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + _editor_mode: EditorMode, + ) -> Option> { + // size of the component + let width = 100f32; + let height: f32 = 0f32; + basic_component_gui( + self, + &simulator, + ui.ctx(), + (width, height), + offset, + scale, + clip_rect, + |ui| { + ui.centered_and_justified(|ui| { + ui.label(RichText::new("Equal").size(12f32 * scale)); + }); + }, + // This is a hack to stop the compiler from complaining + // will hopefully be optimized away + None::>, + ) + } + + fn render_editor( + &mut self, + ui: &mut egui::Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: egui::Vec2, + scale: f32, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + self.render( + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ); + EditorRenderReturn { + delete: false, + resp: None, + } + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } + + fn top_padding(&self) -> f32 { + 20f32 + } +} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index ec25de84..5697e48b 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -3,6 +3,7 @@ mod and; mod clk; mod constant; mod cross; +mod equal; mod full_adder; mod mem; mod mips_branch_logic; From a9271636c6354d8cfc83e90106edd3c9ac696f9b Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Fri, 16 Aug 2024 14:49:29 +0200 Subject: [PATCH 051/126] added mips_pipe wihtout DM and IM --- examples/mips_pipe_example_1.rs | 401 ++++++++++++++++++++++++++++++++ 1 file changed, 401 insertions(+) create mode 100644 examples/mips_pipe_example_1.rs diff --git a/examples/mips_pipe_example_1.rs b/examples/mips_pipe_example_1.rs new file mode 100644 index 00000000..0f31f72d --- /dev/null +++ b/examples/mips_pipe_example_1.rs @@ -0,0 +1,401 @@ +// use crate::src::components::cntr_unit_signals; +use std::path::PathBuf; +use std::rc::Rc; +use syncrim::common::EguiComponent; +#[cfg(feature = "gui-egui")] +use syncrim::gui_egui::editor::Library; +use syncrim::{ + common::{ComponentStore, Input}, + components::*, + fern::fern_setup, + mips_helper_functions::autowire, +}; + +fn main() { + fern_setup(); + let cs = ComponentStore { + store: vec![ + // register that holds instr addr + Register::rc_new("pc", (2000.0, 5000.0), Input::new("mux_jump_merge", "out")), + // step addr from reg by 4 + Constant::rc_new("+4", (2000.0, 5100.0), 4), + Add::rc_new( + "pc+4", + (2200.0, 5000.0), + Input::new("pc", "out"), + Input::new("+4", "out"), + ), + // + // + // + // MUX to choose what intruction addr to choose from, branch jump, reg, pc+4 + Mux::rc_new( + "mux_jump_merge", + (1800.0, 5000.0), + Input::new("branch", BRANCH_OUT_ID), + vec![ + Input::new("pc_add_branch", FULL_ADD_OUT_ID), //TODO: describe origin + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), // goes to addr, RD2 + Input::new("merge_reg", REGISTER_OUT_ID), // + Input::new("pc+4", CLK_OUT_ID), + ], + ), + // + // merges to find out jump location + JumpMerge::rc_new( + "jump_merge", + (1700.0, 5300.0), + Input::new("pc", REGISTER_OUT_ID), //input from reg before pc+4 + Input::new("dummy", "out"), //input from instruction mem + ), + // + // + Register::rc_new( + //TODO: continue the chain of regs + "pc+4_reg", + (2300.0, 5000.0), + Input::new("pc+4", ADD_OUT_ID), + ), + // + Register::rc_new( + "InMem_reg", + (2300.0, 5200.0), + Input::new("dummy", "out"), //TODO: im + ), + // + Register::rc_new( + "merge_reg", + (2300.0, 5300.0), + Input::new("jump_merge", MERGE_OUT_ID), + ), + // + // splits intructions from ir to fields + InstrSplit::rc_new( + "instruction_split", + (2400.0, 4000.0), + Input::new("InMem_reg", REGISTER_OUT_ID), + ), //TODO: take im input + // + //TODO: add 3 more contrill units and rewire + // First CU, handles, selcet for signzero_extend and mux_write_addr + ControlUnit::rc_new( + "control_unit_1", + (3250.0, 1500.0), + Input::new("InMem_reg", REGISTER_OUT_ID), + ), + // + // Second CU, handles, mux_source_a, mux_source_b and the alu + ControlUnit::rc_new( + "control_unit_2", + (3550.0, 1500.0), + Input::new("control_EX_reg", REGISTER_OUT_ID), + ), + // + // Third CU, handles, write_back_mux, and DMs memread and memwrite + ControlUnit::rc_new( + "control_unit_3", + (4300.0, 1500.0), + Input::new("control_MEM_reg", REGISTER_OUT_ID), + ), + // + // Fourth CU, handles, WE for reg_file in the WB stage + ControlUnit::rc_new( + "control_unit_4", + (4500.0, 1500.0), + Input::new("control_WB_reg", REGISTER_OUT_ID), + ), + // + // + // extends immediate field + SignZeroExtend::rc_new( + "signzero_extend", + (2600.0, 5100.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_IMMEDIATE_ID), + Input::new("control_unit_1", cntr_field::EXTEND_SELECT_OUT), // cu tells it to either sing- or zero- extend + ), + // + // + RegFile::rc_new( + "reg_file", + (3100.0, 2000.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + Input::new("reg_addr_reg", REGISTER_OUT_ID), //write address + Input::new("result_reg_EX", REGISTER_OUT_ID), //write data + Input::new("control_unit_4", cntr_field::REG_WRITE_ENABLE_OUT), + ), + // + // + Equal::rc_new( + "equals_operand_A", + (3200.0, 1700.0), + Input::new("reg_addr_MEM_reg", REGISTER_OUT_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), + ), + // + Mux::rc_new( + "operand_A_mux_1", + (3200.0, 1800.0), + Input::new("equals_operand_A", EQUAL_OUT_ID), + vec![ + Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), + Input::new("write_back_mux", MUX_OUT_ID), + ], + ), + // + // + Equal::rc_new( + "equals_operand_B", + (3200.0, 2300.0), + Input::new("reg_addr_MEM_reg", REGISTER_OUT_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + ), + // + Mux::rc_new( + "operand_B_mux_1", + (3200.0, 2200.0), + Input::new("equals_operand_B", EQUAL_OUT_ID), + vec![ + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), + Input::new("write_back_mux", MUX_OUT_ID), + ], + ), + // + // + Equal::rc_new( + "equals_operand_A_2", + (3300.0, 1700.0), + Input::new("reg_addr_EX_reg", REGISTER_OUT_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), + ), + // + Mux::rc_new( + "operand_A_mux_2", + (3300.0, 1800.0), + Input::new("equals_operand_A_2", EQUAL_OUT_ID), + vec![ + Input::new("operand_A_mux_1", MUX_OUT_ID), + Input::new("alu", FULL_ADD_OUT_ID), + ], + ), + // + // + Equal::rc_new( + "equals_operand_B_2", + (3300.0, 2300.0), + Input::new("reg_addr_EX_reg", REGISTER_OUT_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + ), + // + Mux::rc_new( + "operand_B_mux_2", + (3300.0, 2200.0), + Input::new("equals_operand_B_2", EQUAL_OUT_ID), + vec![ + Input::new("operand_B_mux_1", MUX_OUT_ID), + Input::new("alu", FULL_ADD_OUT_ID), + ], + ), + // + // + BranchLogic::rc_new( + "branch", + (3400.0, 2000.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_OP_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_FUNCT_ID), + Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), + ), + // + // + Register::rc_new( + //TODO: make 2 more controll units + "control_EX_reg", + (3450.0, 1400.0), + Input::new("InMem_reg", REGISTER_OUT_ID), + ), + // + Register::rc_new( + "zero_extend_reg", + (3450.0, 1600.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_SHAMT_ID), + ), + // + Register::rc_new( + //TODO: fix after adding 4 muxes + "operand_a_reg", + (3450.0, 1800.0), + Input::new("equals_operand_A_2", MUX_OUT_ID), + ), + // + Register::rc_new( + //TODO: fix after muxes + "operand_b_reg", + (3450.0, 2200.0), + Input::new("equals_operand_B_2", MERGE_OUT_ID), + ), + // + Register::rc_new( + "mux_b2_reg", + (3450.0, 5000.0), + Input::new("pc+4_reg", REGISTER_OUT_ID), + ), + Register::rc_new( + "mux_b3_reg", + (3450.0, 5100.0), + Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), + ), + // + Register::rc_new( + "reg_addr_EX_reg", + (3450.0, 5500.0), + Input::new("mux_write_addr", MUX_OUT_ID), + ), + // + // + ZeroExtend::rc_new( + "zero_extend_for_chamt", + (3700.0, 1600.0), + Input::new("zero_extend_reg", REGISTER_OUT_ID), + ), + // + // + Constant::rc_new("0_a_inp", (3800.0, 1700.0), 0), + Mux::rc_new( + "mux_source_a", + (3800.0, 1800.0), + Input::new("control_unit_2", cntr_field::ALU_SRC_A_OUT), + vec![ + Input::new("zero_extend_for_chamt", SIGNZEROEXTEND_OUT_ID), + Input::new("0_a_inp", "out"), + Input::new("operand_a_reg", REGISTER_OUT_ID), + ], + ), + // + // + Mux::rc_new( + "mux_source_b", + (3800.0, 2200.0), + Input::new("control_unit_2", cntr_field::ALU_SRC_B_OUT), + vec![ + Input::new("operand_b_reg", REGISTER_OUT_ID), + Input::new("mux_b2_reg", REGISTER_OUT_ID), + Input::new("mux_b3_reg", REGISTER_OUT_ID), + ], + ), + // + // + // + // + FullAdd::rc_new( + "alu", + (4100.0, 2000.0), + Input::new("mux_source_a", MUX_OUT_ID), + Input::new("mux_source_b", MUX_OUT_ID), + Input::new("control_unit_2", cntr_field::ALU_OP_OUT), + ), + // + // + Register::rc_new( + "control_MEM_reg", + (4200.0, 1400.0), + Input::new("control_EX_reg", REGISTER_OUT_ID), + ), + // + Register::rc_new( + "alu_reg", + (4200.0, 2000.0), + Input::new("alu", FULL_ADD_OUT_ID), + ), + // + Register::rc_new( + "data_MEM_reg", + (4200.0, 2500.0), + Input::new("operand_b_reg", REGISTER_OUT_ID), + ), + // + Register::rc_new( + "reg_addr_MEM_reg", + (4200.0, 5500.0), + Input::new("reg_addr_EX_reg", REGISTER_OUT_ID), + ), + // + // + Mux::rc_new( + "write_back_mux", + (4300.0, 2200.0), + Input::new("control_unit_3", cntr_field::REG_WRITE_SRC_OUT), + vec![ + Input::new("alu", FULL_ADD_OUT_ID), + Input::new("dummy", "out"), //TODO: data meme output + ], + ), + // + // + Register::rc_new( + "control_WB_reg", + (4400.0, 1400.0), + Input::new("control_MEM_reg", REGISTER_OUT_ID), + ), + // + Register::rc_new( + "result_reg_EX", + (4400.0, 2200.0), + Input::new("write_back_mux", MUX_OUT_ID), + ), + // + Register::rc_new( + "reg_addr_reg", + (4400.0, 5500.0), + Input::new("reg_addr_MEM_reg", REGISTER_OUT_ID), + ), + // + // + ShiftConst::rc_new( + "branch_shift", + (2900.0, 5250.0), + Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), + 2, + ), + // + // + Add::rc_new( + "pc_add_branch", + (3000.0, 5200.0), + Input::new("pc+4", ADD_OUT_ID), + Input::new("branch_shift", SHIFT_OUT_ID), + ), + // + // + Constant::rc_new("0x_1F", (3750.0, 5500.0), 0), + Mux::rc_new( + "mux_write_addr", + (3200.0, 5500.0), + Input::new("control_unit_1", cntr_field::REG_DEST_OUT), + vec![ + Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + Input::new("0x_1F", "out"), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RD_ID), + ], + ), + // + // + + // + // + Constant::rc_new("dummy", (6000.0, 3000.0), 0), + ], + }; + + let cs = autowire(cs); + + let path = PathBuf::from("add.json"); + cs.save_file(&path); + + #[cfg(feature = "gui-egui")] + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + + #[cfg(feature = "gui-vizia")] + syncrim::gui_vizia::gui(cs, &path); +} From eba7162224dc5324839cb73100a50f0451e8dbe3 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Mon, 19 Aug 2024 15:23:10 +0200 Subject: [PATCH 052/126] updated basic ui helper --- src/gui_egui/components/and.rs | 8 +- src/gui_egui/components/equal.rs | 8 +- src/gui_egui/components/mips_branch_logic.rs | 8 +- src/gui_egui/components/mips_controll_unit.rs | 3 - .../components/mips_instruction_splitter.rs | 3 - src/gui_egui/components/mips_jump_merge.rs | 8 +- src/gui_egui/components/mips_reg_file.rs | 3 - src/gui_egui/components/shift_left_const.rs | 8 +- src/gui_egui/components/sz_extend.rs | 8 +- src/gui_egui/components/zero_extend.rs | 8 +- src/gui_egui/helper.rs | 122 +++++++++++------- 11 files changed, 84 insertions(+), 103 deletions(-) diff --git a/src/gui_egui/components/and.rs b/src/gui_egui/components/and.rs index 2496a85d..dfbd82e3 100644 --- a/src/gui_egui/components/and.rs +++ b/src/gui_egui/components/and.rs @@ -17,14 +17,11 @@ impl EguiComponent for And { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - // size of the component - let width = 100f32; - let height: f32 = 0f32; basic_component_gui( self, &simulator, ui.ctx(), - (width, height), + (0f32, 0f32), offset, scale, clip_rect, @@ -33,9 +30,6 @@ impl EguiComponent for And { ui.label(RichText::new("And").size(12f32 * scale)); }); }, - // This is a hack to stop the compiler from complaining - // will hopefully be optimized away - None::>, ) } diff --git a/src/gui_egui/components/equal.rs b/src/gui_egui/components/equal.rs index b3af8026..830c6ce3 100644 --- a/src/gui_egui/components/equal.rs +++ b/src/gui_egui/components/equal.rs @@ -17,14 +17,11 @@ impl EguiComponent for Equal { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - // size of the component - let width = 100f32; - let height: f32 = 0f32; basic_component_gui( self, &simulator, ui.ctx(), - (width, height), + (0f32, 0f32), offset, scale, clip_rect, @@ -33,9 +30,6 @@ impl EguiComponent for Equal { ui.label(RichText::new("Equal").size(12f32 * scale)); }); }, - // This is a hack to stop the compiler from complaining - // will hopefully be optimized away - None::>, ) } diff --git a/src/gui_egui/components/mips_branch_logic.rs b/src/gui_egui/components/mips_branch_logic.rs index fa5eb662..12fa4ad7 100644 --- a/src/gui_egui/components/mips_branch_logic.rs +++ b/src/gui_egui/components/mips_branch_logic.rs @@ -17,14 +17,11 @@ impl EguiComponent for BranchLogic { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - // size of the component - let width = 100f32; - let height: f32 = 12f32; basic_component_gui( self, &simulator, ui.ctx(), - (width, height), + (0f32, 0f32), offset, scale, clip_rect, @@ -33,9 +30,6 @@ impl EguiComponent for BranchLogic { ui.label(RichText::new("Branch Logic").size(12f32 * scale)); }); }, - // This is a hack to stop the compiler from complaining - // will hopefully be optimized away - None::>, ) } diff --git a/src/gui_egui/components/mips_controll_unit.rs b/src/gui_egui/components/mips_controll_unit.rs index 1b3786c4..c75aa8d3 100644 --- a/src/gui_egui/components/mips_controll_unit.rs +++ b/src/gui_egui/components/mips_controll_unit.rs @@ -33,9 +33,6 @@ impl EguiComponent for ControlUnit { ui.label(RichText::new("Control Unit").size(12f32 * scale)); }); }, - // This is a hack to stop the compiler from complaining - // will hopefully be optimized away - None::>, ) } diff --git a/src/gui_egui/components/mips_instruction_splitter.rs b/src/gui_egui/components/mips_instruction_splitter.rs index d9531a1d..7f772e3a 100644 --- a/src/gui_egui/components/mips_instruction_splitter.rs +++ b/src/gui_egui/components/mips_instruction_splitter.rs @@ -33,9 +33,6 @@ impl EguiComponent for InstrSplit { ui.label(RichText::new("instruction\nspliter").size(12f32 * scale)); }); }, - // This is a hack to stop the compiler from complaining - // will hopefully be optimized away - None::>, ) } diff --git a/src/gui_egui/components/mips_jump_merge.rs b/src/gui_egui/components/mips_jump_merge.rs index b992f316..45076f56 100644 --- a/src/gui_egui/components/mips_jump_merge.rs +++ b/src/gui_egui/components/mips_jump_merge.rs @@ -17,14 +17,11 @@ impl EguiComponent for JumpMerge { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - // size of the component - let width = 100f32; - let height: f32 = 12f32; basic_component_gui( self, &simulator, ui.ctx(), - (width, height), + (0f32, 0f32), offset, scale, clip_rect, @@ -33,9 +30,6 @@ impl EguiComponent for JumpMerge { ui.label(RichText::new("Jump Merge").size(12f32 * scale)); }); }, - // This is a hack to stop the compiler from complaining - // will hopefully be optimized away - None::>, ) } diff --git a/src/gui_egui/components/mips_reg_file.rs b/src/gui_egui/components/mips_reg_file.rs index 564345df..03dd9383 100644 --- a/src/gui_egui/components/mips_reg_file.rs +++ b/src/gui_egui/components/mips_reg_file.rs @@ -98,9 +98,6 @@ impl EguiComponent for RegFile { ui.label(RichText::new(str).size(12f32 * scale).monospace()) }); }, - // compiler hack to allow None - // will hopefully be optimized away - None::>, ) } diff --git a/src/gui_egui/components/shift_left_const.rs b/src/gui_egui/components/shift_left_const.rs index 41c6eba6..a38f2e91 100644 --- a/src/gui_egui/components/shift_left_const.rs +++ b/src/gui_egui/components/shift_left_const.rs @@ -17,14 +17,11 @@ impl EguiComponent for ShiftConst { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - // size of the component - let width = 100f32; - let height: f32 = 12f32; basic_component_gui( self, &simulator, ui.ctx(), - (width, height), + (0f32, 0f32), offset, scale, clip_rect, @@ -35,9 +32,6 @@ impl EguiComponent for ShiftConst { ); }); }, - // This is a hack to stop the compiler from complaining - // will hopefully be optimized away - None::>, ) } diff --git a/src/gui_egui/components/sz_extend.rs b/src/gui_egui/components/sz_extend.rs index 205d2857..27bcb87a 100644 --- a/src/gui_egui/components/sz_extend.rs +++ b/src/gui_egui/components/sz_extend.rs @@ -17,14 +17,11 @@ impl EguiComponent for SignZeroExtend { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - // size of the component - let width = 100f32; - let height: f32 = 12f32; basic_component_gui( self, &simulator, ui.ctx(), - (width, height), + (0f32, 0f32), offset, scale, clip_rect, @@ -56,9 +53,6 @@ impl EguiComponent for SignZeroExtend { ui.label(RichText::new("Jump Merge").size(12f32 * scale)); }, - // This is a hack to stop the compiler from complaining - // will hopefully be optimized away - None::>, ) } diff --git a/src/gui_egui/components/zero_extend.rs b/src/gui_egui/components/zero_extend.rs index a6e1a7c5..b2ed9997 100644 --- a/src/gui_egui/components/zero_extend.rs +++ b/src/gui_egui/components/zero_extend.rs @@ -17,14 +17,11 @@ impl EguiComponent for ZeroExtend { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - // size of the component - let width = 100f32; - let height: f32 = 12f32; basic_component_gui( self, &simulator, ui.ctx(), - (width, height), + (0f32, 0f32), offset, scale, clip_rect, @@ -33,9 +30,6 @@ impl EguiComponent for ZeroExtend { ui.label(RichText::new("Zero Extend").size(12f32 * scale)); }); }, - // This is a hack to stop the compiler from complaining - // will hopefully be optimized away - None::>, ) } diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index 5347feef..35e292b5 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -2,7 +2,7 @@ use crate::common::{Components, EguiComponent, Input, Ports, SignalValue, Simula use crate::gui_egui::editor::{EditorMode, SnapPriority}; use egui::{ Align2, Area, Color32, Context, InnerResponse, Order, Pos2, Rect, Response, RichText, Sense, - Ui, Vec2, + TextWrapMode, Ui, Vec2, }; use epaint::Shadow; @@ -143,6 +143,7 @@ pub fn component_area( /// The default hover function displays component id and in/out signals formatet as hex /// /// # Arguments +/// - size: if size is (0f32,0f32) the component will be as large as its content /// - content: Note the function don't size the components, /// that is the responsibility of the content closure /// - on_hover: if this is some this overides the on hover function and displays that instead @@ -188,14 +189,14 @@ pub fn component_area( /// |ui| { /// ui.label(RichText::new("Jump Merge").size(12f32 * scale)); /// }, -/// // This is a hack to stop the compiler from complaining -/// // will hopefully be optimized away -/// None::>, +/// |ui| { +/// ui.label("i am hovered") +/// }, /// ) /// } /// } /// ``` -pub fn basic_component_gui( +pub fn basic_component_gui_with_on_hover( component: &dyn EguiComponent, simulator: &Option<&mut Simulator>, ctx: &Context, @@ -204,7 +205,7 @@ pub fn basic_component_gui( scale: f32, clip_rect: Rect, content: impl FnOnce(&mut Ui), - on_hover: Option, + on_hover: impl FnOnce(&mut Ui), ) -> Option> { let size: Vec2 = size.into(); let offset: Vec2 = offset.into(); @@ -226,9 +227,12 @@ pub fn basic_component_gui( // group.fill = Color32::LIGHT_RED; // Use this ween component background is implemented, probably when we implement dark mode group .show(ui, |ui| { + ui.style_mut().wrap_mode = Some(TextWrapMode::Extend); ui.set_height(component_rect.height()); ui.set_width(component_rect.width()); - ui.set_clip_rect(component_rect.intersect(clip_rect)); + if size != (0f32, 0f32).into() { + ui.set_clip_rect(component_rect.intersect(clip_rect)); + } content(ui); }) .response @@ -236,43 +240,71 @@ pub fn basic_component_gui( ) .inner; - r.clone().on_hover_ui(|ui| match on_hover { - Some(hover_content) => hover_content(ui), - None => { - ui.label(format!("id: {}", component.get_id_ports().0)); - if let Some(sim) = simulator { - ui.separator(); - for port in component.get_id_ports().1.inputs { - ui.label(format!( - "{} <- {}:{} ({})", - port.port_id, - port.input.id, - port.input.field, - match sim.get_input_value(&port.input) { - SignalValue::Uninitialized => "Uninitialized".to_string(), - SignalValue::Unknown => "Unknown".to_string(), - SignalValue::DontCare => "don't care".to_string(), - SignalValue::Data(v) => format!("{:#010x}", v), - }, - )); - } - ui.separator(); - for port_id in component.get_id_ports().1.outputs { - ui.label(format!( - "{} -> {}", - port_id, - match sim - .get_input_value(&Input::new(&component.get_id_ports().0, &port_id)) - { - SignalValue::Uninitialized => "Uninitialized".to_string(), - SignalValue::Unknown => "Unknown".to_string(), - SignalValue::DontCare => "Don't care".to_string(), - SignalValue::Data(v) => format!("{:#010x}", v), - }, - )); - } - }; - } - }); + r.clone().on_hover_ui(on_hover); Some(vec![r]) } + +pub fn basic_component_gui( + component: &dyn EguiComponent, + simulator: &Option<&mut Simulator>, + ctx: &Context, + size: impl Into, + offset: impl Into, + scale: f32, + clip_rect: Rect, + content: impl FnOnce(&mut Ui), +) -> Option> { + basic_component_gui_with_on_hover( + component, + simulator, + ctx, + size, + offset, + scale, + clip_rect, + content, + |ui| basic_on_hover(ui, component, simulator), + ) +} + +/// example +/// r.on_hover(|ui| { +/// basic_on_hover(ui,self,simulator) +/// }) +pub fn basic_on_hover( + ui: &mut Ui, + component: &dyn EguiComponent, + simulator: &Option<&mut Simulator>, +) { + ui.label(format!("id: {}", component.get_id_ports().0)); + if let Some(sim) = simulator { + ui.separator(); + for port in component.get_id_ports().1.inputs { + ui.label(format!( + "{} <- {}:{} ({})", + port.port_id, + port.input.id, + port.input.field, + match sim.get_input_value(&port.input) { + SignalValue::Uninitialized => "Uninitialized".to_string(), + SignalValue::Unknown => "Unknown".to_string(), + SignalValue::DontCare => "don't care".to_string(), + SignalValue::Data(v) => format!("{:#010x}", v), + }, + )); + } + ui.separator(); + for port_id in component.get_id_ports().1.outputs { + ui.label(format!( + "{} -> {}", + port_id, + match sim.get_input_value(&Input::new(&component.get_id_ports().0, &port_id)) { + SignalValue::Uninitialized => "Uninitialized".to_string(), + SignalValue::Unknown => "Unknown".to_string(), + SignalValue::DontCare => "Don't care".to_string(), + SignalValue::Data(v) => format!("{:#010x}", v), + }, + )); + } + }; +} From 3508916723b5983e33967288bf793573064b6138 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Mon, 19 Aug 2024 16:47:25 +0200 Subject: [PATCH 053/126] added function to get register value --- src/components/mips_reg_file.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/mips_reg_file.rs b/src/components/mips_reg_file.rs index 45ffb152..1b1a1f77 100644 --- a/src/components/mips_reg_file.rs +++ b/src/components/mips_reg_file.rs @@ -204,6 +204,8 @@ impl RegFile { write_data_in: Input, write_enable_in: Input, ) -> Self { + let mut arr: [u32; 32] = [0; 32]; + arr[29] = 0x8000_0000; RegFile { id: id.to_string(), pos, @@ -212,7 +214,7 @@ impl RegFile { write_address_in, write_data_in, write_enable_in, - registers: RefCell::new([0; 32]), // create 32 zeros + registers: RefCell::new(arr), // create 32 zeros, wit 29(stack pointer) at 0x8000_0000 history: RefCell::new(vec![]), show_reg_names: RefCell::default(), reg_format: RefCell::default(), @@ -238,4 +240,8 @@ impl RegFile { write_enable_in, )) } + + pub fn get_registers(&self, i: usize) -> u32 { + self.registers.borrow()[i] + } } From 882f44a1d10b1386b04f15642d7614cc27046f18 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Tue, 20 Aug 2024 14:50:54 +0200 Subject: [PATCH 054/126] Reformated struct and added sections map --- src/components/mips_mem_struct.rs | 144 +++++++++++++++++------------- 1 file changed, 83 insertions(+), 61 deletions(-) diff --git a/src/components/mips_mem_struct.rs b/src/components/mips_mem_struct.rs index 7e6f864b..9b369d1b 100644 --- a/src/components/mips_mem_struct.rs +++ b/src/components/mips_mem_struct.rs @@ -1,48 +1,60 @@ use elf::{endian::AnyEndian, ElfBytes}; -use std::{ - collections::{BTreeMap, HashMap}, - fs, - path::PathBuf, -}; +use std::collections::{BTreeMap, HashMap}; +use serde::{Deserialize, Serialize}; /// A men contains two fields. One with the memory mapped data in a BTreeMap. /// And a hashmap with symbols. -#[derive(Default)] -pub struct Mem { +#[derive(Default, Serialize, Deserialize)] +pub struct MipsMem { symbols: HashMap, + sections: HashMap, data: BTreeMap, } -pub enum MemGetSize { +pub enum MemOpSize { Byte, Half, Word, } -impl Mem { +impl MipsMem { /// This function constructs a Mem struct using the elf sections to load the data. /// This may be un-reliable as the Elf might not always contain the sections, /// or contain un-relevant sections and no relevant ones /// # TODO fix result error. currently panics - pub fn from_sections(elf_bytes: &[u8]) -> Result { - let mut mem: Mem = Mem { + pub fn from_sections(elf_bytes: &[u8]) -> Result { + let mut mem: MipsMem = MipsMem { symbols: HashMap::new(), data: BTreeMap::new(), + sections: HashMap::new(), }; let file = ElfBytes::::minimal_parse(elf_bytes).unwrap(); - + // will crash if three is no str table + let sect_head_str_tab = file.section_headers_with_strtab().unwrap(); + let sections = sect_head_str_tab.0.unwrap(); + let str_tab = sect_head_str_tab.1.unwrap(); // for each section in elf - for sect in file.section_headers().unwrap() { - // if the section has flag alloc(0x2), aka lives in memory - // if the section has a size larger than zero - if sect.sh_flags & 0x2 == 0x2 && sect.sh_size != 0 { - let elf_address = sect.sh_offset; // offset into elf file where data is stored (note inside of elf Segment) - let elf_end_address = elf_address + sect.sh_size; // end address of data + for sect in sections { + // if section is PROG BITS and size is none zero + if sect.sh_type == 0x1 && sect.sh_size != 0 { let v_address = sect.sh_addr as u32; - let sect_data = &elf_bytes[elf_address as usize..elf_end_address as usize]; - for (i, byte) in sect_data.into_iter().enumerate() { - mem.data.insert(v_address + i as u32, byte.to_owned()); - } + + // if the section has flag alloc(0x2), aka lives in memory + // if the section has a size larger than zero + if sect.sh_flags & 0x2 == 0x2 && sect.sh_size != 0 { + let elf_address = sect.sh_offset; // offset into elf file where data is stored (note inside of elf Segment) + let elf_end_address = elf_address + sect.sh_size; // end address of data + let sect_data = &elf_bytes[elf_address as usize..elf_end_address as usize]; + for (i, byte) in sect_data.into_iter().enumerate() { + mem.data.insert(v_address + i as u32, byte.to_owned()); + } + }; + + // add section to section hashmap + mem.sections.insert( + v_address, + str_tab.get(sect.sh_name as usize).unwrap().to_string(), + ); } } mem.get_symbols(&file); @@ -53,21 +65,21 @@ impl Mem { pub fn get_unaligned( &self, address: u32, - size: MemGetSize, + size: MemOpSize, sign_extend: bool, big_endian: bool, ) -> u32 { let size_int: usize = match size { - MemGetSize::Byte => 1, - MemGetSize::Half => 2, - MemGetSize::Word => 4, + MemOpSize::Byte => 1, + MemOpSize::Half => 2, + MemOpSize::Word => 4, }; let bytes: Vec = (0..size_int) .map(|i| *self.data.get(&(address + i as u32)).unwrap_or(&0)) .collect(); match size { - MemGetSize::Byte => { + MemOpSize::Byte => { if sign_extend { // first make byte an i8 // then when cast to i32 to sign extends @@ -77,7 +89,7 @@ impl Mem { bytes[0] as u32 } } - MemGetSize::Half => { + MemOpSize::Half => { if sign_extend { let int_16 = if big_endian { i16::from_be_bytes(bytes.try_into().unwrap()) @@ -95,7 +107,7 @@ impl Mem { uint_16 as u32 } } - MemGetSize::Word => { + MemOpSize::Word => { if sign_extend { let int_32 = if big_endian { i32::from_be_bytes(bytes.try_into().unwrap()) @@ -118,14 +130,14 @@ impl Mem { pub fn get( &self, address: u32, - size: MemGetSize, + size: MemOpSize, sign_extend: bool, big_endian: bool, ) -> Result { let size_int: u32 = match size { - MemGetSize::Byte => 1, - MemGetSize::Half => 2, - MemGetSize::Word => 4, + MemOpSize::Byte => 1, + MemOpSize::Half => 2, + MemOpSize::Word => 4, }; if address % size_int != 0 { Err(()) @@ -134,33 +146,13 @@ impl Mem { } } - /// Gets the elf symbol table, and set the self hashmap - fn get_symbols(&mut self, elf_file: &ElfBytes) { - match elf_file.symbol_table().unwrap() { - Some((sym_table, string_table)) => { - let mut sym_hash_map: HashMap = HashMap::new(); - - // for each symbol entry - for sym_entry in sym_table { - let sym_name = string_table.get(sym_entry.st_name as usize).unwrap(); - - // if the symboltype is NOTYPE and has a string add it - if sym_entry.st_symtype() == 0x0 && sym_name != "" { - sym_hash_map.insert(sym_entry.st_value as u32, sym_name.to_string()); - } - } - self.symbols = sym_hash_map - } - None => (), - } - } /// Will truncate the data to the given size and write the data to memory - pub fn write(&mut self, address: u32, data: u32, size: MemGetSize, big_endian: bool) { + pub fn write(&mut self, address: u32, data: u32, size: MemOpSize, big_endian: bool) { match size { - MemGetSize::Byte => { + MemOpSize::Byte => { self.data.insert(address, data as u8); } - MemGetSize::Half => { + MemOpSize::Half => { let uint_16 = data as u16; let bytes = if big_endian { uint_16.to_be_bytes() @@ -170,7 +162,7 @@ impl Mem { self.data.insert(address, bytes[0]); self.data.insert(address + 1, bytes[1]); } - MemGetSize::Word => { + MemOpSize::Word => { let bytes = if big_endian { data.to_be_bytes() } else { @@ -188,13 +180,13 @@ impl Mem { &mut self, address: u32, data: u32, - size: MemGetSize, + size: MemOpSize, big_endian: bool, ) -> Result<(), ()> { let size_int: u32 = match size { - MemGetSize::Byte => 1, - MemGetSize::Half => 2, - MemGetSize::Word => 4, + MemOpSize::Byte => 1, + MemOpSize::Half => 2, + MemOpSize::Word => 4, }; if address % size_int != 0 { Err(()) @@ -203,4 +195,34 @@ impl Mem { Ok(()) } } + + /// Gets the elf symbol table, and set the self hashmap + fn get_symbols(&mut self, elf_file: &ElfBytes) { + match elf_file.symbol_table().unwrap() { + Some((sym_table, string_table)) => { + let mut sym_hash_map: HashMap = HashMap::new(); + let mut _hash_map: HashMap = HashMap::new(); + + // for each symbol entry + for sym_entry in sym_table { + let sym_name = string_table.get(sym_entry.st_name as usize).unwrap(); + + // if the symboltype is NOTYPE, bind is LOCAL and has a string add it + if sym_entry.st_symtype() == 0x0 && sym_entry.st_bind() == 0x0 && sym_name != "" + { + sym_hash_map.insert(sym_entry.st_value as u32, sym_name.to_string()); + } + } + self.symbols = sym_hash_map + } + None => (), + } + } + + pub fn get_symbol_table(&self) -> HashMap { + self.symbols.clone() + } + pub fn get_section_table(&self) -> HashMap { + self.sections.clone() + } } From fee62e0bd66746c1c4658b9054127db67fb17394 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Tue, 20 Aug 2024 14:51:54 +0200 Subject: [PATCH 055/126] updated regfile to have sp at 0x8000_0000 as default --- src/components/mips_reg_file.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/mips_reg_file.rs b/src/components/mips_reg_file.rs index 1b1a1f77..c37b91aa 100644 --- a/src/components/mips_reg_file.rs +++ b/src/components/mips_reg_file.rs @@ -186,6 +186,7 @@ impl Component for RegFile { fn reset(&self) { *self.registers.borrow_mut() = [0; 32]; + self.registers.borrow_mut()[29] = 0x8000_0000; *self.history.borrow_mut() = vec![]; } From 375c197b07eb96a003476e96da299b75e4f1b53b Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Tue, 20 Aug 2024 14:53:36 +0200 Subject: [PATCH 056/126] if size is zero, let component take as much space as needed --- src/gui_egui/helper.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index 35e292b5..7b065b8a 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -228,9 +228,9 @@ pub fn basic_component_gui_with_on_hover( group .show(ui, |ui| { ui.style_mut().wrap_mode = Some(TextWrapMode::Extend); - ui.set_height(component_rect.height()); - ui.set_width(component_rect.width()); if size != (0f32, 0f32).into() { + ui.set_height(component_rect.height()); + ui.set_width(component_rect.width()); ui.set_clip_rect(component_rect.intersect(clip_rect)); } content(ui); From 2691b1426100a6a505c059df6e77d40312bc9a9c Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Tue, 20 Aug 2024 14:55:30 +0200 Subject: [PATCH 057/126] FIX added missing elf import --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 99f7b799..0a9bddc6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ members = ["mips", "riscv"] [dependencies] anyhow = "1.0.72" clap = { version = "4.3.15", features = ["derive"] } +elf = "0.7.4" fern = "0.6.2" log = "0.4.19" num_enum = "0.6.1" From ee6fee0e0527652b41c7bf805d00460b43f639bd Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Tue, 20 Aug 2024 14:57:52 +0200 Subject: [PATCH 058/126] FIX made mem struct visible --- src/components/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/mod.rs b/src/components/mod.rs index 453b1345..6be2f3d8 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -11,6 +11,7 @@ mod mips_controll_unit; mod mips_im; mod mips_instruction_splitter; mod mips_jump_merge; +mod mips_mem_struct; mod mips_reg_file; mod mux; mod probe; @@ -38,6 +39,7 @@ pub use mips_controll_unit::*; pub use mips_im::*; pub use mips_instruction_splitter::*; pub use mips_jump_merge::*; +pub use mips_mem_struct::*; pub use mips_reg_file::*; pub use mux::*; pub use probe::*; From a2c3a7f00a8758b73c6070785f86c32a82fb8f8b Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Tue, 20 Aug 2024 15:01:20 +0200 Subject: [PATCH 059/126] Added mips_mem_view_window --- src/gui_egui/mips_mem_view_window.rs | 641 +++++++++++++++++++++++++++ src/gui_egui/mod.rs | 1 + 2 files changed, 642 insertions(+) create mode 100644 src/gui_egui/mips_mem_view_window.rs diff --git a/src/gui_egui/mips_mem_view_window.rs b/src/gui_egui/mips_mem_view_window.rs new file mode 100644 index 00000000..3e086b27 --- /dev/null +++ b/src/gui_egui/mips_mem_view_window.rs @@ -0,0 +1,641 @@ +use egui::{scroll_area, RichText, ScrollArea, TextWrapMode, Ui, ViewportBuilder, ViewportId}; +use std::{ + cell::RefCell, + collections::{HashMap, HashSet}, + rc::Rc, +}; + +use crate::components::{InstrMem, MemOpSize, MipsMem, RegFile}; + +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Deserialize, Serialize)] +pub struct MemViewWindow { + pub visible: bool, + title: String, + id: String, + mem: Rc>, + row_offset: u32, + max_rows: u32, + /// when set to top, the given address will be displayed at the top of the scroll area + /// center, the center of the scroll area + /// bottom, the bottom of the scroll area + #[serde(skip)] + go_to_address: GoAddress, + // determents what is used as GoAddress in the top bar + #[serde(skip)] + go_type: GoAddress, + // used when user wants to go to another address + #[serde(skip)] + custom_address: u32, + + // used for formatning the view + big_endian: bool, + format: DataFormat, + + // used to determine if section, symbols and other markers should be shown + show_settings: ShowSettings, + + // used for show register + reg_ref: Option>, + + // used to show pc and jump to pc + // why not a Rc? because that would cause circular dependency and a memory leak + dynamic_symbols: HashMap, + + // Added when user clicks a row, and removed when clicked again + break_points: HashSet, +} + +#[derive(PartialEq, Clone, Default)] +enum GoAddress { + Top(u32), + Center(u32), + Bottom(u32), + #[default] + None, +} +#[derive(PartialEq, Clone, Serialize, Deserialize)] +enum DataFormat { + Hex, + HexAndMips, + Bin, + DecSigned, + DecUnsigned, + Byte, + ByteAndUtf8, +} +#[derive(Clone, Serialize, Deserialize)] +struct ShowSettings { + symbols: bool, + sections: bool, + program_counter: bool, + registers: [bool; 32], +} + +const REG_NAMES: [&str; 32] = [ + "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", + "s7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "t8", "t9", "k0", "k1", "gp", "sp", "fp", + "ra", +]; + +fn set_address(adrs: &GoAddress, new_adrs: u32) -> GoAddress { + match adrs { + GoAddress::Top(_) => GoAddress::Top(new_adrs), + GoAddress::Center(_) => GoAddress::Center(new_adrs), + GoAddress::Bottom(_) => GoAddress::Bottom(new_adrs), + GoAddress::None => GoAddress::None, + } +} + +impl MemViewWindow { + // creates a new memory view window with id string and the given memory + pub fn new(id: String, title: String, mem: Rc>) -> Self { + MemViewWindow { + title: title, + id: id, + visible: false, + row_offset: 0, + max_rows: 1024, + mem: mem, + go_to_address: GoAddress::None, + go_type: GoAddress::Top(0), + custom_address: 0, + big_endian: true, // big endian is default on mips + format: DataFormat::Hex, + show_settings: ShowSettings { + symbols: true, + sections: false, + program_counter: false, + registers: [false; 32], + }, + reg_ref: None, + dynamic_symbols: HashMap::new(), + break_points: HashSet::new(), + } + } + + pub fn new_with_reg( + id: String, + title: String, + mem: Rc>, + regfile: Rc, + pc_ref: Rc>, + ) -> Self { + MemViewWindow::new(id, title, mem).set_regfile(regfile) + } + + /// set a reference to a regfile which allows for jumping and displaying registers + pub fn set_regfile(mut self, regfile_rc: Rc) -> Self { + self.reg_ref = Some(regfile_rc); + self + } + + pub fn update_regfile(&mut self, regfile_rc: Rc) { + self.reg_ref = Some(regfile_rc) + } + /// Set the extra symbols address, if no symbol exist add that symbol + pub fn set_dynamic_symbol(&mut self, symbol: &str, adrs: u32) { + match self.dynamic_symbols.get_mut(symbol) { + Some((cur_adrs, _vis)) => { + *cur_adrs = adrs; + } + None => { + self.dynamic_symbols + .insert(symbol.to_string(), (adrs, false)); + } + } + } + /// Get the address of a symbol, if no such symbol exist return None + pub fn get_dynamic_symbol(&self, symbol: &str) -> Option { + match self.dynamic_symbols.get(symbol) { + Some((adrs, _)) => Some(*adrs), + None => None, + } + } + + /// This sets the format to hex + mips and if possible goes to the section .text + pub fn set_code_view(mut self) -> MemViewWindow { + // find if value ".text" exists, if so go to that + match self + .mem + .borrow() + .get_section_table() + .iter() + .find_map( + |(adrs, name)| { + if name == ".text" { + Some(adrs) + } else { + None + } + }, + ) { + Some(adrs) => self.go_to_address = GoAddress::Top(*adrs), + None => self.go_to_address = GoAddress::None, + }; + + // set + self.format = DataFormat::HexAndMips; + self.show_settings.registers[31] = true; + // add PC_IM extra symbol and set to visible + // Decided to use PC_IM, for consistence with the pipeline model + self.dynamic_symbols.insert("PC_IM".into(), (0, true)); + self + } + + /// This sets the format to byte + utf8 and if possible goes to the section .data + pub fn set_data_view(mut self) -> MemViewWindow { + // find if value ".text" exists + match self + .mem + .borrow() + .get_section_table() + .iter() + .find_map( + |(adrs, name)| { + if name == ".data" { + Some(adrs) + } else { + None + } + }, + ) { + Some(adrs) => self.go_to_address = GoAddress::Top(*adrs), + None => self.go_to_address = GoAddress::None, + }; + self.format = DataFormat::ByteAndUtf8; + self + } + + pub fn is_break_point(&self, address: &u32) -> bool { + self.break_points.contains(address) + } + + pub fn render(&mut self, ctx: &egui::Context) { + if !self.visible { + return (); + }; + + ctx.show_viewport_immediate( + ViewportId::from_hash_of(&self.id), + ViewportBuilder::default().with_title(&self.title), + |ctx, _class| { + // If window is close is sent set visible to false + // WARNING, DON'T USE CONTEXT INSIDE READER: WILL CAUSE DEADLOCK + if ctx.input(|i| i.viewport().close_requested()) { + self.visible = false + } + + // Render top panel with go to, format and show menus + self.render_top(ctx); + + egui::CentralPanel::default().show(ctx, |ui| { + let h = ui.text_style_height(&egui::TextStyle::Body); + + // if self.go_to_address is none this functions does nothing but return the passed scrollArea + let scr_area = self.scroll_to_address(ui, ScrollArea::vertical()); + // +2 for the show more buttons + scr_area.show_rows(ui, h, (self.max_rows + 2) as usize, |ui, draw_range| { + ui.style_mut().wrap_mode = Some(TextWrapMode::Truncate); + ui.set_width(ui.available_width()); + for i in draw_range.clone() { + self.render_scroll_area_item(ui, i); + } + }); + }) + }, + ); + } + + fn render_top(&mut self, ctx: &egui::Context) { + egui::TopBottomPanel::top(self.id.clone()).show(ctx, |ui| { + egui::menu::bar(ui, |ui| { + ui.menu_button("Go to", |ui| { + // used to allow the user to select if the address should be show in the top, center, bottom of the scroll area + ui.menu_button("show address at", |ui| { + ui.selectable_value(&mut self.go_type, GoAddress::Top(0), "top"); + ui.selectable_value(&mut self.go_type, GoAddress::Center(0), "center"); + ui.selectable_value(&mut self.go_type, GoAddress::Bottom(0), "bottom"); + }); + ui.separator(); + + let mut close_menu = false; + + // add submenu with a button for each symbol, which sets self.go_to_address + ui.menu_button("symbol", |ui| { + ScrollArea::vertical().show(ui, |ui| { + let because_lifetimes_sad = self.mem.borrow().get_symbol_table(); + let mut symbols = because_lifetimes_sad.iter().collect::>(); + symbols.sort_by(|a, b| a.0.partial_cmp(b.0).unwrap()); + + for (key, v) in symbols { + if ui.button(format!("{} {:#0x}", v, key)).clicked() { + self.go_to_address = set_address(&self.go_type, *key); + ui.close_menu(); + close_menu = true; + } + } + }); + }); + ui.menu_button("section", |ui| { + let because_lifetimes_sad = self.mem.borrow().get_section_table(); + let mut sections = because_lifetimes_sad.iter().collect::>(); + sections.sort_by(|a, b| a.0.partial_cmp(b.0).unwrap()); + + for (key, v) in sections { + if ui.button(format!("{} {:#0x}", v, key)).clicked() { + self.go_to_address = set_address(&self.go_type, *key); + ui.close_menu(); + close_menu = true; + } + } + }); + + // Does any PC pointer exists, make them visible in this menu for quick access + if self.dynamic_symbols.get("PC_IM").is_some() + || self.dynamic_symbols.get("PC_DE").is_some() + || self.dynamic_symbols.get("PC_EX").is_some() + || self.dynamic_symbols.get("PC_DM").is_some() + { + ui.separator(); + + match self.dynamic_symbols.get("PC_IM") { + Some((adrs, _)) => { + if ui.button(format!("PC_IM ({:#0x})", adrs)).clicked() { + self.go_to_address = set_address(&self.go_type, *adrs); + ui.close_menu(); + close_menu = true; + } + } + None => {} + } + + match self.dynamic_symbols.get("PC_DE") { + Some((adrs, _)) => { + if ui.button(format!("PC_DE ({:#0x})", adrs)).clicked() { + self.go_to_address = set_address(&self.go_type, *adrs); + ui.close_menu(); + close_menu = true; + } + } + None => {} + } + + match self.dynamic_symbols.get("PC_EX") { + Some((adrs, _)) => { + if ui.button(format!("PC_EX ({:#0x})", adrs)).clicked() { + self.go_to_address = set_address(&self.go_type, *adrs); + ui.close_menu(); + close_menu = true; + } + } + None => {} + } + + match self.dynamic_symbols.get("PC_DM") { + Some((adrs, _)) => { + if ui.button(format!("PC_DM ({:#0x})", adrs)).clicked() { + self.go_to_address = set_address(&self.go_type, *adrs); + ui.close_menu(); + close_menu = true; + } + } + None => {} + } + } + + if let Some(reg) = &self.reg_ref { + ui.separator(); + + let gp = reg.get_registers(28); + if ui.button(format!("Global pointer ({:#0x})", gp)).clicked() { + self.go_to_address = set_address(&self.go_type, gp) + } + let sp = reg.get_registers(29); + if ui.button(format!("Stack pointer ({:#0x})", sp)).clicked() { + self.go_to_address = set_address(&self.go_type, sp) + } + let fp = reg.get_registers(30); + if ui.button(format!("Frame pointer ({:#0x})", fp)).clicked() { + self.go_to_address = set_address(&self.go_type, fp) + } + let ra = reg.get_registers(31); + if ui.button(format!("Return address ({:#0x})", gp)).clicked() { + self.go_to_address = set_address(&self.go_type, ra) + } + + ui.separator(); + + // TODO add "go to other register" + ui.menu_button("Other Register", |ui| { + ScrollArea::vertical().show(ui, |ui| { + for (i, name) in REG_NAMES.iter().enumerate() { + let val = reg.get_registers(i); + if ui.button(format!("${} {:#0x}", name, val)).clicked() { + self.go_to_address = set_address(&self.go_type, val); + ui.close_menu(); + close_menu = true; + } + } + }) + }); + } + + ui.separator(); + ui.menu_button("Dynamic symbols", |ui| { + let mut extra_symbols = self.dynamic_symbols.iter().collect::>(); + extra_symbols.sort_by(|a, b| a.1 .0.partial_cmp(&b.1 .0).unwrap()); + for (symbol, (adrs, _)) in extra_symbols { + if ui.button(format!("{} {:#0x}", symbol, adrs)).clicked() { + self.go_to_address = set_address(&self.go_type, *adrs); + ui.close_menu(); + close_menu = true; + } + } + }); + + ui.separator(); + ui.menu_button("Other Address", |ui| { + ui.add( + egui::DragValue::new(&mut self.custom_address) + .hexadecimal(8, true, true) + .prefix("0x"), + ); + if ui.button("Go").clicked() { + self.go_to_address = set_address(&self.go_type, self.custom_address); + close_menu = true; + } + }); + + if close_menu { + ui.close_menu(); + } + }); + ui.menu_button("Format", |ui| { + ui.selectable_value(&mut self.big_endian, false, "Little Endian"); + ui.selectable_value(&mut self.big_endian, true, "Big Endian"); + ui.separator(); + ui.selectable_value(&mut self.format, DataFormat::Hex, "Hex"); + ui.selectable_value(&mut self.format, DataFormat::HexAndMips, "Hex + mips"); + ui.selectable_value(&mut self.format, DataFormat::DecSigned, "Decimal Singed"); + ui.selectable_value( + &mut self.format, + DataFormat::DecUnsigned, + "Decimal Unsigned", + ); + ui.selectable_value(&mut self.format, DataFormat::Bin, "Binary"); + ui.selectable_value(&mut self.format, DataFormat::Byte, "Bytes"); + ui.selectable_value(&mut self.format, DataFormat::ByteAndUtf8, "Bytes + UTF8"); + }); + ui.menu_button("Show", |ui| { + ui.checkbox(&mut self.show_settings.symbols, "Symbols"); + ui.checkbox(&mut self.show_settings.sections, "Sections"); + if let Some(_) = &self.reg_ref { + ui.separator(); + + ui.checkbox(&mut self.show_settings.registers[28], "Global Pointer"); + ui.checkbox(&mut self.show_settings.registers[29], "Stack Pointer"); + ui.checkbox(&mut self.show_settings.registers[30], "Frame Pointer"); + ui.checkbox(&mut self.show_settings.registers[31], "Return address"); + ui.separator(); + ui.menu_button("Other register", |ui| { + ScrollArea::vertical().show(ui, |ui| { + for (i, name) in REG_NAMES.iter().enumerate() { + ui.checkbox( + &mut self.show_settings.registers[i], + format!("${}", name), + ); + } + }); + }); + } + if !self.dynamic_symbols.is_empty() { + ui.separator(); + ui.menu_button("Dynamic symbols", |ui| { + for (sym, (_, vis)) in self.dynamic_symbols.iter_mut() { + ui.checkbox(vis, sym); + } + }); + } + }); + ui.menu_button("Break points", |ui| { + if ui.button("Clear all breakpoints").clicked() { + self.break_points.clear(); + ui.close_menu(); + } + }); + }); + }); + } + /// NOTE borrows mem + fn render_scroll_area_item(&mut self, ui: &mut Ui, scroll_area_row: usize) { + let more_row_text = RichText::new(format!("show {} more rows", &self.max_rows / 2)); + if scroll_area_row == 0 { + if self.row_offset == 0 { + _ = ui.small_button(more_row_text.clone().strikethrough()); + } else { + if ui.small_button(more_row_text).clicked() { + // 4* to get memory address + // -1 because the button takes up a row + self.go_to_address = GoAddress::Top((self.row_offset - 1) * 4); + }; + } + } else if scroll_area_row == self.max_rows as usize + 1 { + if ui.small_button(more_row_text).clicked() { + self.go_to_address = GoAddress::Bottom((self.row_offset + self.max_rows) * 4); + }; + } else { + // -4 is to allow for space for the show more button + let address = scroll_area_row as u32 * 4 + self.row_offset * 4 - 4; + if ui + .label( + RichText::new(format!( + "{}{:#010x}\t {:015} {}", + match self.break_points.contains(&address) { + true => "BREAK ", + false => "", + }, + address, + self.format_row(address), + match self.get_symbols_etc_at_address(&address) { + Some(string) => format!("\t<= {}", string), + None => String::new(), + } + )) + .monospace(), + ) + .clicked() + { + // was the row clicked if so add breakpoint to address + match self.break_points.contains(&address) { + true => self.break_points.remove(&address), + false => self.break_points.insert(address), + }; + }; + } + } + /// NOTE BORROWS MEM + fn format_row(&self, adrs: u32) -> String { + let data_u32 = + self.mem + .borrow() + .get_unaligned(adrs, MemOpSize::Word, false, self.big_endian); + let bytes = self + .mem + .borrow() + .get_unaligned(adrs, MemOpSize::Word, false, true) + .to_be_bytes(); + match self.format { + DataFormat::Hex => { + format!("{:#010x}", data_u32) + } + DataFormat::HexAndMips => { + format!("{:#010x} MIPS DISASSEMBLY NOT IMPLEMENTED", data_u32) + } + DataFormat::Bin => { + format!("{:032b}", data_u32) + } + DataFormat::DecSigned => { + format!("{}", data_u32 as i32) + } + DataFormat::DecUnsigned => { + format!("{}", data_u32) + } + DataFormat::Byte => { + format!( + "{:02x} {:02x} {:02x} {:02x}", + bytes[0], bytes[1], bytes[2], bytes[3], + ) + } + DataFormat::ByteAndUtf8 => { + format!( + "{:02x} {:02x} {:02x} {:02x} \"{}\"", + bytes[0], + bytes[1], + bytes[2], + bytes[3], + String::from_utf8_lossy(&bytes).escape_debug() + ) + } + } + } + + /// Scroll the scroll area to the address + fn scroll_to_address(&mut self, ui: &mut Ui, scroll_area: ScrollArea) -> ScrollArea { + // if we should not go to an address return + if self.go_to_address == GoAddress::None { + return scroll_area; + } + + let row = match self.go_to_address { + GoAddress::Top(adrs) => adrs / 4, + GoAddress::Center(adrs) => adrs / 4, + GoAddress::Bottom(adrs) => adrs / 4, + GoAddress::None => panic!("I Should have returned not continue"), + }; + + //make address middle of rows visible rows + let mut offset = match row.checked_sub(self.max_rows / 2) { + // don't ask why +1, don't fully know, but has to to with modulo + Some(v) => v + 1, + None => 0, + }; + + // align to half max rows + offset -= offset % (self.max_rows / 2); + // update offset + self.row_offset = offset; + + // calculate scroll amount + let row_height = ui.text_style_height(&egui::TextStyle::Body); + let y_spacing = ui.style().spacing.item_spacing.y; + let top = (row - self.row_offset + 1) as f32 * (row_height + y_spacing); + + let scroll = match self.go_to_address { + GoAddress::Top(_) => top, + GoAddress::Center(_) => top - ui.available_height() / 2.0, + GoAddress::Bottom(_) => top - ui.available_height(), + GoAddress::None => panic!("I Should have returned not continue"), + }; + + self.go_to_address = GoAddress::None; + scroll_area.vertical_scroll_offset(scroll) + } + + // TODO symbol or sect might not be word aligned, + // since we check word aligned addresses we might miss the symbol/reg ect + fn get_symbols_etc_at_address(&self, adrs: &u32) -> Option { + let mut out_vec: Vec<&str> = vec![]; + let sym = self.mem.borrow().get_symbol_table(); + let sect = self.mem.borrow().get_section_table(); + + for (name, _) in self + .dynamic_symbols + .iter() + .filter(|(_name, (sym_adrs, vis))| sym_adrs == adrs && *vis) + { + out_vec.push(&name) + } + if self.show_settings.sections && sect.contains_key(adrs) { + out_vec.push(sect.get(adrs).unwrap()) + } + if self.show_settings.symbols && sym.contains_key(adrs) { + out_vec.push(sym.get(adrs).unwrap()) + } + + if let Some(reg) = &self.reg_ref { + for (i, show) in self.show_settings.registers.iter().enumerate() { + if *show && (reg.get_registers(i) & !0b11) == *adrs { + out_vec.push(REG_NAMES[i]) + } + } + } + + if out_vec.is_empty() { + None + } else { + Some(out_vec.join(", ")) + } + } +} diff --git a/src/gui_egui/mod.rs b/src/gui_egui/mod.rs index 0d590501..acefb9a5 100644 --- a/src/gui_egui/mod.rs +++ b/src/gui_egui/mod.rs @@ -6,6 +6,7 @@ pub mod helper; mod keymap; mod library; mod menu; +pub mod mips_mem_view_window; #[cfg(feature = "components")] pub mod components; From a54318aa07154cb28937bab750e158ae5a151595 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Tue, 20 Aug 2024 15:01:46 +0200 Subject: [PATCH 060/126] added mips IM and example file --- examples/mips_im_dm_regfile.rs | 74 ++++++ src/components/mips_im.rs | 243 +++++++++--------- src/gui_egui/components/mips_im.rs | 391 +++++++++-------------------- 3 files changed, 313 insertions(+), 395 deletions(-) create mode 100644 examples/mips_im_dm_regfile.rs diff --git a/examples/mips_im_dm_regfile.rs b/examples/mips_im_dm_regfile.rs new file mode 100644 index 00000000..22f7880e --- /dev/null +++ b/examples/mips_im_dm_regfile.rs @@ -0,0 +1,74 @@ +use std::cell::RefCell; +use std::rc::Rc; +use std::{path::PathBuf, rc}; +use syncrim::common::EguiComponent; +#[cfg(feature = "gui-egui")] +use syncrim::gui_egui::editor::Library; +use syncrim::{ + common::{ComponentStore, Input}, + components::*, + fern::fern_setup, +}; + +fn main() { + fern_setup(); + + // create an empty memory that both IM and DM can refrence + let mem = Rc::new(RefCell::new(MipsMem::default())); + let reg_file = RegFile::rc_new( + "reg_file", + (200.0, 200.0), + Input::new("rs_addr", "out"), + Input::new("rt_addr", "out"), + Input::new("write_addr", "out"), + Input::new("write_data", "out"), + Input::new("write_enable", "out"), + ); + + let cs = ComponentStore { + store: vec![ + ProbeEdit::rc_new("rs_addr", (60.0, 100.0)), + ProbeEdit::rc_new("rt_addr", (60.0, 140.0)), + ProbeEdit::rc_new("write_addr", (60.0, 180.0)), + ProbeEdit::rc_new("write_data", (60.0, 220.0)), + ProbeEdit::rc_new("write_enable", (60.0, 260.0)), + Probe::rc_new( + "rs", + (300.0, 120.0), + Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), + ), + Probe::rc_new( + "rt", + (60.0, 400.0), + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), + ), + ProbeEdit::rc_new("pc", (60.0, 500.0)), + Rc::new( + InstrMem::new( + "instr_mem".into(), + (200.0, 500.0), + Input::new("pc", "out"), + Rc::clone(&mem), + ) + .set_mem_view_reg(Rc::clone(®_file)), + ), // InstrMem::rc_new( + // "instr_mem".into(), + // (200.0, 500.0), + // Input::new("pc", "out"), + // Rc::clone(&mem), + // ).set_mem_view_reg(reg_rc), + reg_file, + ], + }; + + // let cs = autowire(cs); + + let path = PathBuf::from("add.json"); + cs.save_file(&path); + + #[cfg(feature = "gui-egui")] + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + + #[cfg(feature = "gui-vizia")] + syncrim::gui_vizia::gui(cs, &path); +} diff --git a/src/components/mips_im.rs b/src/components/mips_im.rs index a02c8353..5fcc0817 100644 --- a/src/components/mips_im.rs +++ b/src/components/mips_im.rs @@ -1,123 +1,134 @@ -// #[cfg(feature = "gui-egui")] -// use crate::common::EguiComponent; -// use crate::common::{ -// Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, -// SignalValue, Simulator, -// }; -// use core::cell::RefCell; -// use core::ops::Range; -// use log::*; -// use serde::{Deserialize, Serialize}; -// use std::any::Any; -// use std::collections::BTreeMap; -// use std::collections::HashMap; -// use std::collections::HashSet; -// use std::rc::Rc; +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::{ + common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}, + gui_egui::mips_mem_view_window::MemViewWindow, +}; +use core::cell::RefCell; +use log::*; +use serde::{Deserialize, Serialize}; +use std::{any::Any, rc::Rc}; -// pub const INSTR_MEM_PC_ID: &str = "pc"; +use super::{ + mips_mem_struct::{MemOpSize, MipsMem}, + RegFile, +}; -// pub const INSTR_MEM_INSTRUCTION_ID: &str = "instruction"; +pub const INSTR_MEM_PC_ID: &str = "pc"; -// pub const INSTR_MEM_HEIGHT: f32 = 100.0; -// pub const INSTR_MEM_WIDTH: f32 = 100.0; +pub const INSTR_MEM_INSTRUCTION_ID: &str = "instruction"; -// #[derive(Serialize, Deserialize, Clone)] -// pub struct InstrMem { -// pub width: f32, -// pub height: f32, -// pub id: String, -// pub pos: (f32, f32), -// #[serde(skip)] -// pub bytes: BTreeMap, -// pub pc: Input, -// pub range: Range, -// #[serde(skip)] -// pub breakpoints: Rc>>, -// #[serde(skip)] -// pub symbols: HashMap, -// pub le: bool, -// } +#[derive(Serialize, Deserialize, Clone)] +pub struct InstrMem { + pub id: String, + pub pos: (f32, f32), + pub pc: Input, + // should probably not skip mem rc here, since we still need them to point to the same MipsMem + #[serde(skip)] + pub mem: Rc>, + pub mem_view: RefCell, +} -// #[typetag::serde()] -// impl Component for InstrMem { -// fn as_any(&self) -> &dyn std::any::Any { -// self -// } +impl InstrMem { + pub fn new( + id: String, + pos: (f32, f32), + pc_input: Input, + mem: Rc>, + ) -> InstrMem { + let mem_view = MemViewWindow::new( + id.clone(), + "instruction memory view".into(), + Rc::clone(&mem), + ) + .set_code_view(); + InstrMem { + id: id, + pos: pos, + pc: pc_input, + mem: mem, + mem_view: RefCell::new(mem_view), + } + } + pub fn rc_new( + id: String, + pos: (f32, f32), + pc_input: Input, + mem: Rc>, + ) -> Rc { + Rc::new(InstrMem::new(id, pos, pc_input, mem)) + } + pub fn set_mem_view_reg(mut self, reg_rc: Rc) -> Self { + self.mem_view.get_mut().update_regfile(reg_rc); + self + } +} -// fn to_(&self) { -// //println!("InstrMem"); -// } -// #[cfg(feature = "gui-egui")] -// fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { -// let dummy_input = Input::new("dummy", "out"); -// Box::new(Rc::new(InstrMem { -// width: INSTR_MEM_WIDTH, -// height: INSTR_MEM_HEIGHT, -// id: id.to_string(), -// pos: (pos.0, pos.1), -// bytes: BTreeMap::new(), -// pc: dummy_input, -// range: Range { -// start: 0, -// end: 0x1000, -// }, -// breakpoints: Rc::new(RefCell::new(HashSet::new())), -// symbols: HashMap::new(), -// le: true, -// })) -// } -// fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { -// if target_port_id.as_str() == INSTR_MEM_PC_ID { -// self.pc = new_input; -// } -// } -// fn get_id_ports(&self) -> (String, Ports) { -// ( -// self.id.clone(), -// Ports::new( -// vec![&InputPort { -// port_id: INSTR_MEM_PC_ID.to_string(), -// input: self.pc.clone(), -// }], -// OutputType::Combinatorial, -// vec![INSTR_MEM_INSTRUCTION_ID], -// ), -// ) -// } +#[typetag::serde()] +impl Component for InstrMem { + fn as_any(&self) -> &dyn std::any::Any { + self + } -// fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { -// // get instr at pc/4 -// let pc: u32 = simulator.get_input_value(&self.pc).try_into().unwrap(); -// let instr = if !self.le { -// (*self.bytes.get(&((pc) as usize)).unwrap() as u32) << 24 -// | (*self.bytes.get(&((pc + 1) as usize)).unwrap() as u32) << 16 -// | (*self.bytes.get(&((pc + 2) as usize)).unwrap() as u32) << 8 -// | (*self.bytes.get(&((pc + 3) as usize)).unwrap() as u32) -// } else { -// (*self.bytes.get(&((pc) as usize)).unwrap() as u32) -// | (*self.bytes.get(&((pc + 1) as usize)).unwrap() as u32) << 8 -// | (*self.bytes.get(&((pc + 2) as usize)).unwrap() as u32) << 16 -// | (*self.bytes.get(&((pc + 3) as usize)).unwrap() as u32) << 24 -// }; -// //the asm_riscv crate incorrectly panics when trying from instead of -// //returning Err, catch it and handle instead -// let instruction_fmt = { -// format!( -// "{:?}", -// match asm_riscv::I::try_from(instr) { -// Ok(i) => riscv_asm_strings::StringifyUpperHex::to_string(&i), -// Err(_) => "Unknown instruction".to_string(), -// } -// ) -// }; -// trace!("instruction: {}", instruction_fmt); -// trace!("pc:0x{:08x}", pc); -// // set output -// simulator.set_out_value(&self.id, "instruction", instr); -// if !self.breakpoints.borrow().contains(&(pc as usize)) { -// Ok(()) -// } else { -// Err(Condition::Halt(format!("Breakpoint at {}", pc))) -// } -// } -// } + fn to_(&self) { + //println!("InstrMem"); + } + #[cfg(feature = "gui-egui")] + fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + let dummy_input = Input::new("dummy", "out"); + let memref = Rc::new(RefCell::new(MipsMem::default())); + Box::new(Rc::new(InstrMem { + id: id.into(), + pos: pos, + pc: dummy_input, + mem: memref.clone(), + mem_view: RefCell::new(MemViewWindow::new( + "dummy".into(), + "IM dummy".into(), + memref, + )), + })) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + if target_port_id.as_str() == INSTR_MEM_PC_ID { + self.pc = new_input; + } + } + + fn get_id_ports(&self) -> (String, Ports) { + ( + self.id.clone(), + Ports::new( + vec![&InputPort { + port_id: INSTR_MEM_PC_ID.to_string(), + input: self.pc.clone(), + }], + OutputType::Combinatorial, + vec![INSTR_MEM_INSTRUCTION_ID], + ), + ) + } + + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get instr at pc/4 + let pc: u32 = simulator.get_input_value(&self.pc).try_into().unwrap(); + + // update dynamic symbol PC_IM + self.mem_view.borrow_mut().set_dynamic_symbol("PC_IM", pc); + + // Get a word at PC with the size of 32bits, read as big endian, + // sign extend doesn't mater since we have 32 bits so extending to 32bits does nothing + match self.mem.borrow().get(pc, MemOpSize::Word, false, true) { + Ok(instr) => { + simulator.set_out_value(&self.id, "instruction", instr); + // check if pc is at breakpoint + match self.mem_view.borrow().is_break_point(&pc) { + true => Err(Condition::Halt(format!("Reached breakpoint at {:#0x}", pc))), + false => Ok(()), + } + } + Err(_) => Err(Condition::Error(format!("Unaligned Read, PC = {:#0x}", pc))), + } + } +} diff --git a/src/gui_egui/components/mips_im.rs b/src/gui_egui/components/mips_im.rs index 23a5b5a3..d785ea37 100644 --- a/src/gui_egui/components/mips_im.rs +++ b/src/gui_egui/components/mips_im.rs @@ -1,288 +1,121 @@ -// use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; -// use crate::components::InstrMem; -// use crate::gui_egui::component_ui::{ -// drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, -// rect_with_hover, visualize_ports, -// }; -// use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; -// use crate::gui_egui::gui::EguiExtra; -// use crate::gui_egui::helper::offset_helper; -// use egui::Window; -// use egui::{ -// Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Slider, Stroke, -// TextWrapMode, Ui, Vec2, -// }; +use std::borrow::BorrowMut; +use std::cell::RefCell; +use std::fs; +use std::path::PathBuf; -// impl InstrMem { -// fn side_panel(&self, ctx: &Context, simulator: Option<&mut Simulator>) { -// Window::new("Instruction Memory") -// .resizable(true) -// .show(ctx, |ui| { -// TableBuilder::new(ui) -// .striped(true) -// .column(Column::initial(75.0).at_least(75.0)) -// .column(Column::initial(10.0).resizable(false)) -// .column(Column::initial(75.0).at_least(75.0)) -// .column(Column::initial(75.0).at_least(50.0)) -// .column(Column::initial(150.0).at_least(85.0).resizable(true)) -// .column(Column::initial(5.0).at_least(5.0).resizable(false)) -// .header(30.0, |mut header| { -// header.col(|ui| { -// ui.heading("Label"); -// }); -// header.col(|_ui| {}); -// header.col(|ui| { -// ui.heading("Address"); -// }); -// header.col(|ui| { -// ui.heading("HEX"); -// }); -// header.col(|ui| { -// ui.heading("Instruction"); -// }); -// }) -// .body(|body| { -// body.rows( -// 15.0, -// (self.range.end - self.range.start) / 4, -// |index, mut row| { -// let address = index * 4 + self.range.start; -// let pc: u32 = { -// if simulator.as_ref().is_some() { -// simulator -// .as_ref() -// .unwrap() -// .get_input_value(&self.pc) -// .try_into() -// .unwrap_or(0) -// } else { -// 0 -// } -// }; -// let (bg_color, fg_color) = { -// if pc as usize == address { -// (Color32::DARK_GRAY, Color32::WHITE) -// } else { -// (Color32::TRANSPARENT, Color32::LIGHT_GRAY) -// } -// }; -// let breakpoint_color = { -// if self.breakpoints.borrow_mut().contains(&address) { -// Color32::RED -// } else { -// Color32::TRANSPARENT -// } -// }; -// row.col(|ui| match &self.symbols.get(&address) { -// Some(s) => { -// ui.add(Label::new(format!("{}:", s)).truncate(true)); -// } -// None => {} -// }); -// //breakpoint -// row.col(|ui| { -// ui.label(RichText::new("•").color(breakpoint_color)); -// }); -// //address -// row.col(|ui| { -// ui.add(Label::new(format!("0x{:08x}", address)).truncate(true)); -// }); -// let mut bytes = [0u8; 4]; -// if !self.le { -// bytes[3] = *self.bytes.get(&address).unwrap(); -// bytes[2] = *self.bytes.get(&(address + 1)).unwrap(); -// bytes[1] = *self.bytes.get(&(address + 2)).unwrap(); -// bytes[0] = *self.bytes.get(&(address + 3)).unwrap(); -// } else { -// bytes[0] = *self.bytes.get(&address).unwrap(); -// bytes[1] = *self.bytes.get(&(address + 1)).unwrap(); -// bytes[2] = *self.bytes.get(&(address + 2)).unwrap(); -// bytes[3] = *self.bytes.get(&(address + 3)).unwrap(); -// } -// let instr = ((bytes[3] as u32) << 24) -// | ((bytes[2] as u32) << 16) -// | ((bytes[1] as u32) << 8) -// | (bytes[0] as u32); +use crate::common::{EguiComponent, Id, Ports, Simulator}; +use crate::components::{InstrMem, MipsMem}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::basic_component_gui; +use crate::gui_egui::mips_mem_view_window::MemViewWindow; +use egui::{Rect, Response, RichText, Ui, Vec2}; -// let instr_fmt = match asm_riscv::I::try_from(instr) { -// Ok(i) => riscv_asm_strings::StringifyUpperHex::to_string(&i), -// Err(_) => "Unknown instruction".to_string(), -// }; -// //hex instr -// row.col(|ui| { -// ui.add(Label::new(format!("0x{:08X}", instr)).truncate(true)); -// }); -// row.col(|ui| { -// if ui -// .add( -// Label::new( -// RichText::new(instr_fmt) -// .color(fg_color) -// .background_color(bg_color), -// ) -// .truncate(true) -// .sense(Sense::click()), -// ) -// .clicked() -// { -// trace!("clicked"); -// if !self.breakpoints.borrow_mut().remove(&address) { -// self.breakpoints.borrow_mut().insert(address); -// } -// }; -// }); -// row.col(|_| {}); -// }, -// ); -// }); -// }); -// } -// } +#[typetag::serde] +impl EguiComponent for InstrMem { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + _editor_mode: EditorMode, + ) -> Option> { + // we could avoid this if we clone self in our basic_component_ui. + // but instead we let our Closure save stuff here (let path_option, mem_view_vis) + // and apply our changes when basic_component_gui returns our borrow + // this is to avoid cloning all the fields. + // avoiding to clone the fields might be premature optimization + // as instrMem.mem is a reference count and wont actually clone the underlying btree and hashmaps + // + // we save 27 bytes of clone + // and most of that clone might even be optimized away + // yes this was premature optimization + let mut path_option: Option = None; + let mut mem_view_vis: bool = self.mem_view.borrow().visible; -// #[typetag::serde] -// impl EguiComponent for InstrMem { -// fn render( -// &self, -// ui: &mut Ui, -// _ctx: &mut EguiExtra, -// simulator: Option<&mut Simulator>, -// offset: Vec2, -// scale: f32, -// clip_rect: Rect, -// editor_mode: EditorMode, -// ) -> Option> { -// // 21x41 -// // middle: 11x 21y (0 0) -// let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; -// let offset_old = offset; -// let mut offset = offset; -// offset.x += self.pos.0 * scale; -// offset.y += self.pos.1 * scale; -// let s = scale; -// let o = offset; -// //self.side_panel(ui.ctx(), simulator); -// // The shape -// let rect = Rect { -// min: oh((-self.width / 2f32, -self.height / 2f32), s, o), -// max: oh((self.width / 2f32, self.height / 2f32), s, o), -// }; -// ui.painter().add(Shape::rect_stroke( -// rect, -// Rounding::ZERO, -// Stroke { -// width: scale, -// color: Color32::BLACK, -// }, -// )); -// ui.painter().text( -// o.to_pos2(), -// egui::Align2::CENTER_CENTER, -// "InstrMem", -// FontId::monospace(14.0), -// Color32::BLACK, -// ); -// let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { -// ui.label(format!("Id: {}", self.id.clone())); -// ui.label("InstrMem"); -// }); -// match editor_mode { -// EditorMode::Simulator => { -// self.side_panel(ui.ctx(), simulator); -// } -// _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), -// } -// Some(vec![r]) -// } + let r = basic_component_gui( + self, + &simulator, + ui.ctx(), + (0f32, 0f32), + offset, + scale, + clip_rect, + |ui| { + // ui.centered_and_justified(|ui| { + ui.label(RichText::new("Instruction memory").size(12f32 * scale)); + if ui.button("load file").clicked() { + path_option = rfd::FileDialog::new().pick_file(); + }; -// fn render_editor( -// &mut self, -// ui: &mut Ui, -// context: &mut EguiExtra, -// simulator: Option<&mut Simulator>, -// offset: Vec2, -// scale: f32, -// clip_rect: Rect, -// id_ports: &[(syncrim::common::Id, Ports)], -// grid: &GridOptions, -// editor_mode: EditorMode, -// ) -> EditorRenderReturn { -// let r_vec = InstrMem::render( -// self, -// ui, -// context, -// simulator, -// offset, -// scale, -// clip_rect, -// editor_mode, -// ) -// .unwrap(); -// let resp = &r_vec[0]; -// let delete = drag_logic( -// ui.ctx(), -// resp, -// &mut self.pos, -// &mut context.pos_tmp, -// scale, -// offset, -// grid, -// ); + match mem_view_vis { + false => { + if ui.button("Show mem window").clicked() { + mem_view_vis = true; + } + } + true => { + ui.toggle_value(&mut mem_view_vis, "Hide mem window"); + } + }; + // }); + }, + ); -// properties_window( -// ui, -// self.id.clone(), -// resp, -// &mut context.properties_window, -// |ui| { -// let mut clicked_dropdown = false; -// input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); -// pos_drag_value(ui, &mut self.pos); -// clicked_dropdown |= input_selector( -// ui, -// &mut self.pc, -// crate::components::INSTR_MEM_PC_ID.to_string(), -// id_ports, -// self.id.clone(), -// ); -// clicked_dropdown -// }, -// ); + if let Some(path) = path_option { + let data = fs::read(path).unwrap(); + &self.mem.replace(MipsMem::from_sections(&data).unwrap()); + mem_view_vis = true; + }; + // {} to drop RefMut as early as possible + { + let mut mem_view = self.mem_view.borrow_mut(); + mem_view.visible = mem_view_vis; + mem_view.render(ui.ctx()); + } + // return response from basic component gui + r + } -// EditorRenderReturn { -// delete, -// resp: Some(r_vec), -// } -// } + fn render_editor( + &mut self, + ui: &mut egui::Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: egui::Vec2, + scale: f32, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + self.render( + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ); + EditorRenderReturn { + delete: false, + resp: None, + } + } -// fn ports_location(&self) -> Vec<(syncrim::common::Id, Pos2)> { -// let own_pos = Vec2::new(self.pos.0, self.pos.1); -// vec![ -// ( -// crate::components::INSTR_MEM_PC_ID.to_string(), -// Pos2::new( -// self.width / 10f32 * 1f32 - self.width / 2f32, -// -self.height / 2f32, -// ) + own_pos, -// ), -// ( -// crate::components::INSTR_MEM_INSTRUCTION_ID.to_string(), -// Pos2::new( -// -self.width / 10f32 * 2f32 + self.width / 2f32, -// -self.height / 2f32, -// ) + own_pos, -// ), -// ] -// } + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } -// fn top_padding(&self) -> f32 { -// self.height / 4f32 -// } + fn get_pos(&self) -> (f32, f32) { + self.pos + } -// fn set_pos(&mut self, pos: (f32, f32)) { -// self.pos = pos; -// } - -// fn get_pos(&self) -> (f32, f32) { -// self.pos -// } -// } + fn top_padding(&self) -> f32 { + 20f32 + } +} From 5b5f5fd71ddb2c04ee04c70823b956508dd69dc0 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 21 Aug 2024 14:28:38 +0200 Subject: [PATCH 061/126] updated mem_view_window to assume data is at 0x1000 if .data is not found --- src/gui_egui/mips_mem_view_window.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui_egui/mips_mem_view_window.rs b/src/gui_egui/mips_mem_view_window.rs index 3e086b27..e4be6896 100644 --- a/src/gui_egui/mips_mem_view_window.rs +++ b/src/gui_egui/mips_mem_view_window.rs @@ -202,7 +202,7 @@ impl MemViewWindow { }, ) { Some(adrs) => self.go_to_address = GoAddress::Top(*adrs), - None => self.go_to_address = GoAddress::None, + None => self.go_to_address = GoAddress::Top(0x1000), }; self.format = DataFormat::ByteAndUtf8; self From 1580dad16f86109b4b41a4b270c5941f0754173c Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 21 Aug 2024 14:29:14 +0200 Subject: [PATCH 062/126] added mips data memory --- examples/mips_im_dm_regfile.rs | 25 ++- src/components/mips_dm.rs | 320 +++++++++++++++++++++++++++++ src/components/mod.rs | 2 + src/gui_egui/components/mips_dm.rs | 108 ++++++++++ src/gui_egui/components/mod.rs | 1 + 5 files changed, 449 insertions(+), 7 deletions(-) create mode 100644 src/components/mips_dm.rs create mode 100644 src/gui_egui/components/mips_dm.rs diff --git a/examples/mips_im_dm_regfile.rs b/examples/mips_im_dm_regfile.rs index 22f7880e..3398611b 100644 --- a/examples/mips_im_dm_regfile.rs +++ b/examples/mips_im_dm_regfile.rs @@ -1,6 +1,6 @@ use std::cell::RefCell; +use std::path::PathBuf; use std::rc::Rc; -use std::{path::PathBuf, rc}; use syncrim::common::EguiComponent; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; @@ -51,12 +51,23 @@ fn main() { Rc::clone(&mem), ) .set_mem_view_reg(Rc::clone(®_file)), - ), // InstrMem::rc_new( - // "instr_mem".into(), - // (200.0, 500.0), - // Input::new("pc", "out"), - // Rc::clone(&mem), - // ).set_mem_view_reg(reg_rc), + ), + ProbeEdit::rc_new("data_adrs", (60.0, 660.0)), + ProbeEdit::rc_new("data_write_enable", (60.0, 700.0)), + ProbeEdit::rc_new("data_mem_op", (60.0, 740.0)), + ProbeEdit::rc_new("data_write_data", (60.0, 780.0)), + Rc::new( + DataMem::new( + "data_mem".into(), + (200.0, 700.0), + Input::new("data_adrs", "out"), + Input::new("data_write_data", "out"), + Input::new("data_mem_op", "out"), + Input::new("data_write_enable", "out"), + Rc::clone(&mem), + ) + .set_mem_view_reg(Rc::clone(®_file)), + ), reg_file, ], }; diff --git a/src/components/mips_dm.rs b/src/components/mips_dm.rs new file mode 100644 index 00000000..db2f2154 --- /dev/null +++ b/src/components/mips_dm.rs @@ -0,0 +1,320 @@ +#[cfg(feature = "gui-egui")] +use crate::common::EguiComponent; +use crate::{ + common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}, + gui_egui::mips_mem_view_window::MemViewWindow, +}; +use core::cell::RefCell; +use log::*; +use serde::{Deserialize, Serialize}; +use std::{any::Any, rc::Rc}; + +use super::{ + mips_mem_struct::{MemOpSize, MipsMem}, + RegFile, +}; + +pub mod data_op { + pub const NO_OP: u32 = 0; + pub const LOAD_BYTE: u32 = 1; + pub const LOAD_BYTE_U: u32 = 2; + pub const LOAD_HALF: u32 = 3; + pub const LOAD_HALF_U: u32 = 4; + pub const LOAD_WORD: u32 = 5; + + pub const STORE_BYTE: u32 = 6; + pub const STORE_HALF: u32 = 7; + pub const STORE_WORD: u32 = 8; +} + +pub const DATA_MEM_A_IN_ID: &str = "data_mem_address_in"; +pub const DATA_MEM_OP_IN_ID: &str = "data_mem_op_in"; +pub const DATA_MEM_WRITE_ENABLE_ID: &str = "data_mem_write_enable"; +pub const DATA_MEM_WD_IN_ID: &str = "data_mem_write_data_in"; + +pub const DATA_MEM_READ_DATA_OUT_ID: &str = "data_out"; + +#[derive(Serialize, Deserialize, Clone)] +pub struct DataMem { + pub id: String, + pub pos: (f32, f32), + pub address_input: Input, + pub data_input: Input, + pub op_input: Input, + pub write_enable_input: Input, + // should probably not skip mem rc here, since we still need them to point to the same MipsMem + #[serde(skip)] + pub mem: Rc>, + pub mem_view: RefCell, +} + +impl DataMem { + pub fn new( + id: String, + pos: (f32, f32), + address_input: Input, + data_input: Input, + op_input: Input, + write_enable_input: Input, + mem: Rc>, + ) -> Self { + let mem_view = MemViewWindow::new(id.clone(), "Data memory view".into(), Rc::clone(&mem)) + .set_data_view(); + DataMem { + id: id, + pos: pos, + mem: mem, + address_input: address_input, + data_input: data_input, + op_input: op_input, + write_enable_input: write_enable_input, + mem_view: RefCell::new(mem_view), + } + } + pub fn rc_new( + id: String, + pos: (f32, f32), + address_input: Input, + data_input: Input, + op_input: Input, + write_enable_input: Input, + mem: Rc>, + ) -> Rc { + Rc::new(DataMem::new( + id, + pos, + address_input, + data_input, + op_input, + write_enable_input, + mem, + )) + } + pub fn set_mem_view_reg(mut self, reg_rc: Rc) -> Self { + self.mem_view.get_mut().update_regfile(reg_rc); + self + } +} + +#[typetag::serde()] +impl Component for DataMem { + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn to_(&self) { + //println!("InstrMem"); + } + #[cfg(feature = "gui-egui")] + fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + let dummy_input = Input::new("dummy", "out"); + let memref = Rc::new(RefCell::new(MipsMem::default())); + Box::new(DataMem::rc_new( + id.to_string(), + pos, + dummy_input.clone(), + dummy_input.clone(), + dummy_input.clone(), + dummy_input, + memref, + )) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + DATA_MEM_A_IN_ID => self.address_input = new_input, + DATA_MEM_OP_IN_ID => self.op_input = new_input, + DATA_MEM_WRITE_ENABLE_ID => self.op_input = new_input, + DATA_MEM_WD_IN_ID => self.write_enable_input = new_input, + _ => {} + } + } + + fn get_id_ports(&self) -> (String, Ports) { + ( + self.id.clone(), + Ports::new( + vec![ + &InputPort { + port_id: DATA_MEM_A_IN_ID.to_string(), + input: self.address_input.clone(), + }, + &InputPort { + port_id: DATA_MEM_OP_IN_ID.to_string(), + input: self.op_input.clone(), + }, + &InputPort { + port_id: DATA_MEM_WD_IN_ID.to_string(), + input: self.data_input.clone(), + }, + &InputPort { + port_id: DATA_MEM_WRITE_ENABLE_ID.to_string(), + input: self.write_enable_input.clone(), + }, + ], + OutputType::Combinatorial, + vec![DATA_MEM_READ_DATA_OUT_ID], + ), + ) + } + + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get instr at pc/4s + let address: u32 = simulator + .get_input_value(&self.address_input) + .try_into() + .unwrap(); + + // is operation load or store ect + let mem_op: u32 = simulator + .get_input_value(&self.op_input) + .try_into() + .unwrap(); + + let write_enable: bool = simulator + .get_input_value(&self.write_enable_input) + .try_into() + .unwrap(); + + let data: u32 = simulator + .get_input_value(&self.data_input) + .try_into() + .unwrap(); + + // update dynamic symbol PC_IM + self.mem_view + .borrow_mut() + .set_dynamic_symbol("DM_ADRS", address); + + // check if write enable and mem op match + let is_write_enable_valid = match mem_op { + data_op::LOAD_BYTE + | data_op::LOAD_BYTE_U + | data_op::LOAD_HALF + | data_op::LOAD_HALF_U + | data_op::LOAD_WORD => !write_enable, + data_op::STORE_BYTE | data_op::STORE_HALF | data_op::STORE_WORD => write_enable, + _ => true, + }; + + if !is_write_enable_valid { + return Err(Condition::Error(format!( + "write_enable ({}) doesn't match mem_op ({})", + write_enable, mem_op + ))); + } + const SIGNED: bool = true; + const UNSIGNED: bool = false; + + match mem_op { + data_op::NO_OP => { + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); + Ok(()) + } + data_op::LOAD_BYTE => { + let val = self + .mem + .borrow() + .get_unaligned(address, MemOpSize::Byte, SIGNED, true); + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); + Ok(()) + } + data_op::LOAD_BYTE_U => { + let val = self + .mem + .borrow() + .get_unaligned(address, MemOpSize::Byte, UNSIGNED, true); + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); + Ok(()) + } + data_op::LOAD_HALF => { + match self + .mem + .borrow() + .get(address, MemOpSize::Half, SIGNED, true) + { + Ok(val) => { + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); + Ok(()) + } + Err(_) => Err(Condition::Error(format!( + "Tried to read unaligned half word, address {:#0x}", + address + ))), + } + } + data_op::LOAD_HALF_U => { + match self + .mem + .borrow() + .get(address, MemOpSize::Half, UNSIGNED, true) + { + Ok(val) => { + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); + Ok(()) + } + Err(_) => Err(Condition::Error(format!( + "Tried to read unaligned half word, address {:#0x}", + address + ))), + } + } + data_op::LOAD_WORD => { + match self + .mem + .borrow() + .get(address, MemOpSize::Word, UNSIGNED, true) + { + Ok(val) => { + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); + Ok(()) + } + Err(_) => Err(Condition::Error(format!( + "Tried to read unaligned word, address {:#0x}", + address + ))), + } + } + data_op::STORE_BYTE => { + self.mem + .borrow_mut() + .write(address, data, MemOpSize::Byte, true); + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); + Ok(()) + } + data_op::STORE_HALF => { + match self + .mem + .borrow_mut() + .write_aligned(address, data, MemOpSize::Half, true) + { + Ok(_) => { + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); + Ok(()) + } + Err(_) => Err(Condition::Error(format!( + "Tried to write unaligned half word, address {:#0x}", + address + ))), + } + } + data_op::STORE_WORD => { + match self + .mem + .borrow_mut() + .write_aligned(address, data, MemOpSize::Word, true) + { + Ok(_) => { + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); + Ok(()) + } + Err(_) => Err(Condition::Error(format!( + "Tried to write unaligned word, address {:#0x}", + address + ))), + } + } + _ => Err(Condition::Error(format!("unknown mem op {}", mem_op))), + } + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index 6be2f3d8..a70d93e0 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -8,6 +8,7 @@ mod full_adder; mod mem; mod mips_branch_logic; mod mips_controll_unit; +mod mips_dm; mod mips_im; mod mips_instruction_splitter; mod mips_jump_merge; @@ -36,6 +37,7 @@ pub use full_adder::*; pub use mem::*; pub use mips_branch_logic::*; pub use mips_controll_unit::*; +pub use mips_dm::*; pub use mips_im::*; pub use mips_instruction_splitter::*; pub use mips_jump_merge::*; diff --git a/src/gui_egui/components/mips_dm.rs b/src/gui_egui/components/mips_dm.rs new file mode 100644 index 00000000..ed2976a8 --- /dev/null +++ b/src/gui_egui/components/mips_dm.rs @@ -0,0 +1,108 @@ +use crate::common::{EguiComponent, Id, Ports, Simulator}; +use crate::components::DataMem; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::basic_component_gui; +use egui::{Rect, Response, RichText, Ui, Vec2}; + +#[typetag::serde] +impl EguiComponent for DataMem { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + _editor_mode: EditorMode, + ) -> Option> { + // we could avoid this if we clone self in our basic_component_ui. + // but instead we let our Closure save stuff here (let path_option, mem_view_vis) + // and apply our changes when basic_component_gui returns our borrow + // this is to avoid cloning all the fields. + // avoiding to clone the fields might be premature optimization + // as instrMem.mem is a reference count and wont actually clone the underlying btree and hashmaps + // + // we save 27 bytes of clone + // and most of that clone might even be optimized away + // yes this was premature optimization + let mut mem_view_vis: bool = self.mem_view.borrow().visible; + + let r = basic_component_gui( + self, + &simulator, + ui.ctx(), + (0f32, 0f32), + offset, + scale, + clip_rect, + |ui| { + // ui.centered_and_justified(|ui| { + ui.label(RichText::new("Data memory").size(12f32 * scale)); + ui.button( + RichText::new("load file") + .size(12f32 * scale) + .strikethrough(), + ) + .on_hover_text("Use instruction memory to load a file"); + + match mem_view_vis { + false => { + if ui.button("Show mem window").clicked() { + mem_view_vis = true; + } + } + true => { + ui.toggle_value(&mut mem_view_vis, "Hide mem window"); + } + }; + // }); + }, + ); + let mut mem_view = self.mem_view.borrow_mut(); + mem_view.visible = mem_view_vis; + mem_view.render(ui.ctx()); + // return response from basic component gui + r + } + + fn render_editor( + &mut self, + ui: &mut egui::Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: egui::Vec2, + scale: f32, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + self.render( + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ); + EditorRenderReturn { + delete: false, + resp: None, + } + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } + + fn top_padding(&self) -> f32 { + 20f32 + } +} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index 5697e48b..c8109fe6 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -8,6 +8,7 @@ mod full_adder; mod mem; mod mips_branch_logic; mod mips_controll_unit; +mod mips_dm; mod mips_im; mod mips_instruction_splitter; mod mips_jump_merge; From a585ef9d8afbd01fc213259e8a37c3b6c9cc3198 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 21 Aug 2024 15:21:09 +0200 Subject: [PATCH 063/126] updated control unit to take care of data op /mem_mode --- src/components/mips_controll_unit.rs | 42 +++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/components/mips_controll_unit.rs b/src/components/mips_controll_unit.rs index 1f907eef..67b004d3 100644 --- a/src/components/mips_controll_unit.rs +++ b/src/components/mips_controll_unit.rs @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; use std::{any::Any, rc::Rc}; use super::alu_op; // values used in communication to the alu - +use super::data_op; // values used in communication with the data memory /// The input and output felid ids for the control unit pub mod cntr_field { @@ -65,7 +65,7 @@ pub mod cntr_field { //TODO // NOTE no mem mode, decided to pass opcode to data mem instead, // might change when LWL/LWR is implemented along with the load/store controller - // pub const MEM_MODE_OUT : &str = "mem_mode"; + pub const MEM_MODE_OUT: &str = "mem_mode"; } const NOP: u32 = 0; @@ -217,6 +217,7 @@ impl Component for ControlUnit { cntr_field::BRANCH_INTERRUPT_OUT, cntr_field::CP0_OUT, cntr_field::MMU_OUT, + cntr_field::MEM_MODE_OUT, ], ), ) @@ -326,6 +327,7 @@ impl Component for ControlUnit { cntr_field::BRANCH_INTERRUPT_OUT, cntr_unit_signals::NO_BRANCH_INTERRUPT ); + set!(cntr_field::MEM_MODE_OUT,); //TODO an idea would be to init all variables // let alu_src_a : Signal; // this would make the compiler force us to populate all paths so to not let any signal be undefined @@ -635,12 +637,44 @@ impl Component for ControlUnit { ))) } //TODO use mem_mode, now it assumed data_mem uses opcode to determine that itself - OP_LB | OP_LBU | OP_LH | OP_LHU | OP_LW => { + OP_LB => { + set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_BYTE); + set_load_instr!(); + Ok(()) + } + OP_LBU => { + set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_BYTE_U); + set_load_instr!(); + Ok(()) + } + OP_LH => { + set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_HALF); + set_load_instr!(); + Ok(()) + } + OP_LHU => { + set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_HALF_U); + set_load_instr!(); + Ok(()) + } + OP_LW => { + set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_WORD); set_load_instr!(); Ok(()) } - OP_SB | OP_SH | OP_SW => { + OP_SB => { + set!(cntr_field::MEM_MODE_OUT, data_op::STORE_WORD); + set_store_instr!(); + Ok(()) + } + OP_SH => { + set!(cntr_field::MEM_MODE_OUT, data_op::STORE_WORD); + set_store_instr!(); + Ok(()) + } + OP_SW => { + set!(cntr_field::MEM_MODE_OUT, data_op::STORE_WORD); set_store_instr!(); Ok(()) } From 346f2b1756c0d51357bd23dc3a288872aef5cf85 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 21 Aug 2024 16:57:28 +0200 Subject: [PATCH 064/126] fixed wrong constants and use of magic values --- src/components/mips_controll_unit.rs | 4 ++-- src/components/mips_im.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/mips_controll_unit.rs b/src/components/mips_controll_unit.rs index 67b004d3..889f9074 100644 --- a/src/components/mips_controll_unit.rs +++ b/src/components/mips_controll_unit.rs @@ -148,7 +148,7 @@ pub mod cntr_unit_signals { pub const ALU_SRC_A_SHAMT: u32 = 0; pub const ALU_SRC_A_RS: u32 = 1; - pub const ALU_SRC_A_ZERO: u32 = 3; + pub const ALU_SRC_A_ZERO: u32 = 2; pub const ALU_SRC_B_RT: u32 = 0; pub const ALU_SRC_B_PC: u32 = 1; @@ -327,7 +327,7 @@ impl Component for ControlUnit { cntr_field::BRANCH_INTERRUPT_OUT, cntr_unit_signals::NO_BRANCH_INTERRUPT ); - set!(cntr_field::MEM_MODE_OUT,); + set!(cntr_field::MEM_MODE_OUT, data_op::NO_OP); //TODO an idea would be to init all variables // let alu_src_a : Signal; // this would make the compiler force us to populate all paths so to not let any signal be undefined diff --git a/src/components/mips_im.rs b/src/components/mips_im.rs index 5fcc0817..81235400 100644 --- a/src/components/mips_im.rs +++ b/src/components/mips_im.rs @@ -121,7 +121,7 @@ impl Component for InstrMem { // sign extend doesn't mater since we have 32 bits so extending to 32bits does nothing match self.mem.borrow().get(pc, MemOpSize::Word, false, true) { Ok(instr) => { - simulator.set_out_value(&self.id, "instruction", instr); + simulator.set_out_value(&self.id, INSTR_MEM_INSTRUCTION_ID, instr); // check if pc is at breakpoint match self.mem_view.borrow().is_break_point(&pc) { true => Err(Condition::Halt(format!("Reached breakpoint at {:#0x}", pc))), From 477df0791c16338a8b88a0de573398995c638405 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 21 Aug 2024 16:57:54 +0200 Subject: [PATCH 065/126] added IM and dm to mips example --- examples/mips_example_1.rs | 69 +++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/examples/mips_example_1.rs b/examples/mips_example_1.rs index a4ec2cc2..8c9bf2eb 100644 --- a/examples/mips_example_1.rs +++ b/examples/mips_example_1.rs @@ -1,6 +1,6 @@ // use crate::src::components::cntr_unit_signals; -use std::path::PathBuf; use std::rc::Rc; +use std::{cell::RefCell, path::PathBuf}; use syncrim::common::EguiComponent; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; @@ -13,6 +13,18 @@ use syncrim::{ fn main() { fern_setup(); + + let mem = Rc::new(RefCell::new(MipsMem::default())); + let rc_reg_file = RegFile::rc_new( + "reg_file", + (3100.0, 2000.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + Input::new("mux_write_addr", REGISTER_OUT_ID), //write address + Input::new("result_reg", REGISTER_OUT_ID), //write data + Input::new("reg_we", REGISTER_OUT_ID), + ); + let cs = ComponentStore { store: vec![ // register that holds instr addr @@ -27,15 +39,26 @@ fn main() { ), // // + Rc::new( + InstrMem::new( + "instr_mem".into(), + (200.0, 500.0), + Input::new("pc", "out"), + Rc::clone(&mem), + ) + .set_mem_view_reg(rc_reg_file.clone()), + ), + // + // // MUX to choose what intruction addr to choose from, branch jump, reg, pc+4 Mux::rc_new( "mux_jump_merge", (1800.0, 5000.0), Input::new("branch", BRANCH_OUT_ID), vec![ - Input::new("pc_add_branch", FULL_ADD_OUT_ID), //TODO: describe origin + Input::new("pc_add_branch", ADD_OUT_ID), //TODO: describe origin Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), // goes to addr, RD2 - Input::new("jump_merge", MERGE_OUT_ID), // + Input::new("jump_merge", MERGE_OUT_ID), // Input::new("pc+4", CLK_OUT_ID), ], ), @@ -45,18 +68,22 @@ fn main() { "jump_merge", (1700.0, 5300.0), Input::new("pc", REGISTER_OUT_ID), //input from reg before pc+4 - Input::new("dummy", "out"), //input from instruction mem + Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), //input from instruction mem ), // // splits intructions from ir to fields InstrSplit::rc_new( "instruction_split", (2400.0, 4000.0), - Input::new("dummy", "out"), + Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), ), //TODO: take im input // // - ControlUnit::rc_new("control_unit", (5000.0, 500.0), Input::new("dummy", "out")), //TODO: take im input + ControlUnit::rc_new( + "control_unit", + (5000.0, 500.0), + Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), + ), //TODO: take im input // // Register::rc_new( @@ -74,17 +101,6 @@ fn main() { ), // // - RegFile::rc_new( - "reg_file", - (3100.0, 2000.0), - Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), - Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), - Input::new("mux_write_addr", REGISTER_OUT_ID), //write address - Input::new("result_reg", REGISTER_OUT_ID), //write data - Input::new("reg_we", REGISTER_OUT_ID), - ), - // - // BranchLogic::rc_new( "branch", (3300.0, 2000.0), @@ -110,8 +126,8 @@ fn main() { Input::new("control_unit", cntr_field::ALU_SRC_A_OUT), vec![ Input::new("zero_extend_for_chamt", SIGNZEROEXTEND_OUT_ID), - Input::new("0_a_inp", "out"), Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), + Input::new("0_a_inp", "out"), ], ), // @@ -137,13 +153,27 @@ fn main() { ), // // + Rc::new( + DataMem::new( + "data_mem".into(), + (4100.0, 2200.0), + Input::new("alu", FULL_ADD_OUT_ID), // calculated from rs and imm + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), + Input::new("control_unit", cntr_field::MEM_MODE_OUT), + Input::new("control_unit", cntr_field::MEM_WRITE_ENABLE_OUT), + Rc::clone(&mem), + ) + .set_mem_view_reg(rc_reg_file.clone()), + ), + // + // Mux::rc_new( "mux_write_back", (4300.0, 2200.0), Input::new("control_unit", cntr_field::REG_WRITE_SRC_OUT), vec![ Input::new("alu", FULL_ADD_OUT_ID), - Input::new("dummy", "out"), //TODO: data meme output + Input::new("data_mem", DATA_MEM_READ_DATA_OUT_ID), //TODO: data meme output ], ), // @@ -192,6 +222,7 @@ fn main() { // // Constant::rc_new("dummy", (6000.0, 3000.0), 0), + rc_reg_file, ], }; From 2b4d4cb9599c78d703de03ab8ff94377805c8487 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 21 Aug 2024 17:30:36 +0200 Subject: [PATCH 066/126] Fixed, write address skipped reg, switched rs rt for alu_src. order of mux_write_addr --- examples/mips_example_1.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/mips_example_1.rs b/examples/mips_example_1.rs index 8c9bf2eb..7dd2973f 100644 --- a/examples/mips_example_1.rs +++ b/examples/mips_example_1.rs @@ -20,7 +20,7 @@ fn main() { (3100.0, 2000.0), Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), - Input::new("mux_write_addr", REGISTER_OUT_ID), //write address + Input::new("reg_write_addr", REGISTER_OUT_ID), //write address Input::new("result_reg", REGISTER_OUT_ID), //write data Input::new("reg_we", REGISTER_OUT_ID), ); @@ -126,7 +126,7 @@ fn main() { Input::new("control_unit", cntr_field::ALU_SRC_A_OUT), vec![ Input::new("zero_extend_for_chamt", SIGNZEROEXTEND_OUT_ID), - Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), + Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), //FIXME should be rs? changed from rt Input::new("0_a_inp", "out"), ], ), @@ -137,7 +137,7 @@ fn main() { (3800.0, 2200.0), Input::new("control_unit", cntr_field::ALU_SRC_B_OUT), vec![ - Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), //FIXME should be rt? changed from rs Input::new("pc+4", ADD_OUT_ID), Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), ], @@ -208,8 +208,8 @@ fn main() { Input::new("control_unit", cntr_field::REG_DEST_OUT), vec![ Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), - Input::new("0x_1F", "out"), Input::new("instruction_split", INSTRUCTION_SPLITTER_RD_ID), + Input::new("0x_1F", "out"), ], ), // From 3b85eb4a279e93dd67e87062ab8d0dd6ca931ead Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 28 Aug 2024 11:07:51 +0200 Subject: [PATCH 067/126] fix: rt instead of rs, wrong MemOpSize, jump merge logic --- examples/mips_example_1.rs | 4 ++-- src/components/mips_controll_unit.rs | 4 ++-- src/components/mips_jump_merge.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/mips_example_1.rs b/examples/mips_example_1.rs index 7dd2973f..98728c93 100644 --- a/examples/mips_example_1.rs +++ b/examples/mips_example_1.rs @@ -57,7 +57,7 @@ fn main() { Input::new("branch", BRANCH_OUT_ID), vec![ Input::new("pc_add_branch", ADD_OUT_ID), //TODO: describe origin - Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), // goes to addr, RD2 + Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), // goes to addr, RD2 Input::new("jump_merge", MERGE_OUT_ID), // Input::new("pc+4", CLK_OUT_ID), ], @@ -201,7 +201,7 @@ fn main() { ), // // - Constant::rc_new("0x_1F", (3750.0, 5500.0), 0), + Constant::rc_new("0x_1F", (3750.0, 5500.0), 0x_1F), Mux::rc_new( "mux_write_addr", (3800.0, 5500.0), diff --git a/src/components/mips_controll_unit.rs b/src/components/mips_controll_unit.rs index 889f9074..68e65fca 100644 --- a/src/components/mips_controll_unit.rs +++ b/src/components/mips_controll_unit.rs @@ -664,12 +664,12 @@ impl Component for ControlUnit { } OP_SB => { - set!(cntr_field::MEM_MODE_OUT, data_op::STORE_WORD); + set!(cntr_field::MEM_MODE_OUT, data_op::STORE_BYTE); set_store_instr!(); Ok(()) } OP_SH => { - set!(cntr_field::MEM_MODE_OUT, data_op::STORE_WORD); + set!(cntr_field::MEM_MODE_OUT, data_op::STORE_HALF); set_store_instr!(); Ok(()) } diff --git a/src/components/mips_jump_merge.rs b/src/components/mips_jump_merge.rs index f35f1606..db18afaa 100644 --- a/src/components/mips_jump_merge.rs +++ b/src/components/mips_jump_merge.rs @@ -77,7 +77,7 @@ impl Component for JumpMerge { .try_into() .unwrap(); - let output = (instr_addr & 0xf000_0000) & (jump_addr << 2); + let output = (instr_addr & 0xf000_0000) | ((jump_addr << 2) & 0x0fff_ffff); simulator.set_out_value(&self.id, MERGE_OUT_ID, SignalValue::Data(output)); Ok(()) From ca73f745f3eb906e1c2fe005d5cc21ab810d113e Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 28 Aug 2024 15:03:15 +0200 Subject: [PATCH 068/126] moved components in mips example --- examples/mips_example_1.rs | 55 +++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/examples/mips_example_1.rs b/examples/mips_example_1.rs index 98728c93..7a768903 100644 --- a/examples/mips_example_1.rs +++ b/examples/mips_example_1.rs @@ -17,7 +17,7 @@ fn main() { let mem = Rc::new(RefCell::new(MipsMem::default())); let rc_reg_file = RegFile::rc_new( "reg_file", - (3100.0, 2000.0), + (360.0, 170.0), Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), Input::new("reg_write_addr", REGISTER_OUT_ID), //write address @@ -28,12 +28,12 @@ fn main() { let cs = ComponentStore { store: vec![ // register that holds instr addr - Register::rc_new("pc", (2000.0, 5000.0), Input::new("mux_jump_merge", "out")), + Register::rc_new("pc", (170.0, 410.0), Input::new("mux_jump_merge", "out")), // step addr from reg by 4 - Constant::rc_new("+4", (2000.0, 5100.0), 4), + Constant::rc_new("+4", (170.0, 380.0), 4), Add::rc_new( "pc+4", - (2200.0, 5000.0), + (220.0, 380.0), Input::new("pc", "out"), Input::new("+4", "out"), ), @@ -42,7 +42,7 @@ fn main() { Rc::new( InstrMem::new( "instr_mem".into(), - (200.0, 500.0), + (280.0, 600.0), Input::new("pc", "out"), Rc::clone(&mem), ) @@ -53,7 +53,7 @@ fn main() { // MUX to choose what intruction addr to choose from, branch jump, reg, pc+4 Mux::rc_new( "mux_jump_merge", - (1800.0, 5000.0), + (140.0, 390.0), Input::new("branch", BRANCH_OUT_ID), vec![ Input::new("pc_add_branch", ADD_OUT_ID), //TODO: describe origin @@ -66,7 +66,7 @@ fn main() { // merges to find out jump location JumpMerge::rc_new( "jump_merge", - (1700.0, 5300.0), + (125.0, 500.0), Input::new("pc", REGISTER_OUT_ID), //input from reg before pc+4 Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), //input from instruction mem ), @@ -74,28 +74,28 @@ fn main() { // splits intructions from ir to fields InstrSplit::rc_new( "instruction_split", - (2400.0, 4000.0), + (280.0, 140.0), Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), - ), //TODO: take im input + ), // // ControlUnit::rc_new( "control_unit", - (5000.0, 500.0), + (280.0, 100.0), Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), - ), //TODO: take im input + ), // // Register::rc_new( "reg_we", - (4400.0, 500.0), + (850.0, 100.0), Input::new("control_unit", cntr_field::REG_WRITE_ENABLE_OUT), ), // // extends immediate field SignZeroExtend::rc_new( "signzero_extend", - (2600.0, 5000.0), + (310.0, 410.0), Input::new("instruction_split", INSTRUCTION_SPLITTER_IMMEDIATE_ID), Input::new("control_unit", cntr_field::EXTEND_SELECT_OUT), // cu tells it to either sing- or zero- extend ), @@ -103,7 +103,7 @@ fn main() { // BranchLogic::rc_new( "branch", - (3300.0, 2000.0), + (525.0, 300.0), Input::new("instruction_split", INSTRUCTION_SPLITTER_OP_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_FUNCT_ID), @@ -114,15 +114,15 @@ fn main() { // ZeroExtend::rc_new( "zero_extend_for_chamt", - (3700.0, 1600.0), + (550.0, 170.0), Input::new("instruction_split", INSTRUCTION_SPLITTER_SHAMT_ID), ), // // - Constant::rc_new("0_a_inp", (3800.0, 1700.0), 0), + Constant::rc_new("0_a_inp", (600.0, 230.0), 0), Mux::rc_new( "mux_source_a", - (3800.0, 1800.0), + (650.0, 220.0), Input::new("control_unit", cntr_field::ALU_SRC_A_OUT), vec![ Input::new("zero_extend_for_chamt", SIGNZEROEXTEND_OUT_ID), @@ -134,7 +134,7 @@ fn main() { // Mux::rc_new( "mux_source_b", - (3800.0, 2200.0), + (650.0, 300.0), Input::new("control_unit", cntr_field::ALU_SRC_B_OUT), vec![ Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), //FIXME should be rt? changed from rs @@ -146,7 +146,7 @@ fn main() { // FullAdd::rc_new( "alu", - (4100.0, 2000.0), + (720.0, 220.0), Input::new("mux_source_a", MUX_OUT_ID), Input::new("mux_source_b", MUX_OUT_ID), Input::new("control_unit", cntr_field::ALU_OP_OUT), @@ -156,7 +156,7 @@ fn main() { Rc::new( DataMem::new( "data_mem".into(), - (4100.0, 2200.0), + (600.0, 580.0), Input::new("alu", FULL_ADD_OUT_ID), // calculated from rs and imm Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), Input::new("control_unit", cntr_field::MEM_MODE_OUT), @@ -169,7 +169,7 @@ fn main() { // Mux::rc_new( "mux_write_back", - (4300.0, 2200.0), + (800.0, 270.0), Input::new("control_unit", cntr_field::REG_WRITE_SRC_OUT), vec![ Input::new("alu", FULL_ADD_OUT_ID), @@ -180,14 +180,14 @@ fn main() { // Register::rc_new( "result_reg", - (4400.0, 2200.0), + (850.0, 290.0), Input::new("mux_write_back", MUX_OUT_ID), ), // // ShiftConst::rc_new( "branch_shift", - (2900.0, 5250.0), + (380.0, 460.0), Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), 2, ), @@ -195,16 +195,16 @@ fn main() { // Add::rc_new( "pc_add_branch", - (3000.0, 5200.0), + (420.0, 440.0), Input::new("pc+4", ADD_OUT_ID), Input::new("branch_shift", SHIFT_OUT_ID), ), // // - Constant::rc_new("0x_1F", (3750.0, 5500.0), 0x_1F), + Constant::rc_new("0x_1F", (500.0, 510.0), 0x_1F), Mux::rc_new( "mux_write_addr", - (3800.0, 5500.0), + (560.0, 500.0), Input::new("control_unit", cntr_field::REG_DEST_OUT), vec![ Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), @@ -216,12 +216,11 @@ fn main() { // Register::rc_new( "reg_write_addr", - (4400.0, 5500.0), + (850.0, 520.0), Input::new("mux_write_addr", MUX_OUT_ID), ), // // - Constant::rc_new("dummy", (6000.0, 3000.0), 0), rc_reg_file, ], }; From 4734d8b517b819f8e5af35268d644a6d0ef09ccf Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 28 Aug 2024 15:23:32 +0200 Subject: [PATCH 069/126] updated ui stuff to deal with scaling --- src/gui_egui/components/and.rs | 17 +-- src/gui_egui/components/equal.rs | 17 +-- src/gui_egui/components/mips_branch_logic.rs | 17 +-- src/gui_egui/components/mips_controll_unit.rs | 25 ++-- src/gui_egui/components/mips_dm.rs | 49 +++---- src/gui_egui/components/mips_im.rs | 43 +++--- .../components/mips_instruction_splitter.rs | 25 ++-- src/gui_egui/components/mips_jump_merge.rs | 17 +-- src/gui_egui/components/mips_reg_file.rs | 128 ++++++++---------- src/gui_egui/components/shift_left_const.rs | 19 +-- src/gui_egui/components/sz_extend.rs | 56 +++----- src/gui_egui/components/zero_extend.rs | 17 +-- src/gui_egui/helper.rs | 50 +++---- 13 files changed, 174 insertions(+), 306 deletions(-) diff --git a/src/gui_egui/components/and.rs b/src/gui_egui/components/and.rs index dfbd82e3..e6c8615c 100644 --- a/src/gui_egui/components/and.rs +++ b/src/gui_egui/components/and.rs @@ -17,20 +17,9 @@ impl EguiComponent for And { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - basic_component_gui( - self, - &simulator, - ui.ctx(), - (0f32, 0f32), - offset, - scale, - clip_rect, - |ui| { - ui.centered_and_justified(|ui| { - ui.label(RichText::new("And").size(12f32 * scale)); - }); - }, - ) + basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.label("And"); + }) } fn render_editor( diff --git a/src/gui_egui/components/equal.rs b/src/gui_egui/components/equal.rs index 830c6ce3..e83e1b15 100644 --- a/src/gui_egui/components/equal.rs +++ b/src/gui_egui/components/equal.rs @@ -17,20 +17,9 @@ impl EguiComponent for Equal { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - basic_component_gui( - self, - &simulator, - ui.ctx(), - (0f32, 0f32), - offset, - scale, - clip_rect, - |ui| { - ui.centered_and_justified(|ui| { - ui.label(RichText::new("Equal").size(12f32 * scale)); - }); - }, - ) + basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.label("Equal"); + }) } fn render_editor( diff --git a/src/gui_egui/components/mips_branch_logic.rs b/src/gui_egui/components/mips_branch_logic.rs index 12fa4ad7..42e4399b 100644 --- a/src/gui_egui/components/mips_branch_logic.rs +++ b/src/gui_egui/components/mips_branch_logic.rs @@ -17,20 +17,9 @@ impl EguiComponent for BranchLogic { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - basic_component_gui( - self, - &simulator, - ui.ctx(), - (0f32, 0f32), - offset, - scale, - clip_rect, - |ui| { - ui.centered_and_justified(|ui| { - ui.label(RichText::new("Branch Logic").size(12f32 * scale)); - }); - }, - ) + basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.label("Branch Logic".to_string()); + }) } fn render_editor( diff --git a/src/gui_egui/components/mips_controll_unit.rs b/src/gui_egui/components/mips_controll_unit.rs index c75aa8d3..183ff43b 100644 --- a/src/gui_egui/components/mips_controll_unit.rs +++ b/src/gui_egui/components/mips_controll_unit.rs @@ -18,22 +18,15 @@ impl EguiComponent for ControlUnit { _editor_mode: EditorMode, ) -> Option> { // size of the component - let width = 400f32; - let height: f32 = 12f32; - basic_component_gui( - self, - &simulator, - ui.ctx(), - (width, height), - offset, - scale, - clip_rect, - |ui| { - ui.centered_and_justified(|ui| { - ui.label(RichText::new("Control Unit").size(12f32 * scale)); - }); - }, - ) + let width = 400f32 * scale; + let height: f32 = 12f32 * scale; + basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.set_height(height); + ui.set_width(width); + ui.centered_and_justified(|ui| { + ui.label("Control Unit"); + }); + }) } fn render_editor( diff --git a/src/gui_egui/components/mips_dm.rs b/src/gui_egui/components/mips_dm.rs index ed2976a8..885d6602 100644 --- a/src/gui_egui/components/mips_dm.rs +++ b/src/gui_egui/components/mips_dm.rs @@ -29,37 +29,28 @@ impl EguiComponent for DataMem { // yes this was premature optimization let mut mem_view_vis: bool = self.mem_view.borrow().visible; - let r = basic_component_gui( - self, - &simulator, - ui.ctx(), - (0f32, 0f32), - offset, - scale, - clip_rect, - |ui| { - // ui.centered_and_justified(|ui| { - ui.label(RichText::new("Data memory").size(12f32 * scale)); - ui.button( - RichText::new("load file") - .size(12f32 * scale) - .strikethrough(), - ) - .on_hover_text("Use instruction memory to load a file"); + let r = basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + // ui.centered_and_justified(|ui| { + ui.label(RichText::new("Data memory").size(12f32 * scale)); + ui.button( + RichText::new("load file") + .size(12f32 * scale) + .strikethrough(), + ) + .on_hover_text("Use instruction memory to load a file"); - match mem_view_vis { - false => { - if ui.button("Show mem window").clicked() { - mem_view_vis = true; - } + match mem_view_vis { + false => { + if ui.button("Show mem window").clicked() { + mem_view_vis = true; } - true => { - ui.toggle_value(&mut mem_view_vis, "Hide mem window"); - } - }; - // }); - }, - ); + } + true => { + ui.toggle_value(&mut mem_view_vis, "Hide mem window"); + } + }; + // }); + }); let mut mem_view = self.mem_view.borrow_mut(); mem_view.visible = mem_view_vis; mem_view.render(ui.ctx()); diff --git a/src/gui_egui/components/mips_im.rs b/src/gui_egui/components/mips_im.rs index d785ea37..2fa20899 100644 --- a/src/gui_egui/components/mips_im.rs +++ b/src/gui_egui/components/mips_im.rs @@ -36,34 +36,25 @@ impl EguiComponent for InstrMem { let mut path_option: Option = None; let mut mem_view_vis: bool = self.mem_view.borrow().visible; - let r = basic_component_gui( - self, - &simulator, - ui.ctx(), - (0f32, 0f32), - offset, - scale, - clip_rect, - |ui| { - // ui.centered_and_justified(|ui| { - ui.label(RichText::new("Instruction memory").size(12f32 * scale)); - if ui.button("load file").clicked() { - path_option = rfd::FileDialog::new().pick_file(); - }; + let r = basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + // ui.centered_and_justified(|ui| { + ui.label(RichText::new("Instruction memory").size(12f32 * scale)); + if ui.button("load file").clicked() { + path_option = rfd::FileDialog::new().pick_file(); + }; - match mem_view_vis { - false => { - if ui.button("Show mem window").clicked() { - mem_view_vis = true; - } + match mem_view_vis { + false => { + if ui.button("Show mem window").clicked() { + mem_view_vis = true; } - true => { - ui.toggle_value(&mut mem_view_vis, "Hide mem window"); - } - }; - // }); - }, - ); + } + true => { + ui.toggle_value(&mut mem_view_vis, "Hide mem window"); + } + }; + // }); + }); if let Some(path) = path_option { let data = fs::read(path).unwrap(); diff --git a/src/gui_egui/components/mips_instruction_splitter.rs b/src/gui_egui/components/mips_instruction_splitter.rs index 7f772e3a..a717189a 100644 --- a/src/gui_egui/components/mips_instruction_splitter.rs +++ b/src/gui_egui/components/mips_instruction_splitter.rs @@ -18,22 +18,15 @@ impl EguiComponent for InstrSplit { _editor_mode: EditorMode, ) -> Option> { // size of the component - let width = 50f32; - let height: f32 = 300f32; - basic_component_gui( - self, - &simulator, - ui.ctx(), - (width, height), - offset, - scale, - clip_rect, - |ui| { - ui.centered_and_justified(|ui| { - ui.label(RichText::new("instruction\nspliter").size(12f32 * scale)); - }); - }, - ) + let width = 50f32 * scale; + let height: f32 = 300f32 * scale; + basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.set_height(height); + ui.set_width(width); + ui.centered_and_justified(|ui| { + ui.label(RichText::new("instruction\nspliter").size(12f32 * scale)); + }); + }) } fn render_editor( diff --git a/src/gui_egui/components/mips_jump_merge.rs b/src/gui_egui/components/mips_jump_merge.rs index 45076f56..9ce5d08d 100644 --- a/src/gui_egui/components/mips_jump_merge.rs +++ b/src/gui_egui/components/mips_jump_merge.rs @@ -17,20 +17,9 @@ impl EguiComponent for JumpMerge { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - basic_component_gui( - self, - &simulator, - ui.ctx(), - (0f32, 0f32), - offset, - scale, - clip_rect, - |ui| { - ui.centered_and_justified(|ui| { - ui.label(RichText::new("Jump Merge").size(12f32 * scale)); - }); - }, - ) + basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.label(RichText::new("Jump Merge").size(12f32 * scale)); + }) } fn render_editor( diff --git a/src/gui_egui/components/mips_reg_file.rs b/src/gui_egui/components/mips_reg_file.rs index 03dd9383..eb4d75d3 100644 --- a/src/gui_egui/components/mips_reg_file.rs +++ b/src/gui_egui/components/mips_reg_file.rs @@ -23,82 +23,72 @@ impl EguiComponent for RegFile { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - basic_component_gui( - self, - &simulator, - ui.ctx(), - (120f32, 400f32), - offset, - scale, - clip_rect, - |ui| { - ui.label(RichText::new("Register File").size(12f32 * scale)); + basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.set_width(120f32 * scale); + ui.set_height(400f32 * scale); + ui.label("Register File"); - // A toggle button for showing register names - ui.toggle_value( - &mut *self.show_reg_names.borrow_mut(), - RichText::new("Show names").size(12f32 * scale), - ); + // A toggle button for showing register names + ui.toggle_value(&mut *self.show_reg_names.borrow_mut(), "Show names"); - // showsing the display format of the register - let mut tmp: RegFormat = self.reg_format.borrow().clone(); - ComboBox::from_id_source(&self.id) - .selected_text(RichText::new(format!("{:?}", tmp)).size(12f32 * scale)) - .show_ui(ui, |ui| { - ui.selectable_value(&mut tmp, RegFormat::Hex, "Hex"); - ui.selectable_value(&mut tmp, RegFormat::DecUnsigned, "Decimal"); - ui.selectable_value(&mut tmp, RegFormat::DecSigned, "Decimal signed"); - ui.selectable_value(&mut tmp, RegFormat::Bin, "Binary"); - ui.selectable_value(&mut tmp, RegFormat::UTF8BE, "UTF-8 big endian"); - ui.selectable_value(&mut tmp, RegFormat::UTF8LE, "UTF-8 little endian"); - }); - *self.reg_format.borrow_mut() = tmp; + // showsing the display format of the register + let mut tmp: RegFormat = self.reg_format.borrow().clone(); + ComboBox::from_id_source(&self.id) + .selected_text(format!("{:?}", tmp)) + .show_ui(ui, |ui| { + ui.selectable_value(&mut tmp, RegFormat::Hex, "Hex"); + ui.selectable_value(&mut tmp, RegFormat::DecUnsigned, "Decimal"); + ui.selectable_value(&mut tmp, RegFormat::DecSigned, "Decimal signed"); + ui.selectable_value(&mut tmp, RegFormat::Bin, "Binary"); + ui.selectable_value(&mut tmp, RegFormat::UTF8BE, "UTF-8 big endian"); + ui.selectable_value(&mut tmp, RegFormat::UTF8LE, "UTF-8 little endian"); + }); + *self.reg_format.borrow_mut() = tmp; - ui.separator(); + ui.separator(); - // A scroll area with all the registers in one label - ScrollArea::vertical().show(ui, |ui| { - ui.set_width(ui.available_width()); - ui.set_height(ui.available_height()); + // A scroll area with all the registers in one label + ScrollArea::vertical().show(ui, |ui| { + ui.set_width(ui.available_width()); + ui.set_height(ui.available_height()); - // for each register format the u32 and pus that formatted sting onto - // the string representing all registers - let mut str: String = "".into(); - for (i, val) in self.registers.borrow().iter().enumerate() { - // add reg name or reg number to the formatted string - str.push_str( - match *self.show_reg_names.borrow() { - true => format!("{:<4}", REG_NAMES[i]), - false => format!("r{:<3}", i), - } - .as_str(), - ); + // for each register format the u32 and pus that formatted sting onto + // the string representing all registers + let mut str: String = "".into(); + for (i, val) in self.registers.borrow().iter().enumerate() { + // add reg name or reg number to the formatted string + str.push_str( + match *self.show_reg_names.borrow() { + true => format!("{:<4}", REG_NAMES[i]), + false => format!("r{:<3}", i), + } + .as_str(), + ); - // add a formatted register to the string - // TODO move to separate function - str.push_str( - match *self.reg_format.borrow() { - RegFormat::Hex => format!("{:#010x}", val), - RegFormat::DecSigned => format!("{}", (*val) as i32), - RegFormat::DecUnsigned => format!("{}", val), - RegFormat::Bin => format!("{:#034b}", val), - RegFormat::UTF8BE => String::from_utf8_lossy(&val.to_be_bytes()) - .escape_debug() - .to_string(), - RegFormat::UTF8LE => String::from_utf8_lossy(&val.to_le_bytes()) - .escape_debug() - .to_string(), - } - .as_str(), - ); - str.push_str("\n") - } + // add a formatted register to the string + // TODO move to separate function + str.push_str( + match *self.reg_format.borrow() { + RegFormat::Hex => format!("{:#010x}", val), + RegFormat::DecSigned => format!("{}", (*val) as i32), + RegFormat::DecUnsigned => format!("{}", val), + RegFormat::Bin => format!("{:#034b}", val), + RegFormat::UTF8BE => String::from_utf8_lossy(&val.to_be_bytes()) + .escape_debug() + .to_string(), + RegFormat::UTF8LE => String::from_utf8_lossy(&val.to_le_bytes()) + .escape_debug() + .to_string(), + } + .as_str(), + ); + str.push_str("\n") + } - // push the string as monospace to the ui - ui.label(RichText::new(str).size(12f32 * scale).monospace()) - }); - }, - ) + // push the string as monospace to the ui + ui.label(RichText::new(str).size(12f32 * scale).monospace()) + }); + }) } fn top_padding(&self) -> f32 { diff --git a/src/gui_egui/components/shift_left_const.rs b/src/gui_egui/components/shift_left_const.rs index a38f2e91..d383998c 100644 --- a/src/gui_egui/components/shift_left_const.rs +++ b/src/gui_egui/components/shift_left_const.rs @@ -17,22 +17,9 @@ impl EguiComponent for ShiftConst { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - basic_component_gui( - self, - &simulator, - ui.ctx(), - (0f32, 0f32), - offset, - scale, - clip_rect, - |ui| { - ui.centered_and_justified(|ui| { - ui.label( - RichText::new(format!("Shift << {}", self.shift_by)).size(12f32 * scale), - ); - }); - }, - ) + basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.label(format!("Shift << {}", self.shift_by)); + }) } fn render_editor( diff --git a/src/gui_egui/components/sz_extend.rs b/src/gui_egui/components/sz_extend.rs index 27bcb87a..b12fba93 100644 --- a/src/gui_egui/components/sz_extend.rs +++ b/src/gui_egui/components/sz_extend.rs @@ -17,43 +17,29 @@ impl EguiComponent for SignZeroExtend { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - basic_component_gui( - self, - &simulator, - ui.ctx(), - (0f32, 0f32), - offset, - scale, - clip_rect, - |ui| { - match &simulator { - Some(sim) => { - ui.label( - RichText::new(match sim.get_input_value(&self.signzero_ctrl_in) { - SignalValue::Uninitialized => { - " Sign/Zero extend: Uninitialized cntr".to_string() - } - SignalValue::Unknown => "Sign/Zero extendUnknown".to_string(), - SignalValue::DontCare => "Sign/Zero extend: Don't Care".to_string(), - SignalValue::Data(v) => match v { - 0 => "Sign/Zero extend: Zero", - 1 => "Sign/Zero extend: Sign", - _ => "Sign/Zero extend: Invalid cntr", - } - .to_string(), - }) - .size(12f32 * scale), - ); - } - - None => { - ui.label(RichText::new("Signal Extender: No Sim").size(12f32 * scale)); - } + basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + match &simulator { + Some(sim) => { + ui.label(match sim.get_input_value(&self.signzero_ctrl_in) { + SignalValue::Uninitialized => { + " Sign/Zero extend:\nUninitialized cntr".to_string() + } + SignalValue::Unknown => "Sign/Zero extend:\nextendUnknown".to_string(), + SignalValue::DontCare => "Sign/Zero extend:\nDon't Care".to_string(), + SignalValue::Data(v) => match v { + 0 => "Sign/Zero extend:\nZero", + 1 => "Sign/Zero extend:\nSign", + _ => "Sign/Zero extend:\nInvalid cntr", + } + .to_string(), + }); } - ui.label(RichText::new("Jump Merge").size(12f32 * scale)); - }, - ) + None => { + ui.label(RichText::new("Signal Extender:\nNo Sim").size(12f32 * scale)); + } + } + }) } fn render_editor( diff --git a/src/gui_egui/components/zero_extend.rs b/src/gui_egui/components/zero_extend.rs index b2ed9997..7a0703cb 100644 --- a/src/gui_egui/components/zero_extend.rs +++ b/src/gui_egui/components/zero_extend.rs @@ -17,20 +17,9 @@ impl EguiComponent for ZeroExtend { clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { - basic_component_gui( - self, - &simulator, - ui.ctx(), - (0f32, 0f32), - offset, - scale, - clip_rect, - |ui| { - ui.centered_and_justified(|ui| { - ui.label(RichText::new("Zero Extend").size(12f32 * scale)); - }); - }, - ) + basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.label("Zero Extend"); + }) } fn render_editor( diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index 7b065b8a..8b82dcdf 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -1,7 +1,7 @@ use crate::common::{Components, EguiComponent, Input, Ports, SignalValue, Simulator}; use crate::gui_egui::editor::{EditorMode, SnapPriority}; use egui::{ - Align2, Area, Color32, Context, InnerResponse, Order, Pos2, Rect, Response, RichText, Sense, + Align2, Area, Color32, Context, InnerResponse, Order, Pos2, Rect, Response, Sense, TextWrapMode, Ui, Vec2, }; use epaint::Shadow; @@ -187,7 +187,7 @@ pub fn component_area( /// offset, /// scale, /// |ui| { -/// ui.label(RichText::new("Jump Merge").size(12f32 * scale)); +/// ui.label("Jump Merge")); /// }, /// |ui| { /// ui.label("i am hovered") @@ -198,41 +198,42 @@ pub fn component_area( /// ``` pub fn basic_component_gui_with_on_hover( component: &dyn EguiComponent, - simulator: &Option<&mut Simulator>, ctx: &Context, - size: impl Into, offset: impl Into, scale: f32, clip_rect: Rect, content: impl FnOnce(&mut Ui), on_hover: impl FnOnce(&mut Ui), ) -> Option> { - let size: Vec2 = size.into(); let offset: Vec2 = offset.into(); - let component_rect = Rect::from_center_size( - Pos2::from(component.get_pos()) * scale + offset, - size * scale, - ); - let r = component_area( component.get_id_ports().0, ctx, - component_rect.center(), + Pos2::from(component.get_pos()) * scale + offset, |ui| { ui.set_clip_rect(clip_rect); + + ui.style_mut().wrap_mode = Some(TextWrapMode::Extend); + + for (_text_style, font) in ui.style_mut().text_styles.iter_mut() { + font.size *= scale; + } + ui.spacing_mut().button_padding *= scale; + ui.spacing_mut().item_spacing *= scale; + ui.spacing_mut().combo_height *= scale; + ui.spacing_mut().combo_width *= scale; + ui.spacing_mut().icon_width *= scale; + ui.spacing_mut().icon_width_inner *= scale; + ui.spacing_mut().icon_spacing *= scale; + ui.spacing_mut().interact_size *= scale; + let mut group = egui::containers::Frame::group(ui.style()); group.inner_margin *= scale; group.rounding *= scale; // group.fill = Color32::LIGHT_RED; // Use this ween component background is implemented, probably when we implement dark mode group .show(ui, |ui| { - ui.style_mut().wrap_mode = Some(TextWrapMode::Extend); - if size != (0f32, 0f32).into() { - ui.set_height(component_rect.height()); - ui.set_width(component_rect.width()); - ui.set_clip_rect(component_rect.intersect(clip_rect)); - } content(ui); }) .response @@ -248,23 +249,14 @@ pub fn basic_component_gui( component: &dyn EguiComponent, simulator: &Option<&mut Simulator>, ctx: &Context, - size: impl Into, offset: impl Into, scale: f32, clip_rect: Rect, content: impl FnOnce(&mut Ui), ) -> Option> { - basic_component_gui_with_on_hover( - component, - simulator, - ctx, - size, - offset, - scale, - clip_rect, - content, - |ui| basic_on_hover(ui, component, simulator), - ) + basic_component_gui_with_on_hover(component, ctx, offset, scale, clip_rect, content, |ui| { + basic_on_hover(ui, component, simulator) + }) } /// example From 0f4c1d3d77c496e64d6b30a860f93afbc319b1ef Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 28 Aug 2024 15:50:46 +0200 Subject: [PATCH 070/126] added breakpoints to DM --- src/components/mips_dm.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/components/mips_dm.rs b/src/components/mips_dm.rs index db2f2154..0f95b939 100644 --- a/src/components/mips_dm.rs +++ b/src/components/mips_dm.rs @@ -206,7 +206,7 @@ impl Component for DataMem { const SIGNED: bool = true; const UNSIGNED: bool = false; - match mem_op { + let ret: Result<(), Condition> = match mem_op { data_op::NO_OP => { simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); Ok(()) @@ -315,6 +315,23 @@ impl Component for DataMem { } } _ => Err(Condition::Error(format!("unknown mem op {}", mem_op))), + }; + // test breakpoint + match ret { + Ok(_) => match mem_op { + data_op::NO_OP => Ok(()), + _ => { + if self.mem_view.borrow().is_break_point(&(address & !0b11)) { + Err(Condition::Halt(format!( + "Read or write at breakpoint address {:#0x}", + address + ))) + } else { + Ok(()) + } + } + }, + Err(_) => ret, } } } From d87dc3d733692590171a95c495d6279a22711bf6 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Fri, 30 Aug 2024 10:28:07 +0200 Subject: [PATCH 071/126] tmp working --- examples/mips_pipe_example_1.rs | 129 ++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 49 deletions(-) diff --git a/examples/mips_pipe_example_1.rs b/examples/mips_pipe_example_1.rs index 0f31f72d..60f305ab 100644 --- a/examples/mips_pipe_example_1.rs +++ b/examples/mips_pipe_example_1.rs @@ -1,6 +1,6 @@ // use crate::src::components::cntr_unit_signals; -use std::path::PathBuf; use std::rc::Rc; +use std::{cell::RefCell, path::PathBuf}; use syncrim::common::EguiComponent; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; @@ -13,30 +13,62 @@ use syncrim::{ fn main() { fern_setup(); + + let mem = Rc::new(RefCell::new(MipsMem::default())); + let rc_reg_file = RegFile::rc_new( + "reg_file", + (360.0, 170.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + Input::new("reg_addr_reg", REGISTER_OUT_ID), //write address + Input::new("result_reg_EX", REGISTER_OUT_ID), //write data + Input::new("control_unit_4", cntr_field::REG_WRITE_ENABLE_OUT), + ); + + // RegFile::rc_new( + // "reg_file", + // (3100.0, 2000.0), + // Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), + // Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + // Input::new("reg_addr_reg", REGISTER_OUT_ID), //write address + // Input::new("result_reg_EX", REGISTER_OUT_ID), //write data + // Input::new("control_unit_4", cntr_field::REG_WRITE_ENABLE_OUT), + // ), + let cs = ComponentStore { store: vec![ // register that holds instr addr - Register::rc_new("pc", (2000.0, 5000.0), Input::new("mux_jump_merge", "out")), + Register::rc_new("pc", (170.0, 410.0), Input::new("mux_jump_merge", "out")), // step addr from reg by 4 - Constant::rc_new("+4", (2000.0, 5100.0), 4), + Constant::rc_new("+4", (170.0, 380.0), 4), Add::rc_new( "pc+4", - (2200.0, 5000.0), + (220.0, 380.0), Input::new("pc", "out"), Input::new("+4", "out"), ), // // + Rc::new( + InstrMem::new( + "instr_mem".into(), + (280.0, 600.0), + Input::new("pc", "out"), + Rc::clone(&mem), + ) + .set_mem_view_reg(rc_reg_file.clone()), + ), + // // // MUX to choose what intruction addr to choose from, branch jump, reg, pc+4 Mux::rc_new( "mux_jump_merge", - (1800.0, 5000.0), + (140.0, 390.0), Input::new("branch", BRANCH_OUT_ID), vec![ - Input::new("pc_add_branch", FULL_ADD_OUT_ID), //TODO: describe origin - Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), // goes to addr, RD2 - Input::new("merge_reg", REGISTER_OUT_ID), // + Input::new("pc_add_branch", ADD_OUT_ID), // describe origin + Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), // goes to addr, RD2 + Input::new("merge_reg", REGISTER_OUT_ID), // Input::new("pc+4", CLK_OUT_ID), ], ), @@ -44,23 +76,18 @@ fn main() { // merges to find out jump location JumpMerge::rc_new( "jump_merge", - (1700.0, 5300.0), + (125.0, 500.0), Input::new("pc", REGISTER_OUT_ID), //input from reg before pc+4 - Input::new("dummy", "out"), //input from instruction mem + Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), //input from instruction mem ), // // - Register::rc_new( - //TODO: continue the chain of regs - "pc+4_reg", - (2300.0, 5000.0), - Input::new("pc+4", ADD_OUT_ID), - ), + Register::rc_new("pc+4_reg", (2300.0, 5000.0), Input::new("pc+4", ADD_OUT_ID)), // Register::rc_new( "InMem_reg", (2300.0, 5200.0), - Input::new("dummy", "out"), //TODO: im + Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), ), // Register::rc_new( @@ -72,36 +99,35 @@ fn main() { // splits intructions from ir to fields InstrSplit::rc_new( "instruction_split", - (2400.0, 4000.0), + (280.0, 140.0), Input::new("InMem_reg", REGISTER_OUT_ID), - ), //TODO: take im input + ), // - //TODO: add 3 more contrill units and rewire // First CU, handles, selcet for signzero_extend and mux_write_addr ControlUnit::rc_new( "control_unit_1", - (3250.0, 1500.0), + (280.0, 100.0), Input::new("InMem_reg", REGISTER_OUT_ID), ), // // Second CU, handles, mux_source_a, mux_source_b and the alu ControlUnit::rc_new( "control_unit_2", - (3550.0, 1500.0), + (380.0, 100.0), Input::new("control_EX_reg", REGISTER_OUT_ID), ), // // Third CU, handles, write_back_mux, and DMs memread and memwrite ControlUnit::rc_new( "control_unit_3", - (4300.0, 1500.0), + (480.0, 100.0), Input::new("control_MEM_reg", REGISTER_OUT_ID), ), // // Fourth CU, handles, WE for reg_file in the WB stage ControlUnit::rc_new( "control_unit_4", - (4500.0, 1500.0), + (580.0, 100.0), Input::new("control_WB_reg", REGISTER_OUT_ID), ), // @@ -109,21 +135,12 @@ fn main() { // extends immediate field SignZeroExtend::rc_new( "signzero_extend", - (2600.0, 5100.0), + (310.0, 410.0), Input::new("instruction_split", INSTRUCTION_SPLITTER_IMMEDIATE_ID), Input::new("control_unit_1", cntr_field::EXTEND_SELECT_OUT), // cu tells it to either sing- or zero- extend ), // // - RegFile::rc_new( - "reg_file", - (3100.0, 2000.0), - Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), - Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), - Input::new("reg_addr_reg", REGISTER_OUT_ID), //write address - Input::new("result_reg_EX", REGISTER_OUT_ID), //write data - Input::new("control_unit_4", cntr_field::REG_WRITE_ENABLE_OUT), - ), // // Equal::rc_new( @@ -200,7 +217,7 @@ fn main() { // BranchLogic::rc_new( "branch", - (3400.0, 2000.0), + (525.0, 300.0), Input::new("instruction_split", INSTRUCTION_SPLITTER_OP_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_FUNCT_ID), @@ -256,27 +273,27 @@ fn main() { // ZeroExtend::rc_new( "zero_extend_for_chamt", - (3700.0, 1600.0), + (550.0, 170.0), Input::new("zero_extend_reg", REGISTER_OUT_ID), ), // // - Constant::rc_new("0_a_inp", (3800.0, 1700.0), 0), + Constant::rc_new("0_a_inp", (600.0, 230.0), 0), Mux::rc_new( "mux_source_a", - (3800.0, 1800.0), + (650.0, 220.0), Input::new("control_unit_2", cntr_field::ALU_SRC_A_OUT), vec![ Input::new("zero_extend_for_chamt", SIGNZEROEXTEND_OUT_ID), - Input::new("0_a_inp", "out"), Input::new("operand_a_reg", REGISTER_OUT_ID), + Input::new("0_a_inp", "out"), ], ), // // Mux::rc_new( "mux_source_b", - (3800.0, 2200.0), + (650.0, 300.0), Input::new("control_unit_2", cntr_field::ALU_SRC_B_OUT), vec![ Input::new("operand_b_reg", REGISTER_OUT_ID), @@ -290,13 +307,27 @@ fn main() { // FullAdd::rc_new( "alu", - (4100.0, 2000.0), + (720.0, 220.0), Input::new("mux_source_a", MUX_OUT_ID), Input::new("mux_source_b", MUX_OUT_ID), Input::new("control_unit_2", cntr_field::ALU_OP_OUT), ), // // + Rc::new( + DataMem::new( + "data_mem".into(), + (600.0, 580.0), + Input::new("alu_reg", REGISTER_OUT_ID), // calculated from rs and imm + Input::new("data_MEM_reg", REGISTER_OUT_ID), + Input::new("control_unit_3", cntr_field::MEM_MODE_OUT), + Input::new("control_unit_3", cntr_field::MEM_WRITE_ENABLE_OUT), + Rc::clone(&mem), + ) + .set_mem_view_reg(rc_reg_file.clone()), + ), + // + // Register::rc_new( "control_MEM_reg", (4200.0, 1400.0), @@ -324,11 +355,11 @@ fn main() { // Mux::rc_new( "write_back_mux", - (4300.0, 2200.0), + (800.0, 270.0), Input::new("control_unit_3", cntr_field::REG_WRITE_SRC_OUT), vec![ Input::new("alu", FULL_ADD_OUT_ID), - Input::new("dummy", "out"), //TODO: data meme output + Input::new("data_mem", DATA_MEM_READ_DATA_OUT_ID), ], ), // @@ -354,7 +385,7 @@ fn main() { // ShiftConst::rc_new( "branch_shift", - (2900.0, 5250.0), + (380.0, 460.0), Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), 2, ), @@ -362,21 +393,21 @@ fn main() { // Add::rc_new( "pc_add_branch", - (3000.0, 5200.0), + (420.0, 440.0), Input::new("pc+4", ADD_OUT_ID), Input::new("branch_shift", SHIFT_OUT_ID), ), // // - Constant::rc_new("0x_1F", (3750.0, 5500.0), 0), + Constant::rc_new("0x_1F", (500.0, 510.0), 0x_1F), Mux::rc_new( "mux_write_addr", - (3200.0, 5500.0), + (560.0, 500.0), Input::new("control_unit_1", cntr_field::REG_DEST_OUT), vec![ Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), - Input::new("0x_1F", "out"), Input::new("instruction_split", INSTRUCTION_SPLITTER_RD_ID), + Input::new("0x_1F", "out"), ], ), // @@ -384,7 +415,7 @@ fn main() { // // - Constant::rc_new("dummy", (6000.0, 3000.0), 0), + rc_reg_file, ], }; From e4886216b542b9beb07e9b098c2bc69f31e112bf Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Fri, 30 Aug 2024 12:54:13 +0200 Subject: [PATCH 072/126] idk --- examples/mips_pipe_example_1.rs | 32 +++++++++++-------- src/components/add.rs | 4 +-- src/components/and.rs | 5 ++- src/components/clk.rs | 2 +- src/components/equals.rs | 2 +- src/components/full_adder.rs | 4 +-- src/components/mips_branch_logic.rs | 2 +- src/components/mips_jump_merge.rs | 2 +- src/components/mux.rs | 2 +- src/components/register.rs | 2 +- src/components/shift_left_const.rs | 2 +- src/components/sz_extend.rs | 2 +- src/components/zero_extend.rs | 2 +- src/fern.rs | 4 +-- src/gui_egui/components/full_adder.rs | 5 +-- src/gui_egui/components/mips_controll_unit.rs | 4 +-- src/gui_egui/components/mux.rs | 7 ++-- src/gui_egui/components/register.rs | 26 ++------------- 18 files changed, 45 insertions(+), 64 deletions(-) diff --git a/examples/mips_pipe_example_1.rs b/examples/mips_pipe_example_1.rs index 60f305ab..0384422e 100644 --- a/examples/mips_pipe_example_1.rs +++ b/examples/mips_pipe_example_1.rs @@ -38,14 +38,18 @@ fn main() { let cs = ComponentStore { store: vec![ // register that holds instr addr - Register::rc_new("pc", (170.0, 410.0), Input::new("mux_jump_merge", "out")), + Register::rc_new( + "pc", + (170.0, 410.0), + Input::new("mux_jump_merge", MUX_OUT_ID), + ), // step addr from reg by 4 Constant::rc_new("+4", (170.0, 380.0), 4), Add::rc_new( "pc+4", (220.0, 380.0), - Input::new("pc", "out"), - Input::new("+4", "out"), + Input::new("pc", REGISTER_OUT_ID), + Input::new("+4", CONSTANT_OUT_ID), ), // // @@ -53,7 +57,7 @@ fn main() { InstrMem::new( "instr_mem".into(), (280.0, 600.0), - Input::new("pc", "out"), + Input::new("pc", REGISTER_OUT_ID), Rc::clone(&mem), ) .set_mem_view_reg(rc_reg_file.clone()), @@ -69,7 +73,7 @@ fn main() { Input::new("pc_add_branch", ADD_OUT_ID), // describe origin Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), // goes to addr, RD2 Input::new("merge_reg", REGISTER_OUT_ID), // - Input::new("pc+4", CLK_OUT_ID), + Input::new("pc+4", ADD_OUT_ID), //clk ], ), // @@ -106,28 +110,28 @@ fn main() { // First CU, handles, selcet for signzero_extend and mux_write_addr ControlUnit::rc_new( "control_unit_1", - (280.0, 100.0), + (480.0, 100.0), Input::new("InMem_reg", REGISTER_OUT_ID), ), // // Second CU, handles, mux_source_a, mux_source_b and the alu ControlUnit::rc_new( "control_unit_2", - (380.0, 100.0), + (580.0, 100.0), Input::new("control_EX_reg", REGISTER_OUT_ID), ), // // Third CU, handles, write_back_mux, and DMs memread and memwrite ControlUnit::rc_new( "control_unit_3", - (480.0, 100.0), + (680.0, 100.0), Input::new("control_MEM_reg", REGISTER_OUT_ID), ), // // Fourth CU, handles, WE for reg_file in the WB stage ControlUnit::rc_new( "control_unit_4", - (580.0, 100.0), + (780.0, 100.0), Input::new("control_WB_reg", REGISTER_OUT_ID), ), // @@ -243,14 +247,14 @@ fn main() { //TODO: fix after adding 4 muxes "operand_a_reg", (3450.0, 1800.0), - Input::new("equals_operand_A_2", MUX_OUT_ID), + Input::new("operand_A_mux_2", MUX_OUT_ID), ), // Register::rc_new( //TODO: fix after muxes "operand_b_reg", (3450.0, 2200.0), - Input::new("equals_operand_B_2", MERGE_OUT_ID), + Input::new("operand_B_mux_2", MUX_OUT_ID), ), // Register::rc_new( @@ -286,7 +290,7 @@ fn main() { vec![ Input::new("zero_extend_for_chamt", SIGNZEROEXTEND_OUT_ID), Input::new("operand_a_reg", REGISTER_OUT_ID), - Input::new("0_a_inp", "out"), + Input::new("0_a_inp", CONSTANT_OUT_ID), ], ), // @@ -407,7 +411,7 @@ fn main() { vec![ Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_RD_ID), - Input::new("0x_1F", "out"), + Input::new("0x_1F", CONSTANT_OUT_ID), ], ), // @@ -419,7 +423,7 @@ fn main() { ], }; - let cs = autowire(cs); + //let cs = autowire(cs); let path = PathBuf::from("add.json"); cs.save_file(&path); diff --git a/src/components/add.rs b/src/components/add.rs index 005b7f65..ec2adef4 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -11,8 +11,8 @@ use std::rc::Rc; pub const ADD_A_IN_ID: &str = "a_in"; pub const ADD_B_IN_ID: &str = "b_in"; -pub const ADD_OUT_ID: &str = "out"; -pub const ADD_OVERFLOW_ID: &str = "overflow"; +pub const ADD_OUT_ID: &str = "add_out"; +pub const ADD_OVERFLOW_ID: &str = "overflow_out"; #[derive(Serialize, Deserialize, Clone)] pub struct Add { diff --git a/src/components/and.rs b/src/components/and.rs index dae2cd1f..4f0d0ae2 100644 --- a/src/components/and.rs +++ b/src/components/and.rs @@ -1,8 +1,7 @@ #[cfg(feature = "gui-egui")] use crate::common::EguiComponent; use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, - SignalValue, Simulator, + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; use log::*; use serde::{Deserialize, Serialize}; @@ -11,7 +10,7 @@ use std::rc::Rc; pub const AND_A_IN_ID: &str = "a_in"; pub const AND_B_IN_ID: &str = "b_in"; -pub const AND_OUT_ID: &str = "out"; +pub const AND_OUT_ID: &str = "and_out"; #[derive(Serialize, Deserialize, Clone)] pub struct And { diff --git a/src/components/clk.rs b/src/components/clk.rs index a0ae9f71..1c27e447 100644 --- a/src/components/clk.rs +++ b/src/components/clk.rs @@ -11,7 +11,7 @@ use std::rc::Rc; pub const CLK_IN_ID: &str = "clk_in"; -pub const CLK_OUT_ID: &str = "out"; +pub const CLK_OUT_ID: &str = "clk_out"; #[derive(Serialize, Deserialize, Clone)] pub struct MIPSCLK { diff --git a/src/components/equals.rs b/src/components/equals.rs index 02b07228..85120e68 100644 --- a/src/components/equals.rs +++ b/src/components/equals.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub const EQUAL_A_IN_ID: &str = "a_in"; pub const EQUAL_B_IN_ID: &str = "b_in"; -pub const EQUAL_OUT_ID: &str = "out"; +pub const EQUAL_OUT_ID: &str = "equals_out"; #[derive(Serialize, Deserialize, Clone)] pub struct Equal { diff --git a/src/components/full_adder.rs b/src/components/full_adder.rs index 17377a81..3ec71aab 100644 --- a/src/components/full_adder.rs +++ b/src/components/full_adder.rs @@ -153,10 +153,10 @@ impl Component for FullAdd { output = (a < b) as u32; } alu_op::SLL => { - output = a << b; + (output, _) = a.overflowing_shl(b); } alu_op::SRL => { - output = a >> b; + (output, _) = a.overflowing_shr(b); } alu_op::SRA => { output = ((a as i32) >> b) as u32; diff --git a/src/components/mips_branch_logic.rs b/src/components/mips_branch_logic.rs index f96bf75e..d844bf0a 100644 --- a/src/components/mips_branch_logic.rs +++ b/src/components/mips_branch_logic.rs @@ -16,7 +16,7 @@ pub const BRANCH_FUNCT_ID: &str = "branch_funct_in"; pub const BRANCH_RS_VALUE_ID: &str = "branch_rs_vlaue_id"; pub const BRANCH_RT_VALUE_ID: &str = "branch_rt_value_id"; -pub const BRANCH_OUT_ID: &str = "out"; +pub const BRANCH_OUT_ID: &str = "branch_logic_out"; pub const BRANCH_OFFSET: u32 = 0; pub const BRANCH_REGISTER: u32 = 1; diff --git a/src/components/mips_jump_merge.rs b/src/components/mips_jump_merge.rs index db18afaa..f02f5a75 100644 --- a/src/components/mips_jump_merge.rs +++ b/src/components/mips_jump_merge.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub const MERGE_INSTR_ADDR_ID: &str = "merge_instr_addr_in"; pub const MERGE_JUMP_ADDR_ID: &str = "merge_jump_addr_in"; -pub const MERGE_OUT_ID: &str = "out"; +pub const MERGE_OUT_ID: &str = "jump_merge_out"; #[derive(Serialize, Deserialize, Clone)] pub struct JumpMerge { diff --git a/src/components/mux.rs b/src/components/mux.rs index 1883ebbc..8e7f26a5 100644 --- a/src/components/mux.rs +++ b/src/components/mux.rs @@ -11,7 +11,7 @@ use std::rc::Rc; pub const MUX_SELECT_ID: &str = "select"; pub const MUX_TEMPLATE_ID: &str = "in"; -pub const MUX_OUT_ID: &str = "out"; +pub const MUX_OUT_ID: &str = "mux_out"; #[derive(Serialize, Deserialize, Clone)] pub struct Mux { diff --git a/src/components/register.rs b/src/components/register.rs index cba6e29a..7178ec8d 100644 --- a/src/components/register.rs +++ b/src/components/register.rs @@ -8,7 +8,7 @@ use std::rc::Rc; pub const REGISTER_R_IN_ID: &str = "r_in"; -pub const REGISTER_OUT_ID: &str = "out"; +pub const REGISTER_OUT_ID: &str = "abc_out"; #[derive(Serialize, Deserialize, Clone)] pub struct Register { diff --git a/src/components/shift_left_const.rs b/src/components/shift_left_const.rs index af1a78b4..a09eedff 100644 --- a/src/components/shift_left_const.rs +++ b/src/components/shift_left_const.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub const SHIFT_SIGNAL_IN_ID: &str = "shift_in"; -pub const SHIFT_OUT_ID: &str = "out"; +pub const SHIFT_OUT_ID: &str = "shift_left_const_out"; #[derive(Serialize, Deserialize, Clone)] pub struct ShiftConst { diff --git a/src/components/sz_extend.rs b/src/components/sz_extend.rs index 6b4b58bc..89cbf798 100644 --- a/src/components/sz_extend.rs +++ b/src/components/sz_extend.rs @@ -14,7 +14,7 @@ use std::rc::Rc; pub const SIGNZEROEXTEND_SIGNAL_IN_ID: &str = "signzero_signal_in"; pub const SIGNZEROEXTEND_CTRL_IN_ID: &str = "signzero_ctrl_in"; -pub const SIGNZEROEXTEND_OUT_ID: &str = "out"; +pub const SIGNZEROEXTEND_OUT_ID: &str = "sign_zero_out"; #[derive(Serialize, Deserialize, Clone)] pub struct SignZeroExtend { diff --git a/src/components/zero_extend.rs b/src/components/zero_extend.rs index e196ff0b..a4f8f7be 100644 --- a/src/components/zero_extend.rs +++ b/src/components/zero_extend.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub const ZEROEXTEND_SIGNAL_IN_ID: &str = "signal_in"; -pub const ZEROEXTEND_OUT_ID: &str = "out"; +pub const ZEROEXTEND_OUT_ID: &str = "zero_extend_out"; #[derive(Serialize, Deserialize, Clone)] pub struct ZeroExtend { diff --git a/src/fern.rs b/src/fern.rs index 8b80fb23..4e837a02 100644 --- a/src/fern.rs +++ b/src/fern.rs @@ -15,8 +15,8 @@ pub fn fern_setup() { )) }) // Add blanket level filter - - // .level(log::LevelFilter::Debug); - .level(log::LevelFilter::Trace); + .level(log::LevelFilter::Debug); + // .level(log::LevelFilter::Trace); // .level(log::LevelFilter::Off); // - and per-module overrides diff --git a/src/gui_egui/components/full_adder.rs b/src/gui_egui/components/full_adder.rs index 1288153b..b612dd06 100644 --- a/src/gui_egui/components/full_adder.rs +++ b/src/gui_egui/components/full_adder.rs @@ -6,7 +6,7 @@ use crate::gui_egui::component_ui::{ }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::offset_helper; +use crate::gui_egui::helper::{basic_on_hover, offset_helper}; use egui::{ Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Stroke, TextWrapMode, Ui, Vec2, @@ -56,7 +56,7 @@ impl EguiComponent for FullAdd { min: oh((-20f32, -40f32), s, o), max: oh((20f32, 40f32), s, o), }; - let op: String = if let Some(s) = simulator { + let op: String = if let Some(s) = &simulator { match TryInto::::try_into(s.get_input_value(&self.op_in)).unwrap() { alu_op::ADD => "ADD", alu_op::ADDU => "ADDU", @@ -91,6 +91,7 @@ impl EguiComponent for FullAdd { ui.set_clip_rect(clip_rect); ui.style_mut().wrap_mode = Some(TextWrapMode::Extend); ui.label(RichText::new(format!("ALU\n{}", op)).size(scale * 12f32)) + .on_hover_ui(|ui| basic_on_hover(ui, self, &simulator)) }); let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { ui.label(format!("Id: {}", self.id.clone())); diff --git a/src/gui_egui/components/mips_controll_unit.rs b/src/gui_egui/components/mips_controll_unit.rs index 183ff43b..048f5236 100644 --- a/src/gui_egui/components/mips_controll_unit.rs +++ b/src/gui_egui/components/mips_controll_unit.rs @@ -18,8 +18,8 @@ impl EguiComponent for ControlUnit { _editor_mode: EditorMode, ) -> Option> { // size of the component - let width = 400f32 * scale; - let height: f32 = 12f32 * scale; + let width = 0f32 * scale; + let height: f32 = 0f32 * scale; basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { ui.set_height(height); ui.set_width(width); diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index d2a747f6..238905a3 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -6,7 +6,7 @@ use crate::gui_egui::component_ui::{ }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::offset_helper; +use crate::gui_egui::helper::{basic_on_hover, offset_helper}; use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] @@ -33,7 +33,7 @@ impl EguiComponent for Mux { let pa = self.m_in.len() as f32; // selector, here we can treat Signal better (see Vizia counterpart) - let select: SignalUnsigned = match simulator { + let select: SignalUnsigned = match &simulator { Some(s) => s.get_input_value(&self.select).try_into().unwrap_or(0), None => 0, }; @@ -75,8 +75,7 @@ impl EguiComponent for Mux { max: oh((10f32, pa * 10f32 + 10f32), s, o), }; let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - ui.label(format!("Id: {}", self.id.clone())); - ui.label("Mux"); + basic_on_hover(ui, self, &simulator) }); match editor_mode { EditorMode::Simulator => (), diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index 2fd862ba..d7f07959 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -6,7 +6,7 @@ use crate::gui_egui::component_ui::{ }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::offset_helper; +use crate::gui_egui::helper::{basic_on_hover, offset_helper}; use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] @@ -52,29 +52,7 @@ impl EguiComponent for Register { max: oh((10f32, 20f32), s, o), }; let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - ui.label(format!("Id: {}", self.id.clone())); - if let Some(s) = &simulator { - ui.label({ - let r: Result = - s.get_input_value(&self.r_in).try_into(); - match r { - Ok(data) => format!("In {:#x}", data), - _ => format!("In {:?}", r), - } - }); - ui.label({ - let r: Result = s - .get_input_value(&Input { - id: self.id.clone(), - field: "out".to_string(), - }) - .try_into(); - match r { - Ok(data) => format!("Out {:#x}", data), - _ => format!("Out {:?}", r), - } - }); - } + basic_on_hover(ui, self, &simulator) }); match editor_mode { From d5590263578f7d9a34444668efe7848347d093a5 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Fri, 30 Aug 2024 14:38:33 +0200 Subject: [PATCH 073/126] Revert "idk" This reverts commit e4886216b542b9beb07e9b098c2bc69f31e112bf. --- examples/mips_pipe_example_1.rs | 32 ++++++++----------- src/components/add.rs | 4 +-- src/components/and.rs | 5 +-- src/components/clk.rs | 2 +- src/components/equals.rs | 2 +- src/components/full_adder.rs | 4 +-- src/components/mips_branch_logic.rs | 2 +- src/components/mips_jump_merge.rs | 2 +- src/components/mux.rs | 2 +- src/components/register.rs | 2 +- src/components/shift_left_const.rs | 2 +- src/components/sz_extend.rs | 2 +- src/components/zero_extend.rs | 2 +- src/fern.rs | 4 +-- src/gui_egui/components/full_adder.rs | 5 ++- src/gui_egui/components/mips_controll_unit.rs | 4 +-- src/gui_egui/components/mux.rs | 7 ++-- src/gui_egui/components/register.rs | 26 +++++++++++++-- 18 files changed, 64 insertions(+), 45 deletions(-) diff --git a/examples/mips_pipe_example_1.rs b/examples/mips_pipe_example_1.rs index 0384422e..60f305ab 100644 --- a/examples/mips_pipe_example_1.rs +++ b/examples/mips_pipe_example_1.rs @@ -38,18 +38,14 @@ fn main() { let cs = ComponentStore { store: vec![ // register that holds instr addr - Register::rc_new( - "pc", - (170.0, 410.0), - Input::new("mux_jump_merge", MUX_OUT_ID), - ), + Register::rc_new("pc", (170.0, 410.0), Input::new("mux_jump_merge", "out")), // step addr from reg by 4 Constant::rc_new("+4", (170.0, 380.0), 4), Add::rc_new( "pc+4", (220.0, 380.0), - Input::new("pc", REGISTER_OUT_ID), - Input::new("+4", CONSTANT_OUT_ID), + Input::new("pc", "out"), + Input::new("+4", "out"), ), // // @@ -57,7 +53,7 @@ fn main() { InstrMem::new( "instr_mem".into(), (280.0, 600.0), - Input::new("pc", REGISTER_OUT_ID), + Input::new("pc", "out"), Rc::clone(&mem), ) .set_mem_view_reg(rc_reg_file.clone()), @@ -73,7 +69,7 @@ fn main() { Input::new("pc_add_branch", ADD_OUT_ID), // describe origin Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), // goes to addr, RD2 Input::new("merge_reg", REGISTER_OUT_ID), // - Input::new("pc+4", ADD_OUT_ID), //clk + Input::new("pc+4", CLK_OUT_ID), ], ), // @@ -110,28 +106,28 @@ fn main() { // First CU, handles, selcet for signzero_extend and mux_write_addr ControlUnit::rc_new( "control_unit_1", - (480.0, 100.0), + (280.0, 100.0), Input::new("InMem_reg", REGISTER_OUT_ID), ), // // Second CU, handles, mux_source_a, mux_source_b and the alu ControlUnit::rc_new( "control_unit_2", - (580.0, 100.0), + (380.0, 100.0), Input::new("control_EX_reg", REGISTER_OUT_ID), ), // // Third CU, handles, write_back_mux, and DMs memread and memwrite ControlUnit::rc_new( "control_unit_3", - (680.0, 100.0), + (480.0, 100.0), Input::new("control_MEM_reg", REGISTER_OUT_ID), ), // // Fourth CU, handles, WE for reg_file in the WB stage ControlUnit::rc_new( "control_unit_4", - (780.0, 100.0), + (580.0, 100.0), Input::new("control_WB_reg", REGISTER_OUT_ID), ), // @@ -247,14 +243,14 @@ fn main() { //TODO: fix after adding 4 muxes "operand_a_reg", (3450.0, 1800.0), - Input::new("operand_A_mux_2", MUX_OUT_ID), + Input::new("equals_operand_A_2", MUX_OUT_ID), ), // Register::rc_new( //TODO: fix after muxes "operand_b_reg", (3450.0, 2200.0), - Input::new("operand_B_mux_2", MUX_OUT_ID), + Input::new("equals_operand_B_2", MERGE_OUT_ID), ), // Register::rc_new( @@ -290,7 +286,7 @@ fn main() { vec![ Input::new("zero_extend_for_chamt", SIGNZEROEXTEND_OUT_ID), Input::new("operand_a_reg", REGISTER_OUT_ID), - Input::new("0_a_inp", CONSTANT_OUT_ID), + Input::new("0_a_inp", "out"), ], ), // @@ -411,7 +407,7 @@ fn main() { vec![ Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_RD_ID), - Input::new("0x_1F", CONSTANT_OUT_ID), + Input::new("0x_1F", "out"), ], ), // @@ -423,7 +419,7 @@ fn main() { ], }; - //let cs = autowire(cs); + let cs = autowire(cs); let path = PathBuf::from("add.json"); cs.save_file(&path); diff --git a/src/components/add.rs b/src/components/add.rs index ec2adef4..005b7f65 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -11,8 +11,8 @@ use std::rc::Rc; pub const ADD_A_IN_ID: &str = "a_in"; pub const ADD_B_IN_ID: &str = "b_in"; -pub const ADD_OUT_ID: &str = "add_out"; -pub const ADD_OVERFLOW_ID: &str = "overflow_out"; +pub const ADD_OUT_ID: &str = "out"; +pub const ADD_OVERFLOW_ID: &str = "overflow"; #[derive(Serialize, Deserialize, Clone)] pub struct Add { diff --git a/src/components/and.rs b/src/components/and.rs index 4f0d0ae2..dae2cd1f 100644 --- a/src/components/and.rs +++ b/src/components/and.rs @@ -1,7 +1,8 @@ #[cfg(feature = "gui-egui")] use crate::common::EguiComponent; use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, + SignalValue, Simulator, }; use log::*; use serde::{Deserialize, Serialize}; @@ -10,7 +11,7 @@ use std::rc::Rc; pub const AND_A_IN_ID: &str = "a_in"; pub const AND_B_IN_ID: &str = "b_in"; -pub const AND_OUT_ID: &str = "and_out"; +pub const AND_OUT_ID: &str = "out"; #[derive(Serialize, Deserialize, Clone)] pub struct And { diff --git a/src/components/clk.rs b/src/components/clk.rs index 1c27e447..a0ae9f71 100644 --- a/src/components/clk.rs +++ b/src/components/clk.rs @@ -11,7 +11,7 @@ use std::rc::Rc; pub const CLK_IN_ID: &str = "clk_in"; -pub const CLK_OUT_ID: &str = "clk_out"; +pub const CLK_OUT_ID: &str = "out"; #[derive(Serialize, Deserialize, Clone)] pub struct MIPSCLK { diff --git a/src/components/equals.rs b/src/components/equals.rs index 85120e68..02b07228 100644 --- a/src/components/equals.rs +++ b/src/components/equals.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub const EQUAL_A_IN_ID: &str = "a_in"; pub const EQUAL_B_IN_ID: &str = "b_in"; -pub const EQUAL_OUT_ID: &str = "equals_out"; +pub const EQUAL_OUT_ID: &str = "out"; #[derive(Serialize, Deserialize, Clone)] pub struct Equal { diff --git a/src/components/full_adder.rs b/src/components/full_adder.rs index 3ec71aab..17377a81 100644 --- a/src/components/full_adder.rs +++ b/src/components/full_adder.rs @@ -153,10 +153,10 @@ impl Component for FullAdd { output = (a < b) as u32; } alu_op::SLL => { - (output, _) = a.overflowing_shl(b); + output = a << b; } alu_op::SRL => { - (output, _) = a.overflowing_shr(b); + output = a >> b; } alu_op::SRA => { output = ((a as i32) >> b) as u32; diff --git a/src/components/mips_branch_logic.rs b/src/components/mips_branch_logic.rs index d844bf0a..f96bf75e 100644 --- a/src/components/mips_branch_logic.rs +++ b/src/components/mips_branch_logic.rs @@ -16,7 +16,7 @@ pub const BRANCH_FUNCT_ID: &str = "branch_funct_in"; pub const BRANCH_RS_VALUE_ID: &str = "branch_rs_vlaue_id"; pub const BRANCH_RT_VALUE_ID: &str = "branch_rt_value_id"; -pub const BRANCH_OUT_ID: &str = "branch_logic_out"; +pub const BRANCH_OUT_ID: &str = "out"; pub const BRANCH_OFFSET: u32 = 0; pub const BRANCH_REGISTER: u32 = 1; diff --git a/src/components/mips_jump_merge.rs b/src/components/mips_jump_merge.rs index f02f5a75..db18afaa 100644 --- a/src/components/mips_jump_merge.rs +++ b/src/components/mips_jump_merge.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub const MERGE_INSTR_ADDR_ID: &str = "merge_instr_addr_in"; pub const MERGE_JUMP_ADDR_ID: &str = "merge_jump_addr_in"; -pub const MERGE_OUT_ID: &str = "jump_merge_out"; +pub const MERGE_OUT_ID: &str = "out"; #[derive(Serialize, Deserialize, Clone)] pub struct JumpMerge { diff --git a/src/components/mux.rs b/src/components/mux.rs index 8e7f26a5..1883ebbc 100644 --- a/src/components/mux.rs +++ b/src/components/mux.rs @@ -11,7 +11,7 @@ use std::rc::Rc; pub const MUX_SELECT_ID: &str = "select"; pub const MUX_TEMPLATE_ID: &str = "in"; -pub const MUX_OUT_ID: &str = "mux_out"; +pub const MUX_OUT_ID: &str = "out"; #[derive(Serialize, Deserialize, Clone)] pub struct Mux { diff --git a/src/components/register.rs b/src/components/register.rs index 7178ec8d..cba6e29a 100644 --- a/src/components/register.rs +++ b/src/components/register.rs @@ -8,7 +8,7 @@ use std::rc::Rc; pub const REGISTER_R_IN_ID: &str = "r_in"; -pub const REGISTER_OUT_ID: &str = "abc_out"; +pub const REGISTER_OUT_ID: &str = "out"; #[derive(Serialize, Deserialize, Clone)] pub struct Register { diff --git a/src/components/shift_left_const.rs b/src/components/shift_left_const.rs index a09eedff..af1a78b4 100644 --- a/src/components/shift_left_const.rs +++ b/src/components/shift_left_const.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub const SHIFT_SIGNAL_IN_ID: &str = "shift_in"; -pub const SHIFT_OUT_ID: &str = "shift_left_const_out"; +pub const SHIFT_OUT_ID: &str = "out"; #[derive(Serialize, Deserialize, Clone)] pub struct ShiftConst { diff --git a/src/components/sz_extend.rs b/src/components/sz_extend.rs index 89cbf798..6b4b58bc 100644 --- a/src/components/sz_extend.rs +++ b/src/components/sz_extend.rs @@ -14,7 +14,7 @@ use std::rc::Rc; pub const SIGNZEROEXTEND_SIGNAL_IN_ID: &str = "signzero_signal_in"; pub const SIGNZEROEXTEND_CTRL_IN_ID: &str = "signzero_ctrl_in"; -pub const SIGNZEROEXTEND_OUT_ID: &str = "sign_zero_out"; +pub const SIGNZEROEXTEND_OUT_ID: &str = "out"; #[derive(Serialize, Deserialize, Clone)] pub struct SignZeroExtend { diff --git a/src/components/zero_extend.rs b/src/components/zero_extend.rs index a4f8f7be..e196ff0b 100644 --- a/src/components/zero_extend.rs +++ b/src/components/zero_extend.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub const ZEROEXTEND_SIGNAL_IN_ID: &str = "signal_in"; -pub const ZEROEXTEND_OUT_ID: &str = "zero_extend_out"; +pub const ZEROEXTEND_OUT_ID: &str = "out"; #[derive(Serialize, Deserialize, Clone)] pub struct ZeroExtend { diff --git a/src/fern.rs b/src/fern.rs index 4e837a02..8b80fb23 100644 --- a/src/fern.rs +++ b/src/fern.rs @@ -15,8 +15,8 @@ pub fn fern_setup() { )) }) // Add blanket level filter - - .level(log::LevelFilter::Debug); - // .level(log::LevelFilter::Trace); + // .level(log::LevelFilter::Debug); + .level(log::LevelFilter::Trace); // .level(log::LevelFilter::Off); // - and per-module overrides diff --git a/src/gui_egui/components/full_adder.rs b/src/gui_egui/components/full_adder.rs index b612dd06..1288153b 100644 --- a/src/gui_egui/components/full_adder.rs +++ b/src/gui_egui/components/full_adder.rs @@ -6,7 +6,7 @@ use crate::gui_egui::component_ui::{ }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::{basic_on_hover, offset_helper}; +use crate::gui_egui::helper::offset_helper; use egui::{ Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Stroke, TextWrapMode, Ui, Vec2, @@ -56,7 +56,7 @@ impl EguiComponent for FullAdd { min: oh((-20f32, -40f32), s, o), max: oh((20f32, 40f32), s, o), }; - let op: String = if let Some(s) = &simulator { + let op: String = if let Some(s) = simulator { match TryInto::::try_into(s.get_input_value(&self.op_in)).unwrap() { alu_op::ADD => "ADD", alu_op::ADDU => "ADDU", @@ -91,7 +91,6 @@ impl EguiComponent for FullAdd { ui.set_clip_rect(clip_rect); ui.style_mut().wrap_mode = Some(TextWrapMode::Extend); ui.label(RichText::new(format!("ALU\n{}", op)).size(scale * 12f32)) - .on_hover_ui(|ui| basic_on_hover(ui, self, &simulator)) }); let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { ui.label(format!("Id: {}", self.id.clone())); diff --git a/src/gui_egui/components/mips_controll_unit.rs b/src/gui_egui/components/mips_controll_unit.rs index 048f5236..183ff43b 100644 --- a/src/gui_egui/components/mips_controll_unit.rs +++ b/src/gui_egui/components/mips_controll_unit.rs @@ -18,8 +18,8 @@ impl EguiComponent for ControlUnit { _editor_mode: EditorMode, ) -> Option> { // size of the component - let width = 0f32 * scale; - let height: f32 = 0f32 * scale; + let width = 400f32 * scale; + let height: f32 = 12f32 * scale; basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { ui.set_height(height); ui.set_width(width); diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index 238905a3..d2a747f6 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -6,7 +6,7 @@ use crate::gui_egui::component_ui::{ }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::{basic_on_hover, offset_helper}; +use crate::gui_egui::helper::offset_helper; use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] @@ -33,7 +33,7 @@ impl EguiComponent for Mux { let pa = self.m_in.len() as f32; // selector, here we can treat Signal better (see Vizia counterpart) - let select: SignalUnsigned = match &simulator { + let select: SignalUnsigned = match simulator { Some(s) => s.get_input_value(&self.select).try_into().unwrap_or(0), None => 0, }; @@ -75,7 +75,8 @@ impl EguiComponent for Mux { max: oh((10f32, pa * 10f32 + 10f32), s, o), }; let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - basic_on_hover(ui, self, &simulator) + ui.label(format!("Id: {}", self.id.clone())); + ui.label("Mux"); }); match editor_mode { EditorMode::Simulator => (), diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index d7f07959..2fd862ba 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -6,7 +6,7 @@ use crate::gui_egui::component_ui::{ }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::{basic_on_hover, offset_helper}; +use crate::gui_egui::helper::offset_helper; use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] @@ -52,7 +52,29 @@ impl EguiComponent for Register { max: oh((10f32, 20f32), s, o), }; let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - basic_on_hover(ui, self, &simulator) + ui.label(format!("Id: {}", self.id.clone())); + if let Some(s) = &simulator { + ui.label({ + let r: Result = + s.get_input_value(&self.r_in).try_into(); + match r { + Ok(data) => format!("In {:#x}", data), + _ => format!("In {:?}", r), + } + }); + ui.label({ + let r: Result = s + .get_input_value(&Input { + id: self.id.clone(), + field: "out".to_string(), + }) + .try_into(); + match r { + Ok(data) => format!("Out {:#x}", data), + _ => format!("Out {:?}", r), + } + }); + } }); match editor_mode { From 8c9fd1eacdc0614b17c4c9b1889e4507c46013a4 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:10:14 +0200 Subject: [PATCH 074/126] changed out IDs for components to be unique --- Cargo.toml | 1 + examples/mips_example_1.rs | 48 +++++++++++++++------------- src/components/add.rs | 6 ++-- src/components/and.rs | 2 +- src/components/constant.rs | 2 +- src/components/equals.rs | 2 +- src/components/mips_branch_logic.rs | 2 +- src/components/mips_jump_merge.rs | 2 +- src/components/mux.rs | 4 +-- src/components/register.rs | 4 +-- src/components/sext.rs | 6 ++-- src/components/shift_left_const.rs | 2 +- src/components/sz_extend.rs | 2 +- src/components/zero_extend.rs | 2 +- src/gui_egui/mips_mem_view_window.rs | 7 +++- 15 files changed, 51 insertions(+), 41 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0a9bddc6..200313ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" members = ["mips", "riscv"] [dependencies] +MIPS_disassembly = "0.1.1" anyhow = "1.0.72" clap = { version = "4.3.15", features = ["derive"] } elf = "0.7.4" diff --git a/examples/mips_example_1.rs b/examples/mips_example_1.rs index 7a768903..78a8716b 100644 --- a/examples/mips_example_1.rs +++ b/examples/mips_example_1.rs @@ -17,7 +17,7 @@ fn main() { let mem = Rc::new(RefCell::new(MipsMem::default())); let rc_reg_file = RegFile::rc_new( "reg_file", - (360.0, 170.0), + (450.0, 150.0), Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), Input::new("reg_write_addr", REGISTER_OUT_ID), //write address @@ -28,22 +28,26 @@ fn main() { let cs = ComponentStore { store: vec![ // register that holds instr addr - Register::rc_new("pc", (170.0, 410.0), Input::new("mux_jump_merge", "out")), + Register::rc_new( + "pc", + (150.0, 390.0), + Input::new("mux_jump_merge", MUX_OUT_ID), + ), // step addr from reg by 4 - Constant::rc_new("+4", (170.0, 380.0), 4), + Constant::rc_new("+4", (150.0, 450.0), 4), Add::rc_new( "pc+4", - (220.0, 380.0), - Input::new("pc", "out"), - Input::new("+4", "out"), + (220.0, 420.0), + Input::new("+4", CONSTANT_OUT_ID), + Input::new("pc", REGISTER_OUT_ID), ), // // Rc::new( InstrMem::new( "instr_mem".into(), - (280.0, 600.0), - Input::new("pc", "out"), + (250.0, 700.0), + Input::new("pc", REGISTER_OUT_ID), Rc::clone(&mem), ) .set_mem_view_reg(rc_reg_file.clone()), @@ -53,20 +57,20 @@ fn main() { // MUX to choose what intruction addr to choose from, branch jump, reg, pc+4 Mux::rc_new( "mux_jump_merge", - (140.0, 390.0), + (100.0, 390.0), Input::new("branch", BRANCH_OUT_ID), vec![ Input::new("pc_add_branch", ADD_OUT_ID), //TODO: describe origin Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), // goes to addr, RD2 Input::new("jump_merge", MERGE_OUT_ID), // - Input::new("pc+4", CLK_OUT_ID), + Input::new("pc+4", ADD_OUT_ID), ], ), // // merges to find out jump location JumpMerge::rc_new( "jump_merge", - (125.0, 500.0), + (125.0, 525.0), Input::new("pc", REGISTER_OUT_ID), //input from reg before pc+4 Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), //input from instruction mem ), @@ -74,14 +78,14 @@ fn main() { // splits intructions from ir to fields InstrSplit::rc_new( "instruction_split", - (280.0, 140.0), + (275.0, 150.0), Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), ), // // ControlUnit::rc_new( "control_unit", - (280.0, 100.0), + (500.0, 100.0), Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), ), // @@ -95,7 +99,7 @@ fn main() { // extends immediate field SignZeroExtend::rc_new( "signzero_extend", - (310.0, 410.0), + (400.0, 475.0), Input::new("instruction_split", INSTRUCTION_SPLITTER_IMMEDIATE_ID), Input::new("control_unit", cntr_field::EXTEND_SELECT_OUT), // cu tells it to either sing- or zero- extend ), @@ -103,7 +107,7 @@ fn main() { // BranchLogic::rc_new( "branch", - (525.0, 300.0), + (575.0, 150.0), Input::new("instruction_split", INSTRUCTION_SPLITTER_OP_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_FUNCT_ID), @@ -125,9 +129,9 @@ fn main() { (650.0, 220.0), Input::new("control_unit", cntr_field::ALU_SRC_A_OUT), vec![ - Input::new("zero_extend_for_chamt", SIGNZEROEXTEND_OUT_ID), + Input::new("zero_extend_for_chamt", ZEROEXTEND_OUT_ID), Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), //FIXME should be rs? changed from rt - Input::new("0_a_inp", "out"), + Input::new("0_a_inp", CONSTANT_OUT_ID), ], ), // @@ -156,7 +160,7 @@ fn main() { Rc::new( DataMem::new( "data_mem".into(), - (600.0, 580.0), + (600.0, 700.0), Input::new("alu", FULL_ADD_OUT_ID), // calculated from rs and imm Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), Input::new("control_unit", cntr_field::MEM_MODE_OUT), @@ -187,7 +191,7 @@ fn main() { // ShiftConst::rc_new( "branch_shift", - (380.0, 460.0), + (475.0, 550.0), Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), 2, ), @@ -195,7 +199,7 @@ fn main() { // Add::rc_new( "pc_add_branch", - (420.0, 440.0), + (525.0, 600.0), Input::new("pc+4", ADD_OUT_ID), Input::new("branch_shift", SHIFT_OUT_ID), ), @@ -209,7 +213,7 @@ fn main() { vec![ Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_RD_ID), - Input::new("0x_1F", "out"), + Input::new("0x_1F", CONSTANT_OUT_ID), ], ), // @@ -225,7 +229,7 @@ fn main() { ], }; - let cs = autowire(cs); + //let cs = autowire(cs); let path = PathBuf::from("add.json"); cs.save_file(&path); diff --git a/src/components/add.rs b/src/components/add.rs index 005b7f65..2741e43e 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -11,7 +11,7 @@ use std::rc::Rc; pub const ADD_A_IN_ID: &str = "a_in"; pub const ADD_B_IN_ID: &str = "b_in"; -pub const ADD_OUT_ID: &str = "out"; +pub const ADD_OUT_ID: &str = "add_out"; pub const ADD_OVERFLOW_ID: &str = "overflow"; #[derive(Serialize, Deserialize, Clone)] @@ -89,8 +89,8 @@ impl Component for Add { ); // set output - simulator.set_out_value(&self.id, "out", value); - simulator.set_out_value(&self.id, "overflow", overflow); + simulator.set_out_value(&self.id, ADD_OUT_ID, value); + simulator.set_out_value(&self.id, ADD_OVERFLOW_ID, overflow); res } diff --git a/src/components/and.rs b/src/components/and.rs index dae2cd1f..e706e153 100644 --- a/src/components/and.rs +++ b/src/components/and.rs @@ -11,7 +11,7 @@ use std::rc::Rc; pub const AND_A_IN_ID: &str = "a_in"; pub const AND_B_IN_ID: &str = "b_in"; -pub const AND_OUT_ID: &str = "out"; +pub const AND_OUT_ID: &str = "and_out"; #[derive(Serialize, Deserialize, Clone)] pub struct And { diff --git a/src/components/constant.rs b/src/components/constant.rs index 98e5713b..b3ede0f8 100644 --- a/src/components/constant.rs +++ b/src/components/constant.rs @@ -4,7 +4,7 @@ use crate::common::{Component, Condition, Id, OutputType, Ports, Signal, Simulat use log::*; use serde::{Deserialize, Serialize}; use std::{convert::Into, rc::Rc}; -pub const CONSTANT_OUT_ID: &str = "out"; +pub const CONSTANT_OUT_ID: &str = "constant_out"; use std::any::Any; #[derive(Serialize, Deserialize, Clone)] pub struct Constant { diff --git a/src/components/equals.rs b/src/components/equals.rs index 02b07228..85120e68 100644 --- a/src/components/equals.rs +++ b/src/components/equals.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub const EQUAL_A_IN_ID: &str = "a_in"; pub const EQUAL_B_IN_ID: &str = "b_in"; -pub const EQUAL_OUT_ID: &str = "out"; +pub const EQUAL_OUT_ID: &str = "equals_out"; #[derive(Serialize, Deserialize, Clone)] pub struct Equal { diff --git a/src/components/mips_branch_logic.rs b/src/components/mips_branch_logic.rs index f96bf75e..91f3a896 100644 --- a/src/components/mips_branch_logic.rs +++ b/src/components/mips_branch_logic.rs @@ -16,7 +16,7 @@ pub const BRANCH_FUNCT_ID: &str = "branch_funct_in"; pub const BRANCH_RS_VALUE_ID: &str = "branch_rs_vlaue_id"; pub const BRANCH_RT_VALUE_ID: &str = "branch_rt_value_id"; -pub const BRANCH_OUT_ID: &str = "out"; +pub const BRANCH_OUT_ID: &str = "branch_out"; pub const BRANCH_OFFSET: u32 = 0; pub const BRANCH_REGISTER: u32 = 1; diff --git a/src/components/mips_jump_merge.rs b/src/components/mips_jump_merge.rs index db18afaa..c8b62a1d 100644 --- a/src/components/mips_jump_merge.rs +++ b/src/components/mips_jump_merge.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub const MERGE_INSTR_ADDR_ID: &str = "merge_instr_addr_in"; pub const MERGE_JUMP_ADDR_ID: &str = "merge_jump_addr_in"; -pub const MERGE_OUT_ID: &str = "out"; +pub const MERGE_OUT_ID: &str = "merge_out"; #[derive(Serialize, Deserialize, Clone)] pub struct JumpMerge { diff --git a/src/components/mux.rs b/src/components/mux.rs index 1883ebbc..f719e363 100644 --- a/src/components/mux.rs +++ b/src/components/mux.rs @@ -11,7 +11,7 @@ use std::rc::Rc; pub const MUX_SELECT_ID: &str = "select"; pub const MUX_TEMPLATE_ID: &str = "in"; -pub const MUX_OUT_ID: &str = "out"; +pub const MUX_OUT_ID: &str = "mux_out"; #[derive(Serialize, Deserialize, Clone)] pub struct Mux { @@ -83,7 +83,7 @@ impl Component for Mux { }; trace!("-----------------value:{:?}, end---------------", value); // set output - simulator.set_out_value(&self.id, "out", value); + simulator.set_out_value(&self.id, MUX_OUT_ID, value); res } diff --git a/src/components/register.rs b/src/components/register.rs index cba6e29a..2dde8dac 100644 --- a/src/components/register.rs +++ b/src/components/register.rs @@ -8,7 +8,7 @@ use std::rc::Rc; pub const REGISTER_R_IN_ID: &str = "r_in"; -pub const REGISTER_OUT_ID: &str = "out"; +pub const REGISTER_OUT_ID: &str = "register_out"; #[derive(Serialize, Deserialize, Clone)] pub struct Register { @@ -51,7 +51,7 @@ impl Component for Register { // get input value let value = simulator.get_input_value(&self.r_in); // set output - simulator.set_out_value(&self.id, "out", value); + simulator.set_out_value(&self.id, REGISTER_OUT_ID, value); trace!("eval: register id {} in {:?}", self.id, value); Ok(()) } diff --git a/src/components/sext.rs b/src/components/sext.rs index 8f36e12c..60636285 100644 --- a/src/components/sext.rs +++ b/src/components/sext.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub const SEXT_IN_ID: &str = "sext_in"; -pub const SEXT_OUT_ID: &str = "out"; +pub const SEXT_OUT_ID: &str = "sext_out"; #[derive(Serialize, Deserialize, Clone)] pub struct Sext { @@ -82,10 +82,10 @@ impl Component for Sext { value >>= to_shr; // set output - simulator.set_out_value(&self.id, "out", SignalValue::Data(value)); + simulator.set_out_value(&self.id, SEXT_OUT_ID, SignalValue::Data(value)); } _ => { - simulator.set_out_value(&self.id, "out", SignalValue::Unknown); + simulator.set_out_value(&self.id, SEXT_OUT_ID, SignalValue::Unknown); trace!("{} unknown input", self.id); } } diff --git a/src/components/shift_left_const.rs b/src/components/shift_left_const.rs index af1a78b4..a09eedff 100644 --- a/src/components/shift_left_const.rs +++ b/src/components/shift_left_const.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub const SHIFT_SIGNAL_IN_ID: &str = "shift_in"; -pub const SHIFT_OUT_ID: &str = "out"; +pub const SHIFT_OUT_ID: &str = "shift_left_const_out"; #[derive(Serialize, Deserialize, Clone)] pub struct ShiftConst { diff --git a/src/components/sz_extend.rs b/src/components/sz_extend.rs index 6b4b58bc..2535398f 100644 --- a/src/components/sz_extend.rs +++ b/src/components/sz_extend.rs @@ -14,7 +14,7 @@ use std::rc::Rc; pub const SIGNZEROEXTEND_SIGNAL_IN_ID: &str = "signzero_signal_in"; pub const SIGNZEROEXTEND_CTRL_IN_ID: &str = "signzero_ctrl_in"; -pub const SIGNZEROEXTEND_OUT_ID: &str = "out"; +pub const SIGNZEROEXTEND_OUT_ID: &str = "sz_out"; #[derive(Serialize, Deserialize, Clone)] pub struct SignZeroExtend { diff --git a/src/components/zero_extend.rs b/src/components/zero_extend.rs index e196ff0b..a4f8f7be 100644 --- a/src/components/zero_extend.rs +++ b/src/components/zero_extend.rs @@ -12,7 +12,7 @@ use std::rc::Rc; pub const ZEROEXTEND_SIGNAL_IN_ID: &str = "signal_in"; -pub const ZEROEXTEND_OUT_ID: &str = "out"; +pub const ZEROEXTEND_OUT_ID: &str = "zero_extend_out"; #[derive(Serialize, Deserialize, Clone)] pub struct ZeroExtend { diff --git a/src/gui_egui/mips_mem_view_window.rs b/src/gui_egui/mips_mem_view_window.rs index e4be6896..9b25901b 100644 --- a/src/gui_egui/mips_mem_view_window.rs +++ b/src/gui_egui/mips_mem_view_window.rs @@ -6,6 +6,7 @@ use std::{ }; use crate::components::{InstrMem, MemOpSize, MipsMem, RegFile}; +use MIPS_disassembly; use serde::{Deserialize, Serialize}; @@ -531,7 +532,11 @@ impl MemViewWindow { format!("{:#010x}", data_u32) } DataFormat::HexAndMips => { - format!("{:#010x} MIPS DISASSEMBLY NOT IMPLEMENTED", data_u32) + format!( + "{:#010x} {:015}", + data_u32, + MIPS_disassembly::get_dissassembly(data_u32) + ) } DataFormat::Bin => { format!("{:032b}", data_u32) From 6d95bf7b1629fb5585fc8d8fae71cf270e8881a9 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Fri, 30 Aug 2024 15:51:47 +0200 Subject: [PATCH 075/126] updated wire hover to work with slanted lines --- src/gui_egui/components/wire.rs | 103 +++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 36 deletions(-) diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 85054025..aa5b81fc 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -1,16 +1,60 @@ -use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::common::{EguiComponent, Ports, Simulator}; use crate::components::Wire; -use crate::gui_egui::component_ui::{ - input_change_id, input_selector, rect_with_hover, visualize_ports, -}; +use crate::gui_egui::component_ui::{input_change_id, input_selector, visualize_ports}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions, SnapPriority}; use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::{offset_helper, shadow_small_dark}; +use crate::gui_egui::helper::{basic_on_hover, offset_helper, shadow_small_dark}; use egui::{ Color32, DragValue, Frame, Key, KeyboardShortcut, Margin, Modifiers, PointerButton, Pos2, Rect, Response, Rounding, Shape, Stroke, Ui, Vec2, Window, }; +/// if the mouse cursor is less than this distance in points away from the wire display tooltip +/// Note points is often same as pixels, but some times differ with the points_per_pixels value in egui +const TOOLTIP_DISTANCE: f32 = 5.0; + +fn min_from_line(start: Vec2, end: Vec2, point: Vec2) -> f32 { + // could probably use length_sq, but this don't need to be optimized + let length = (end - start).length(); + if length == 0f32 { + return (start - point).length(); + }; + + let dir_to_end = (end - start).normalized(); + let point_rel_to_start = point - start; + // dot prud, + // a dot b = abs(a)*abs(b)*cos(theta) + // if a is one we can use this to determine how far along the line our point is + let dist_along_line = dir_to_end.dot(point_rel_to_start); + + // if we are before our line start + if dist_along_line < 0f32 { + // distance to our start point + (point - start).length() + } + // if our point is after the end of our line + else if dist_along_line > length { + // distance to our end point + (point - end).length() + } + // our point is between the line + else { + // project vec a up on vec b + // abs(a) * cos(theta) * b/abs(b) + // we can se the resemblance to dot product + // abs(a) * abs(b) * cos(theta) * b/abs(b) # one tu much abs (b) + // abs(a) * abs(b) * cos(theta) * b/(abs(b))^2 + // a dot b * b/abs(b)^2 + // this is our point projected along our line (line starts at origin) + // if abs(b) is one, aka normalized we can simplify the math + // a dot b * b/1^2 + // a dot b * b + let proj_point_on_line = point_rel_to_start.dot(dir_to_end) * dir_to_end; + // lets use this to calculate the orthogonal vector from our line to our point + (point_rel_to_start - proj_point_on_line).length() + } +} + #[typetag::serde] impl EguiComponent for Wire { fn render( @@ -39,38 +83,25 @@ impl EguiComponent for Wire { color: Color32::BLACK, }, )); - let mut r_vec = vec![]; - - for (i, _) in line_vec[1..].iter().enumerate() { - let (line_top, line_bottom) = if line_vec[i].x > line_vec[i + 1].x { - (line_vec[i + 1].x, line_vec[i].x) - } else { - (line_vec[i].x, line_vec[i + 1].x) - }; - let (line_left, line_right) = if line_vec[i].y > line_vec[i + 1].y { - (line_vec[i + 1].y, line_vec[i].y) - } else { - (line_vec[i].y, line_vec[i + 1].y) - }; - let rect = Rect { - min: Pos2::new(line_top, line_left), - max: Pos2::new(line_bottom, line_right), - }; - let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - ui.label(format!("Id: {}", self.id.clone())); - if let Some(s) = &simulator { - ui.label({ - let r: Result = - s.get_input_value(&self.input).try_into(); - match r { - Ok(data) => format!("{:#x}", data), - _ => format!("{:?}", r), - } - }); + for val in line_vec.windows(2) { + let first_pos = val[0]; + let last_pos = val[1]; + if let Some(cursor) = ui.ctx().pointer_latest_pos() { + if min_from_line(first_pos.to_vec2(), last_pos.to_vec2(), cursor.to_vec2()) + < TOOLTIP_DISTANCE + && clip_rect.contains(cursor) + { + egui::containers::popup::show_tooltip_at( + ui.ctx(), + ui.layer_id(), + egui::Id::new(&self.id), + (first_pos + last_pos.to_vec2()) / 2.0, + |ui| basic_on_hover(ui, self, &simulator), + ); + break; } - }); - r_vec.push(r); + }; } match editor_mode { @@ -78,7 +109,7 @@ impl EguiComponent for Wire { _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), } - Some(r_vec) + Some(vec![]) } fn render_editor( From 51520f778939778ee17f9ca0ddd0871616706005 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Fri, 30 Aug 2024 16:30:18 +0200 Subject: [PATCH 076/126] wip --- examples/mips_example_1.rs | 4 ++-- src/gui_egui/components/mips_reg_file.rs | 2 +- src/gui_egui/components/register.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/mips_example_1.rs b/examples/mips_example_1.rs index 78a8716b..e735ae93 100644 --- a/examples/mips_example_1.rs +++ b/examples/mips_example_1.rs @@ -130,7 +130,7 @@ fn main() { Input::new("control_unit", cntr_field::ALU_SRC_A_OUT), vec![ Input::new("zero_extend_for_chamt", ZEROEXTEND_OUT_ID), - Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), //FIXME should be rs? changed from rt + Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), Input::new("0_a_inp", CONSTANT_OUT_ID), ], ), @@ -141,7 +141,7 @@ fn main() { (650.0, 300.0), Input::new("control_unit", cntr_field::ALU_SRC_B_OUT), vec![ - Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), //FIXME should be rt? changed from rs + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), Input::new("pc+4", ADD_OUT_ID), Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), ], diff --git a/src/gui_egui/components/mips_reg_file.rs b/src/gui_egui/components/mips_reg_file.rs index eb4d75d3..63cc68f5 100644 --- a/src/gui_egui/components/mips_reg_file.rs +++ b/src/gui_egui/components/mips_reg_file.rs @@ -25,7 +25,7 @@ impl EguiComponent for RegFile { ) -> Option> { basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { ui.set_width(120f32 * scale); - ui.set_height(400f32 * scale); + ui.set_height(300f32 * scale); ui.label("Register File"); // A toggle button for showing register names diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index 2fd862ba..5331e498 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -1,5 +1,5 @@ use crate::common::{EguiComponent, Input, Ports, SignalUnsigned, Simulator}; -use crate::components::Register; +use crate::components::{Register, REGISTER_OUT_ID}; use crate::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, visualize_ports, @@ -66,7 +66,7 @@ impl EguiComponent for Register { let r: Result = s .get_input_value(&Input { id: self.id.clone(), - field: "out".to_string(), + field: REGISTER_OUT_ID.to_string(), }) .try_into(); match r { From cdd60ac0bf810cde3dc47551bbacec09f70135f2 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Sat, 31 Aug 2024 15:33:22 +0200 Subject: [PATCH 077/126] optimized math --- src/gui_egui/components/wire.rs | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index aa5b81fc..f3efb344 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -13,45 +13,49 @@ use egui::{ /// Note points is often same as pixels, but some times differ with the points_per_pixels value in egui const TOOLTIP_DISTANCE: f32 = 5.0; +/// Calculates the minimum distance the point is from our line going from start: Vec2 to end: Vec2 fn min_from_line(start: Vec2, end: Vec2, point: Vec2) -> f32 { // could probably use length_sq, but this don't need to be optimized - let length = (end - start).length(); + let length: f32 = (end - start).length(); + // if length is zero, get length between start and point if length == 0f32 { return (start - point).length(); }; - let dir_to_end = (end - start).normalized(); - let point_rel_to_start = point - start; - // dot prud, + let dir_to_end: Vec2 = (end - start).normalized(); + let point_rel_to_start: Vec2 = point - start; + // dot product, // a dot b = abs(a)*abs(b)*cos(theta) - // if a is one we can use this to determine how far along the line our point is - let dist_along_line = dir_to_end.dot(point_rel_to_start); + // if abs(a)=1 we can use this to determine how far along the line our point is + let dist_along_line: f32 = dir_to_end.dot(point_rel_to_start); // if we are before our line start if dist_along_line < 0f32 { // distance to our start point - (point - start).length() + (point - start).length() // return this value } // if our point is after the end of our line else if dist_along_line > length { // distance to our end point - (point - end).length() + (point - end).length() // return this value } // our point is between the line else { // project vec a up on vec b + // theta is the angel between our vectors // abs(a) * cos(theta) * b/abs(b) - // we can se the resemblance to dot product - // abs(a) * abs(b) * cos(theta) * b/abs(b) # one tu much abs (b) + // we can se the resemblance to a dot product + // abs(a) * abs(b) * cos(theta) * b/abs(b) # one to much abs(b) // abs(a) * abs(b) * cos(theta) * b/(abs(b))^2 // a dot b * b/abs(b)^2 - // this is our point projected along our line (line starts at origin) - // if abs(b) is one, aka normalized we can simplify the math + // this is our point projected along our line (line starts at origin (0,0)) + // if abs(b)=1, aka normalized we can simplify the math // a dot b * b/1^2 // a dot b * b - let proj_point_on_line = point_rel_to_start.dot(dir_to_end) * dir_to_end; + // a dot b is already calculated in dist along line + let proj_point_on_line: Vec2 = dist_along_line * dir_to_end; // lets use this to calculate the orthogonal vector from our line to our point - (point_rel_to_start - proj_point_on_line).length() + (point_rel_to_start - proj_point_on_line).length() // return this value } } From 607f0a3d6bf6806b025ea23d70a206f2718ee69b Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Sat, 31 Aug 2024 16:36:45 +0200 Subject: [PATCH 078/126] updated to use new version of MIPS_disassembly crate --- Cargo.toml | 2 +- src/gui_egui/mips_mem_view_window.rs | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 200313ac..998c3de0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" members = ["mips", "riscv"] [dependencies] -MIPS_disassembly = "0.1.1" +MIPS_disassembly = "0.1.2" anyhow = "1.0.72" clap = { version = "4.3.15", features = ["derive"] } elf = "0.7.4" diff --git a/src/gui_egui/mips_mem_view_window.rs b/src/gui_egui/mips_mem_view_window.rs index 9b25901b..72215b2e 100644 --- a/src/gui_egui/mips_mem_view_window.rs +++ b/src/gui_egui/mips_mem_view_window.rs @@ -527,6 +527,8 @@ impl MemViewWindow { .borrow() .get_unaligned(adrs, MemOpSize::Word, false, true) .to_be_bytes(); + // TODO get symbol table clones the hashmap, this is infective + let sym_tab = self.mem.borrow().get_symbol_table(); match self.format { DataFormat::Hex => { format!("{:#010x}", data_u32) @@ -535,7 +537,12 @@ impl MemViewWindow { format!( "{:#010x} {:015}", data_u32, - MIPS_disassembly::get_dissassembly(data_u32) + MIPS_disassembly::get_disassembly_adv( + data_u32, + adrs, + &sym_tab, + &MIPS_disassembly::MipsDisassemblyOptions::new(true, true) + ) ) } DataFormat::Bin => { From 5066ee1b67b261181212c751fb5980472ff7bc11 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Sat, 31 Aug 2024 19:26:34 +0200 Subject: [PATCH 079/126] cheged sices and mede mips presentable --- examples/mips_example_1.rs | 48 +++++++++---------- src/gui_egui/components/add.rs | 31 +++++++----- src/gui_egui/components/mips_controll_unit.rs | 2 +- .../components/mips_instruction_splitter.rs | 2 +- src/gui_egui/components/mips_reg_file.rs | 2 +- src/gui_egui/components/mux.rs | 32 ++++++++----- 6 files changed, 67 insertions(+), 50 deletions(-) diff --git a/examples/mips_example_1.rs b/examples/mips_example_1.rs index e735ae93..5041b2cc 100644 --- a/examples/mips_example_1.rs +++ b/examples/mips_example_1.rs @@ -17,7 +17,7 @@ fn main() { let mem = Rc::new(RefCell::new(MipsMem::default())); let rc_reg_file = RegFile::rc_new( "reg_file", - (450.0, 150.0), + (350.0, 225.0), Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), Input::new("reg_write_addr", REGISTER_OUT_ID), //write address @@ -34,10 +34,10 @@ fn main() { Input::new("mux_jump_merge", MUX_OUT_ID), ), // step addr from reg by 4 - Constant::rc_new("+4", (150.0, 450.0), 4), + Constant::rc_new("+4", (150.0, 440.0), 4), Add::rc_new( "pc+4", - (220.0, 420.0), + (200.0, 400.0), Input::new("+4", CONSTANT_OUT_ID), Input::new("pc", REGISTER_OUT_ID), ), @@ -46,7 +46,7 @@ fn main() { Rc::new( InstrMem::new( "instr_mem".into(), - (250.0, 700.0), + (250.0, 575.0), Input::new("pc", REGISTER_OUT_ID), Rc::clone(&mem), ) @@ -70,7 +70,7 @@ fn main() { // merges to find out jump location JumpMerge::rc_new( "jump_merge", - (125.0, 525.0), + (125.0, 475.0), Input::new("pc", REGISTER_OUT_ID), //input from reg before pc+4 Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), //input from instruction mem ), @@ -78,28 +78,28 @@ fn main() { // splits intructions from ir to fields InstrSplit::rc_new( "instruction_split", - (275.0, 150.0), + (200.0, 225.0), Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), ), // // ControlUnit::rc_new( "control_unit", - (500.0, 100.0), + (500.0, 50.0), Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), ), // // Register::rc_new( "reg_we", - (850.0, 100.0), + (850.0, 50.0), Input::new("control_unit", cntr_field::REG_WRITE_ENABLE_OUT), ), // // extends immediate field SignZeroExtend::rc_new( "signzero_extend", - (400.0, 475.0), + (325.0, 425.0), Input::new("instruction_split", INSTRUCTION_SPLITTER_IMMEDIATE_ID), Input::new("control_unit", cntr_field::EXTEND_SELECT_OUT), // cu tells it to either sing- or zero- extend ), @@ -107,7 +107,7 @@ fn main() { // BranchLogic::rc_new( "branch", - (575.0, 150.0), + (475.0, 225.0), Input::new("instruction_split", INSTRUCTION_SPLITTER_OP_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), Input::new("instruction_split", INSTRUCTION_SPLITTER_FUNCT_ID), @@ -118,15 +118,15 @@ fn main() { // ZeroExtend::rc_new( "zero_extend_for_chamt", - (550.0, 170.0), + (600.0, 150.0), Input::new("instruction_split", INSTRUCTION_SPLITTER_SHAMT_ID), ), // // - Constant::rc_new("0_a_inp", (600.0, 230.0), 0), + Constant::rc_new("0_a_inp", (610.0, 220.0), 0), Mux::rc_new( "mux_source_a", - (650.0, 220.0), + (650.0, 195.0), Input::new("control_unit", cntr_field::ALU_SRC_A_OUT), vec![ Input::new("zero_extend_for_chamt", ZEROEXTEND_OUT_ID), @@ -138,7 +138,7 @@ fn main() { // Mux::rc_new( "mux_source_b", - (650.0, 300.0), + (650.0, 255.0), Input::new("control_unit", cntr_field::ALU_SRC_B_OUT), vec![ Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), @@ -150,7 +150,7 @@ fn main() { // FullAdd::rc_new( "alu", - (720.0, 220.0), + (720.0, 225.0), Input::new("mux_source_a", MUX_OUT_ID), Input::new("mux_source_b", MUX_OUT_ID), Input::new("control_unit", cntr_field::ALU_OP_OUT), @@ -160,7 +160,7 @@ fn main() { Rc::new( DataMem::new( "data_mem".into(), - (600.0, 700.0), + (600.0, 575.0), Input::new("alu", FULL_ADD_OUT_ID), // calculated from rs and imm Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), Input::new("control_unit", cntr_field::MEM_MODE_OUT), @@ -173,7 +173,7 @@ fn main() { // Mux::rc_new( "mux_write_back", - (800.0, 270.0), + (800.0, 225.0), Input::new("control_unit", cntr_field::REG_WRITE_SRC_OUT), vec![ Input::new("alu", FULL_ADD_OUT_ID), @@ -184,14 +184,14 @@ fn main() { // Register::rc_new( "result_reg", - (850.0, 290.0), + (850.0, 225.0), Input::new("mux_write_back", MUX_OUT_ID), ), // // ShiftConst::rc_new( "branch_shift", - (475.0, 550.0), + (325.0, 480.0), Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), 2, ), @@ -199,16 +199,16 @@ fn main() { // Add::rc_new( "pc_add_branch", - (525.0, 600.0), + (400.0, 475.0), Input::new("pc+4", ADD_OUT_ID), Input::new("branch_shift", SHIFT_OUT_ID), ), // // - Constant::rc_new("0x_1F", (500.0, 510.0), 0x_1F), + Constant::rc_new("0x_1F", (350.0, 550.0), 0x_1F), Mux::rc_new( "mux_write_addr", - (560.0, 500.0), + (400.0, 525.0), Input::new("control_unit", cntr_field::REG_DEST_OUT), vec![ Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), @@ -220,7 +220,7 @@ fn main() { // Register::rc_new( "reg_write_addr", - (850.0, 520.0), + (850.0, 525.0), Input::new("mux_write_addr", MUX_OUT_ID), ), // @@ -229,7 +229,7 @@ fn main() { ], }; - //let cs = autowire(cs); + let cs = autowire(cs); let path = PathBuf::from("add.json"); cs.save_file(&path); diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 4f2adf8c..756c6307 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -32,19 +32,28 @@ impl EguiComponent for Add { offset.y += self.pos.1 * scale; let s = scale; let o = offset; + // The shape + #[rustfmt::skip] // stop formate from "compacting" our vec, doesn't affect anything else + let shape: Vec<(f32, f32)> = vec![ + (-20f32, -40f32), + (0f32, -40f32), + (20f32, -20f32), + (20f32, 20f32), + (0f32, 40f32), + (-20f32, 40f32), + (-20f32, 20f32), + (-10f32, 0f32), + (-20f32, -20f32), + ]; + + let comp_scale = 0.6; + // The shape ui.painter().add(Shape::closed_line( - vec![ - oh((-20f32, -40f32), s, o), - oh((0f32, -40f32), s, o), - oh((20f32, -20f32), s, o), - oh((20f32, 20f32), s, o), - oh((0f32, 40f32), s, o), - oh((-20f32, 40f32), s, o), - oh((-20f32, 20f32), s, o), - oh((-10f32, 0f32), s, o), - oh((-20f32, -20f32), s, o), - ], + shape + .iter() + .map(|(x, y)| oh((x * comp_scale, y * comp_scale), s, o)) + .collect(), Stroke { width: scale, color: Color32::RED, diff --git a/src/gui_egui/components/mips_controll_unit.rs b/src/gui_egui/components/mips_controll_unit.rs index 183ff43b..7b18a1be 100644 --- a/src/gui_egui/components/mips_controll_unit.rs +++ b/src/gui_egui/components/mips_controll_unit.rs @@ -18,7 +18,7 @@ impl EguiComponent for ControlUnit { _editor_mode: EditorMode, ) -> Option> { // size of the component - let width = 400f32 * scale; + let width = 100f32 * scale; let height: f32 = 12f32 * scale; basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { ui.set_height(height); diff --git a/src/gui_egui/components/mips_instruction_splitter.rs b/src/gui_egui/components/mips_instruction_splitter.rs index a717189a..0d28b653 100644 --- a/src/gui_egui/components/mips_instruction_splitter.rs +++ b/src/gui_egui/components/mips_instruction_splitter.rs @@ -19,7 +19,7 @@ impl EguiComponent for InstrSplit { ) -> Option> { // size of the component let width = 50f32 * scale; - let height: f32 = 300f32 * scale; + let height: f32 = 200f32 * scale; basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { ui.set_height(height); ui.set_width(width); diff --git a/src/gui_egui/components/mips_reg_file.rs b/src/gui_egui/components/mips_reg_file.rs index 63cc68f5..43e32900 100644 --- a/src/gui_egui/components/mips_reg_file.rs +++ b/src/gui_egui/components/mips_reg_file.rs @@ -25,7 +25,7 @@ impl EguiComponent for RegFile { ) -> Option> { basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { ui.set_width(120f32 * scale); - ui.set_height(300f32 * scale); + ui.set_height(250f32 * scale); ui.label("Register File"); // A toggle button for showing register names diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index d2a747f6..ec769683 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -37,17 +37,22 @@ impl EguiComponent for Mux { Some(s) => s.get_input_value(&self.select).try_into().unwrap_or(0), None => 0, }; + let mut shape: Vec<(f32, f32)> = vec![ + (-20f32, pa * (-10f32) - 10f32), + (0f32, pa * (-10f32) - 10f32), + (10f32, pa * (-10f32) + 10f32), + (10f32, pa * (10f32) - 10f32), + (0f32, pa * (10f32) + 10f32), + (-20f32, pa * (10f32) + 10f32), + ]; + for (x, y) in shape.iter_mut() { + *x *= 0.6; + *y *= 0.6; + } // The shape ui.painter().add(Shape::closed_line( - vec![ - oh((-20f32, pa * (-10f32) - 10f32), s, o), - oh((0f32, pa * (-10f32) - 10f32), s, o), - oh((10f32, pa * (-10f32) + 10f32), s, o), - oh((10f32, pa * (10f32) - 10f32), s, o), - oh((0f32, pa * (10f32) + 10f32), s, o), - oh((-20f32, pa * (10f32) + 10f32), s, o), - ], + shape.clone().iter().map(|point| oh(*point, s, o)).collect(), Stroke { width: scale, color: Color32::BLACK, @@ -58,11 +63,14 @@ impl EguiComponent for Mux { ui.painter().add(Shape::line_segment( [ oh( - (-20f32, ((select as f32) * 20f32) - pa * 10f32 + 10f32), + ( + -20f32 * 0.6, + (((select as f32) * 20f32) - pa * 10f32 + 10f32) * 0.6, + ), s, o, ), - oh((10f32, 0f32), s, o), + oh((10f32 * 0.6, 0f32 * 0.6), s, o), ], Stroke { width: scale, @@ -71,8 +79,8 @@ impl EguiComponent for Mux { )); let rect = Rect { - min: oh((-20f32, pa * (-10f32) - 10f32), s, o), - max: oh((10f32, pa * 10f32 + 10f32), s, o), + min: oh((-20f32 * 0.6, (pa * (-10f32) - 10f32) * 0.6), s, o), + max: oh((10f32 * 0.6, (pa * 10f32 + 10f32) * 0.6), s, o), }; let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { ui.label(format!("Id: {}", self.id.clone())); From 464cb3aac56d6e9405ab90586b53e982ad58d240 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Mon, 2 Sep 2024 14:44:53 +0200 Subject: [PATCH 080/126] added reset and un_clock to data mem --- src/components/mips_dm.rs | 52 ++++++++++++++--- src/components/mips_mem_struct.rs | 97 ++++++++++++++++++++++++++++--- 2 files changed, 133 insertions(+), 16 deletions(-) diff --git a/src/components/mips_dm.rs b/src/components/mips_dm.rs index 0f95b939..e2d9e12e 100644 --- a/src/components/mips_dm.rs +++ b/src/components/mips_dm.rs @@ -7,10 +7,10 @@ use crate::{ use core::cell::RefCell; use log::*; use serde::{Deserialize, Serialize}; -use std::{any::Any, rc::Rc}; +use std::{collections::HashMap, rc::Rc}; use super::{ - mips_mem_struct::{MemOpSize, MipsMem}, + mips_mem_struct::{MemOpSize, MemWriteReturn, MipsMem}, RegFile, }; @@ -42,10 +42,16 @@ pub struct DataMem { pub data_input: Input, pub op_input: Input, pub write_enable_input: Input, - // should probably not skip mem rc here, since we still need them to point to the same MipsMem + // FIXME should probably not skip mem rc here, since we still need them to point to the same MipsMem #[serde(skip)] pub mem: Rc>, pub mem_view: RefCell, + + #[serde(skip)] + history: RefCell>, + // used for the un_clock(), this is because the simulator is not passed in un clock and we dont know what cycle we un clock to + #[serde(skip)] + cycle: RefCell, } impl DataMem { @@ -69,6 +75,8 @@ impl DataMem { op_input: op_input, write_enable_input: write_enable_input, mem_view: RefCell::new(mem_view), + history: RefCell::new(HashMap::new()), + cycle: RefCell::default(), // this doesn't mater will be overwritten when clock is called } } pub fn rc_new( @@ -94,6 +102,9 @@ impl DataMem { self.mem_view.get_mut().update_regfile(reg_rc); self } + fn up_hist(&self, op: MemWriteReturn) { + self.history.borrow_mut().insert(*self.cycle.borrow(), op); + } } #[typetag::serde()] @@ -159,6 +170,7 @@ impl Component for DataMem { } fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + *self.cycle.borrow_mut() = simulator.cycle; // get instr at pc/4s let address: u32 = simulator .get_input_value(&self.address_input) @@ -276,9 +288,11 @@ impl Component for DataMem { } } data_op::STORE_BYTE => { - self.mem - .borrow_mut() - .write(address, data, MemOpSize::Byte, true); + self.up_hist( + self.mem + .borrow_mut() + .write(address, data, MemOpSize::Byte, true), + ); simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); Ok(()) } @@ -288,7 +302,8 @@ impl Component for DataMem { .borrow_mut() .write_aligned(address, data, MemOpSize::Half, true) { - Ok(_) => { + Ok(ret) => { + self.up_hist(ret); simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); Ok(()) } @@ -304,7 +319,8 @@ impl Component for DataMem { .borrow_mut() .write_aligned(address, data, MemOpSize::Word, true) { - Ok(_) => { + Ok(ret) => { + self.up_hist(ret); simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); Ok(()) } @@ -334,4 +350,24 @@ impl Component for DataMem { Err(_) => ret, } } + + fn un_clock(&self) { + *self.cycle.borrow_mut() -= 1; + if let Some(op) = self.history.borrow_mut().remove(&*self.cycle.borrow()) { + self.mem.borrow_mut().revert(op); + }; + } + + fn reset(&self) { + // dont need to reset cycle, since cycle is updated in clock + + let mut hist_vec: Vec<(usize, MemWriteReturn)> = + self.history.borrow_mut().drain().collect(); + // sort vec with largest first + hist_vec.sort_by(|(a, _), (b, _)| a.cmp(b).reverse()); + let mut mem = self.mem.borrow_mut(); + for (_, op) in hist_vec { + mem.revert(op); + } + } } diff --git a/src/components/mips_mem_struct.rs b/src/components/mips_mem_struct.rs index 9b369d1b..e9123316 100644 --- a/src/components/mips_mem_struct.rs +++ b/src/components/mips_mem_struct.rs @@ -10,11 +10,36 @@ pub struct MipsMem { sections: HashMap, data: BTreeMap, } +#[derive(Clone)] pub enum MemOpSize { Byte, Half, Word, } +/// This struct is not ment to be cloned +#[derive(Clone)] +pub struct MemWriteReturn { + address: u32, + op_size: MemOpSize, + bytes: [u8; 4], +} +impl MemWriteReturn { + /// return the address the bytes comes from + pub fn address(&self) -> u32 { + self.address + } + pub fn op_size(&self) -> MemOpSize { + self.op_size.clone() + } + /// return the bytes befre the write where [0] is at address, [1] is at address + 1 and [N] is at address + N + pub fn before_bytes(&self) -> Vec { + match self.op_size { + MemOpSize::Byte => vec![self.bytes[0]], + MemOpSize::Half => vec![self.bytes[0], self.bytes[1]], + MemOpSize::Word => vec![self.bytes[0], self.bytes[1], self.bytes[4], self.bytes[3]], + } + } +} impl MipsMem { /// This function constructs a Mem struct using the elf sections to load the data. @@ -147,10 +172,21 @@ impl MipsMem { } /// Will truncate the data to the given size and write the data to memory - pub fn write(&mut self, address: u32, data: u32, size: MemOpSize, big_endian: bool) { + pub fn write( + &mut self, + address: u32, + data: u32, + size: MemOpSize, + big_endian: bool, + ) -> MemWriteReturn { match size { MemOpSize::Byte => { - self.data.insert(address, data as u8); + let b = self.data.insert(address, data as u8).unwrap_or(0); + MemWriteReturn { + address, + op_size: size, + bytes: [b, 0, 0, 0], + } } MemOpSize::Half => { let uint_16 = data as u16; @@ -159,8 +195,13 @@ impl MipsMem { } else { uint_16.to_le_bytes() }; - self.data.insert(address, bytes[0]); - self.data.insert(address + 1, bytes[1]); + let b0 = self.data.insert(address, bytes[0]).unwrap_or(0); + let b1 = self.data.insert(address + 1, bytes[1]).unwrap_or(0); + MemWriteReturn { + address, + op_size: size, + bytes: [b0, b1, 0, 0], + } } MemOpSize::Word => { let bytes = if big_endian { @@ -168,9 +209,18 @@ impl MipsMem { } else { data.to_le_bytes() }; + let mut b: [u8; 4] = [0; 4]; bytes.iter().enumerate().for_each(|(i, byte)| { - self.data.insert(address + i as u32, byte.to_owned()); + b[i] = self + .data + .insert(address + i as u32, byte.to_owned()) + .unwrap_or(0); }); + MemWriteReturn { + address, + op_size: size, + bytes: b, + } } } } @@ -182,7 +232,7 @@ impl MipsMem { data: u32, size: MemOpSize, big_endian: bool, - ) -> Result<(), ()> { + ) -> Result { let size_int: u32 = match size { MemOpSize::Byte => 1, MemOpSize::Half => 2, @@ -191,8 +241,7 @@ impl MipsMem { if address % size_int != 0 { Err(()) } else { - self.write(address, data, size, big_endian); - Ok(()) + Ok(self.write(address, data, size, big_endian)) } } @@ -218,6 +267,38 @@ impl MipsMem { None => (), } } + /// consumes undo the passed related mem write operation + pub fn revert(&mut self, op: MemWriteReturn) { + match op.op_size { + MemOpSize::Byte => { + self.data + .insert(op.address, op.bytes[0]) + .expect("tried to revert an write operation that did not happen"); + } + MemOpSize::Half => { + self.data + .insert(op.address, op.bytes[0]) + .expect("tried to revert an write operation that did not happen"); + self.data + .insert(op.address + 1, op.bytes[1]) + .expect("tried to revert an write operation that did not happen"); + } + MemOpSize::Word => { + self.data + .insert(op.address, op.bytes[0]) + .expect("tried to revert an write operation that did not happen"); + self.data + .insert(op.address + 1, op.bytes[1]) + .expect("tried to revert an write operation that did not happen"); + self.data + .insert(op.address + 2, op.bytes[2]) + .expect("tried to revert an write operation that did not happen"); + self.data + .insert(op.address + 3, op.bytes[3]) + .expect("tried to revert an write operation that did not happen"); + } + } + } pub fn get_symbol_table(&self) -> HashMap { self.symbols.clone() From 7460c9db7195d5ec98011c5ab3ea10e61994409e Mon Sep 17 00:00:00 2001 From: onsdagens Date: Mon, 2 Sep 2024 16:13:11 +0200 Subject: [PATCH 081/126] example move components --- Cargo.toml | 2 +- mips-lib/Cargo.toml | 29 + mips-lib/src/components/full_adder.rs | 309 +++++ mips-lib/src/components/mips_control_unit.rs | 1011 ++++++++++++++ mips-lib/src/components/mips_dm.rs | 373 ++++++ mips-lib/src/components/mod.rs | 9 + mips-lib/src/components/sz_extend.rs | 126 ++ mips-lib/src/gui_egui/full_adder.rs | 204 +++ mips-lib/src/gui_egui/mips_control_unit.rs | 70 + mips-lib/src/gui_egui/mips_dm.rs | 99 ++ mips-lib/src/gui_egui/mod.rs | 4 + mips-lib/src/gui_egui/sz_extend.rs | 83 ++ .../gui_egui/mod.rs => mips-lib/src/lib.rs | 2 + mips-simple/Cargo.toml | 17 + mips-simple/src/main.rs | 243 ++++ mips/Cargo.toml | 38 - mips/README.md | 3 - mips/examples/mips.rs | 75 -- mips/examples/reg_file.rs | 99 -- mips/src/components/instr_mem.rs | 80 -- mips/src/components/mod.rs | 5 - mips/src/components/reg_file.rs | 353 ----- mips/src/gui_egui/components/instr_mem.rs | 5 - mips/src/gui_egui/components/mod.rs | 2 - mips/src/gui_egui/components/reg_file.rs | 5 - mips/src/gui_vizia/components/instr_mem.rs | 77 -- mips/src/gui_vizia/components/mod.rs | 2 - mips/src/gui_vizia/components/reg_file.rs | 129 -- mips/src/gui_vizia/mod.rs | 1 - mips/src/lib.rs | 8 - mips/src/main.rs | 16 - mips/tests/component_tests.rs | 7 - src/components/mips_controll_unit.rs | 1179 +++-------------- src/components/mod.rs | 20 +- src/gui_egui/components/mod.rs | 8 +- src/gui_egui/editor.rs | 29 - 36 files changed, 2780 insertions(+), 1942 deletions(-) create mode 100644 mips-lib/Cargo.toml create mode 100644 mips-lib/src/components/full_adder.rs create mode 100644 mips-lib/src/components/mips_control_unit.rs create mode 100644 mips-lib/src/components/mips_dm.rs create mode 100644 mips-lib/src/components/mod.rs create mode 100644 mips-lib/src/components/sz_extend.rs create mode 100644 mips-lib/src/gui_egui/full_adder.rs create mode 100644 mips-lib/src/gui_egui/mips_control_unit.rs create mode 100644 mips-lib/src/gui_egui/mips_dm.rs create mode 100644 mips-lib/src/gui_egui/mod.rs create mode 100644 mips-lib/src/gui_egui/sz_extend.rs rename mips/src/gui_egui/mod.rs => mips-lib/src/lib.rs (51%) create mode 100644 mips-simple/Cargo.toml create mode 100644 mips-simple/src/main.rs delete mode 100644 mips/Cargo.toml delete mode 100644 mips/README.md delete mode 100644 mips/examples/mips.rs delete mode 100644 mips/examples/reg_file.rs delete mode 100644 mips/src/components/instr_mem.rs delete mode 100644 mips/src/components/mod.rs delete mode 100644 mips/src/components/reg_file.rs delete mode 100644 mips/src/gui_egui/components/instr_mem.rs delete mode 100644 mips/src/gui_egui/components/mod.rs delete mode 100644 mips/src/gui_egui/components/reg_file.rs delete mode 100644 mips/src/gui_vizia/components/instr_mem.rs delete mode 100644 mips/src/gui_vizia/components/mod.rs delete mode 100644 mips/src/gui_vizia/components/reg_file.rs delete mode 100644 mips/src/gui_vizia/mod.rs delete mode 100644 mips/src/lib.rs delete mode 100644 mips/src/main.rs delete mode 100644 mips/tests/component_tests.rs diff --git a/Cargo.toml b/Cargo.toml index 998c3de0..056b2b51 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [workspace] -members = ["mips", "riscv"] +members = [ "mips-lib","mips-simple", "riscv"] [dependencies] MIPS_disassembly = "0.1.2" diff --git a/mips-lib/Cargo.toml b/mips-lib/Cargo.toml new file mode 100644 index 00000000..083e9d89 --- /dev/null +++ b/mips-lib/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "mips-lib" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.72" +clap = { version = "4.3.15", features = ["derive"] } +elf = "0.7.4" +fern = "0.6.2" +log = "0.4.19" +num_enum = "0.6.1" +petgraph = "0.6.3" +rfd = "0.11.4" +serde = { version = "1.0.171", features = ["rc"] } +serde_derive = "1.0.171" +serde_json = "1.0.103" +typetag = "0.2.10" +egui = {version = "0.28.0"} +[dependencies.syncrim] +path = "../" +default-features = false + +[features] +default = ["gui-egui"] + +components = ["syncrim/components"] +gui-vizia = ["syncrim/gui-vizia"] +gui-egui = ["syncrim/gui-egui"] diff --git a/mips-lib/src/components/full_adder.rs b/mips-lib/src/components/full_adder.rs new file mode 100644 index 00000000..b8eb9254 --- /dev/null +++ b/mips-lib/src/components/full_adder.rs @@ -0,0 +1,309 @@ +// use std::fmt::Alignment; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::rc::Rc; +#[cfg(feature = "gui-egui")] +use syncrim::common::EguiComponent; +use syncrim::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, +}; + +pub const FULL_ADD_A_IN_ID: &str = "full_add_a_in"; +pub const FULL_ADD_B_IN_ID: &str = "full_add_b_in"; +pub const FULL_ADD_OP_IN_ID: &str = "full_add_op_in"; +pub const FULL_ADD_OUT_ID: &str = "alu_out"; +pub const FULL_ADD_OVERFLOW_OUT_ID: &str = "alu_overflow_out"; + +pub mod alu_op { + pub const ADD: u32 = 0; + pub const ADDU: u32 = 1; + pub const SUB: u32 = 2; + pub const SUBU: u32 = 3; + pub const AND: u32 = 4; + pub const OR: u32 = 5; + pub const XOR: u32 = 6; + pub const NOR: u32 = 7; + pub const SLT: u32 = 8; + pub const SLTU: u32 = 9; + pub const SLL: u32 = 10; + pub const SRL: u32 = 11; + pub const SRA: u32 = 12; + pub const LUI: u32 = 13; +} + +#[derive(Serialize, Deserialize, Clone)] +pub struct FullAdd { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) a_in: Input, + pub(crate) b_in: Input, + pub(crate) op_in: Input, +} + +#[typetag::serde] +impl Component for FullAdd { + fn to_(&self) { + trace!("full_adder"); + } + #[cfg(feature = "gui-egui")] + fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { + let dummy_input = Input::new("dummy", "out"); + Box::new(Rc::new(FullAdd { + id: "dummy".to_string(), + pos: (0.0, 0.0), + a_in: dummy_input.clone(), + b_in: dummy_input.clone(), + op_in: dummy_input.clone(), + })) + } + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![ + &InputPort { + port_id: FULL_ADD_A_IN_ID.to_string(), + input: self.a_in.clone(), + }, + &InputPort { + port_id: FULL_ADD_B_IN_ID.to_string(), + input: self.b_in.clone(), + }, + &InputPort { + port_id: FULL_ADD_OP_IN_ID.to_string(), + input: self.op_in.clone(), + }, + ], + OutputType::Combinatorial, + vec![FULL_ADD_OUT_ID, FULL_ADD_OVERFLOW_OUT_ID], + ), + ) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + FULL_ADD_A_IN_ID => self.a_in = new_input, + FULL_ADD_B_IN_ID => self.b_in = new_input, + FULL_ADD_OP_IN_ID => self.op_in = new_input, + _ => {} + } + } + + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get input values + let a: u32 = simulator.get_input_value(&self.a_in).try_into().unwrap(); + let b: u32 = simulator.get_input_value(&self.b_in).try_into().unwrap(); + let op: u32 = simulator.get_input_value(&self.op_in).try_into().unwrap(); + + let output: u32; + let mut overflow: u32 = 0; + + match op { + alu_op::ADD => { + // output = a.wrapping_add(b); + + let tmp = (a as i32).checked_add(b as i32); + overflow = match tmp { + Some(val) => { + output = val as u32; + 0 + } + None => { + output = a.wrapping_add(b); + 1 + } + }; + } + alu_op::ADDU => { + output = a.wrapping_add(b); + } + alu_op::SUB => { + let tmp = (a as i32).checked_sub(b as i32); + overflow = match tmp { + Some(val) => { + output = val as u32; + 0 + } + None => { + output = a.wrapping_sub(b); + 1 + } + } + } + alu_op::SUBU => { + output = a.wrapping_sub(b); + } + alu_op::AND => { + output = a & b; + } + alu_op::OR => { + output = a | b; + } + alu_op::XOR => { + output = a ^ b; + } + alu_op::NOR => { + output = !(a | b); + } + alu_op::SLT => { + output = ((a as i32) < (b as i32)) as u32; + } + alu_op::SLTU => { + output = (a < b) as u32; + } + alu_op::SLL => { + output = a << b; + } + alu_op::SRL => { + output = a >> b; + } + alu_op::SRA => { + output = ((a as i32) >> b) as u32; + } + alu_op::LUI => { + output = (a & 0x0000_ffff) | (b << 16); + } + _ => { + return Err(Condition::Error( + "undef alu operation or unimplemented instruction".to_string(), + )); + } + } + simulator.set_out_value(&self.id, FULL_ADD_OUT_ID, SignalValue::Data(output)); + simulator.set_out_value( + &self.id, + FULL_ADD_OVERFLOW_OUT_ID, + SignalValue::Data(overflow), + ); + Ok(()) + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl FullAdd { + pub fn new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input, op_in: Input) -> Self { + FullAdd { + id: id.to_string(), + pos, + a_in, + b_in, + op_in, + } + } + + pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input, op_in: Input) -> Rc { + Rc::new(FullAdd::new(id, pos, a_in, b_in, op_in)) + } +} +#[cfg(test)] +mod test { + use super::*; + + use crate::{ + common::{ComponentStore, Input, Simulator}, + components::ProbeOut, + }; + use std::rc::Rc; + + #[test] + fn test_some_alu_op() { + let cs = ComponentStore { + store: vec![ + Rc::new(ProbeOut::new("op")), + Rc::new(ProbeOut::new("a")), + Rc::new(ProbeOut::new("b")), + FullAdd::rc_new( + "ALU", + (0.0, 0.0), + Input::new("a", "out"), + Input::new("b", "out"), + Input::new("op", "out"), + ), + ], + }; + let mut simulator = Simulator::new(cs).unwrap(); + + assert_eq!(simulator.cycle, 1); + + // outputs + let alu_val = &Input::new("ALU", "out"); + + // reset + assert_eq!(simulator.get_input_value(alu_val), (0 + 0).into()); + + println!(""); + simulator.set_out_value("a", "out", 42); + simulator.set_out_value("b", "out", 1337); + simulator.set_out_value("op", "out", alu_op::ADD); + println!("sim_state {:?}", simulator.sim_state); + println!(""); + simulator.clock(); + println!("sim_state {:?}", simulator.sim_state); + assert_eq!(simulator.cycle, 2); + assert_eq!( + simulator.get_input_value(alu_val), + (42 + 1337).into(), + "testing add (1)" + ); + + println!(""); + simulator.set_out_value("a", "out", -100i32 as u32); + simulator.set_out_value("b", "out", 1337); + simulator.set_out_value("op", "out", alu_op::ADD); + println!("sim_state {:?}", simulator.sim_state); + println!(""); + simulator.clock(); + println!("sim_state {:?}", simulator.sim_state); + assert_eq!( + simulator.get_input_value(alu_val), + (1337 - 100).into(), + "testing add (2)" + ); + + println!(""); + simulator.set_out_value("a", "out", -100i32 as u32); + simulator.set_out_value("b", "out", 1337); + simulator.set_out_value("op", "out", alu_op::SUB); + println!("sim_state {:?}", simulator.sim_state); + println!(""); + simulator.clock(); + println!("sim_state {:?}", simulator.sim_state); + assert_eq!( + simulator.get_input_value(alu_val), + ((-100i32 - 1337) as u32).into(), + "testing sub" + ); + + println!(""); + simulator.set_out_value("a", "out", -100i32 as u32); + simulator.set_out_value("b", "out", 1337); + simulator.set_out_value("op", "out", alu_op::SLT); + println!("sim_state {:?}", simulator.sim_state); + println!(""); + simulator.clock(); + println!("sim_state {:?}", simulator.sim_state); + assert_eq!( + simulator.get_input_value(alu_val), + true.into(), + "testing SLT" + ); + + println!(""); + simulator.set_out_value("a", "out", -100i32 as u32); + simulator.set_out_value("b", "out", 1337); + simulator.set_out_value("op", "out", alu_op::SLTU); + println!("sim_state {:?}", simulator.sim_state); + println!(""); + simulator.clock(); + println!("sim_state {:?}", simulator.sim_state); + assert_eq!( + simulator.get_input_value(alu_val), + false.into(), + "testing SLT" + ); + } +} diff --git a/mips-lib/src/components/mips_control_unit.rs b/mips-lib/src/components/mips_control_unit.rs new file mode 100644 index 00000000..42618aa4 --- /dev/null +++ b/mips-lib/src/components/mips_control_unit.rs @@ -0,0 +1,1011 @@ +// use std::fmt::Alignment; +use log::trace; +use serde::{Deserialize, Serialize}; +use std::{any::Any, rc::Rc}; +#[cfg(feature = "gui-egui")] +use syncrim::common::EguiComponent; +use syncrim::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, +}; + +use super::alu_op; // values used in communication to the alu +use super::data_op; // values used in communication with the data memory +/// The input and output felid ids for the control unit +pub mod cntr_field { + + pub const INSTR_IN: &str = "control_unit_instr_in"; + + /// const REG_DEST_RT: u32 = 0; + /// const REG_DEST_RD: u32 = 1; + /// const REG_DEST_31: u32 = 2; + pub const REG_DEST_OUT: &str = "reg_dest"; + + /// 0 or 1 + pub const REG_WRITE_ENABLE_OUT: &str = "reg_write_enable"; + + /// const WRITE_REG_SRC_ALU:u32 = 0; + /// const WRITE_REG_SRC_MEM:u32 = 1; + pub const REG_WRITE_SRC_OUT: &str = "reg_write_src"; + + /// se module full_adder:alu_op + pub const ALU_OP_OUT: &str = "alu_op"; + + /// const ALU_SRC_A_OP:u32 = 0; + /// const ALU_SRC_A_RS:u32 = 1; + /// const ALU_SRC_A_ZERO:u32 = 3; + pub const ALU_SRC_A_OUT: &str = "alu_src_a"; + + /// const ALU_SRC_B_RT:u32 = 0; + /// const ALU_SRC_B_PC:u32 = 1; + /// const ALU_SRC_B_IMM:u32 = 2; + pub const ALU_SRC_B_OUT: &str = "alu_src_b"; + + // const EXTEND_ZERO:u32 = 0; + // const EXTEND_SIGNED:u32 = 1; + pub const EXTEND_SELECT_OUT: &str = "extend_select"; + + // 0 or 1 + pub const MEM_WRITE_ENABLE_OUT: &str = "mem_write_enable"; + + // 0 or 1, used for co-processor address stuff + pub const BRANCH_INTERRUPT_OUT: &str = "branch_interrupt"; + + // pub const CP0_MFC0 = 0; + // pub const CP0_MTC0 = 1; + // pub const CP0_RFE = 2; + // pub const CP0_SYSCALL = 3; + pub const CP0_OUT: &str = "cp0_out"; + + pub const MMU_OUT: &str = "mmu_out"; + + //TODO + // Opcode is passed to branch unit wich is responsible to controll branch logic + // pub const BRANCH_TYPE_OUT: &str = "branch"; + + //TODO + // NOTE no mem mode, decided to pass opcode to data mem instead, + // might change when LWL/LWR is implemented along with the load/store controller + pub const MEM_MODE_OUT: &str = "mem_mode"; +} + +const NOP: u32 = 0; +const OP_0: u32 = 0; + +const FUNCT_SLL: u32 = 0; +const FUNCT_SRL: u32 = 0b00_0010; +const FUNCT_SRA: u32 = 0b00_0011; +const FUNCT_SLLV: u32 = 0b00_0100; +const FUNCT_SRLV: u32 = 0b00_0110; +const FUNCT_SRAV: u32 = 0b00_111; +const FUNCT_JR: u32 = 0b00_1000; +const FUNCT_JALR: u32 = 0b00_1001; +const SYSCALL: u32 = 0b00_1100; +const FUNCT_ADD: u32 = 0b10_0000; +const FUNCT_ADDU: u32 = 0b10_0001; +const FUNCT_SUB: u32 = 0b10_0010; +const FUNCT_SUBU: u32 = 0b10_0011; +const FUNCT_AND: u32 = 0b10_0100; +const FUNCT_OR: u32 = 0b10_0101; +const FUNCT_XOR: u32 = 0b10_0110; +const FUNCT_NOR: u32 = 0b10_0111; +const FUNCT_SLT: u32 = 0b10_1010; +const FUNCT_SLTU: u32 = 0b10_1011; + +const OP_1: u32 = 1; + +const B_FUNCT_BLTZ: u32 = 0; +const B_FUNCT_BGEZ: u32 = 1; +const B_FUNCT_BLTZAL: u32 = 0b1_0000; +const B_FUNCT_BGEZAL: u32 = 0b1_0001; + +const OP_J: u32 = 0b00_0010; +const OP_JAL: u32 = 0b00_0011; +const OP_BEQ: u32 = 0b00_0100; +const OP_BNE: u32 = 0b00_0101; +const OP_BLEZ: u32 = 0b00_0110; +const OP_BGTZ: u32 = 0b00_0111; + +const OP_ADDI: u32 = 0b00_1000; +const OP_ADDIU: u32 = 0b00_1001; +const OP_SLTI: u32 = 0b00_1010; +const OP_SLTIU: u32 = 0b00_1011; +const OP_ANDI: u32 = 0b00_1100; +const OP_ORI: u32 = 0b00_1101; +const OP_XORI: u32 = 0b00_1110; +const OP_LUI: u32 = 0b00_1111; + +const OP_CP0: u32 = 0b01_0000; +const CP0_FUNCT_MFC0: u32 = 0; +const CP0_FUNCT_MTF0: u32 = 0b0_0100; +const CP0_FUNCT_SPECIAL: u32 = 0b1_0000; +const CP0_FUNCT_SPECIAL_: u32 = 0b1_0000; + +const OP_LB: u32 = 0b10_0000; +const OP_LH: u32 = 0b10_0001; +const OP_LWL: u32 = 0b10_0010; +const OP_LW: u32 = 0b10_0011; +const OP_LBU: u32 = 0b10_0100; +const OP_LHU: u32 = 0b10_0101; +const OP_LWR: u32 = 0b10_0110; + +const OP_SB: u32 = 0b10_1000; +const OP_SH: u32 = 0b10_1001; +const OP_SWL: u32 = 0b10_1010; +const OP_SW: u32 = 0b10_1011; +const OP_SWR: u32 = 0b10_1110; + +/// module used to get what u32 represent. Used for communication between components +pub mod cntr_unit_signals { + pub const REG_DEST_RT: u32 = 0; + pub const REG_DEST_RD: u32 = 1; + pub const REG_DEST_31: u32 = 2; + + pub const REG_WRITE_DISABLE: u32 = 0; + pub const REG_WRITE_ENABLE: u32 = 1; + + pub const MEM_WRITE_DISABLE: u32 = 0; + pub const MEM_WRITE_ENABLE: u32 = 1; + + pub const ALU_SRC_A_SHAMT: u32 = 0; + pub const ALU_SRC_A_RS: u32 = 1; + pub const ALU_SRC_A_ZERO: u32 = 2; + + pub const ALU_SRC_B_RT: u32 = 0; + pub const ALU_SRC_B_PC: u32 = 1; + pub const ALU_SRC_B_IMM: u32 = 2; + + pub const WRITE_REG_SRC_ALU: u32 = 0; + pub const WRITE_REG_SRC_MEM: u32 = 1; + + pub const NO_BRANCH_INTERRUPT: u32 = 0; + pub const BRANCH_INTERRUPT: u32 = 1; + + pub const EXTEND_ZERO: u32 = 0; + pub const EXTEND_SIGNED: u32 = 1; + + pub const CP0_MFC0: u32 = 0; + pub const CP0_MTC0: u32 = 1; + pub const CP0_RFE: u32 = 2; + pub const CP0_SYSCALL: u32 = 3; + + pub const MMU_NORMAL: u32 = 0; + pub const MMU_CP0: u32 = 1; + pub const MMU_NOP: u32 = 2; + + // Note, it was decided to pass opcode to data mem to handle load + // and store instructions there +} + +#[derive(Serialize, Deserialize, Clone)] +pub struct ControlUnit { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) a_in: Input, +} +#[typetag::serde] +impl Component for ControlUnit { + fn to_(&self) { + trace!("control_unit"); + } + #[cfg(feature = "gui-egui")] + fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { + let dummy_input = Input::new("dummy", "out"); + Box::new(Rc::new(ControlUnit { + id: "dummy".to_string(), + pos: (0.0, 0.0), + a_in: dummy_input.clone(), + })) + } + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![&InputPort { + port_id: cntr_field::INSTR_IN.to_string(), + input: self.a_in.clone(), + }], + OutputType::Combinatorial, + vec![ + cntr_field::REG_DEST_OUT, + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_field::REG_WRITE_SRC_OUT, + cntr_field::ALU_OP_OUT, + cntr_field::ALU_SRC_A_OUT, + cntr_field::ALU_SRC_B_OUT, + cntr_field::EXTEND_SELECT_OUT, + cntr_field::MEM_WRITE_ENABLE_OUT, + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_field::CP0_OUT, + cntr_field::MMU_OUT, + cntr_field::MEM_MODE_OUT, + ], + ), + ) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + cntr_field::INSTR_IN => self.a_in = new_input, + _ => {} + } + } + + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + let instr_in: u32 = simulator.get_input_value(&self.a_in).try_into().unwrap(); + + let op_code: u32 = (&instr_in >> 26) & 0x0000_003f; + + /// Sets the given field to the given value + macro_rules! set { + ($field:expr, $signal_val:expr) => { + simulator.set_out_value(&self.id, $field, SignalValue::Data($signal_val)) + }; + } + + /// sets the relevant fields for an i instruction + /// OP rt rs imm + /// ALU_OP and EXTEND ned to be set separately + macro_rules! set_i_instr { + () => { + // set target reg to be RT and read from alu + set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_RT); + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_ENABLE + ); + set!( + cntr_field::REG_WRITE_SRC_OUT, + cntr_unit_signals::WRITE_REG_SRC_ALU + ); + + // set alu src to be RS and imm + set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_RS); + set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_IMM); + }; + } + + /// sets the relevant fields for an load operation + /// reg_src = mem + /// reg_dest = rt + /// addu rs (imm sign extended) + /// MEM MODE needs to be set separately + macro_rules! set_load_instr { + () => { + // set target reg to be RT and read from mem + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_ENABLE + ); + set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_RT); + set!( + cntr_field::REG_WRITE_SRC_OUT, + cntr_unit_signals::WRITE_REG_SRC_MEM + ); + + // set alu to be addu with rs and signed imm + set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_RS); + set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_IMM); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_SIGNED + ); + }; + } + macro_rules! set_store_instr { + () => { + // SET reg_write to disabled nad mem write to enable + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_DISABLE + ); + set!( + cntr_field::MEM_WRITE_ENABLE_OUT, + cntr_unit_signals::MEM_WRITE_ENABLE + ); + + // set alu to be addu with rs and signed imm + set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_RS); + set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_IMM); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_SIGNED + ); + }; + } + + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_DISABLE + ); + set!( + cntr_field::MEM_WRITE_ENABLE_OUT, + cntr_unit_signals::MEM_WRITE_DISABLE + ); + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::NO_BRANCH_INTERRUPT + ); + set!(cntr_field::MEM_MODE_OUT, data_op::NO_OP); + //TODO an idea would be to init all variables + // let alu_src_a : Signal; + // this would make the compiler force us to populate all paths so to not let any signal be undefined + // It would be more code, but would hopefully be more "secure" as it would stop us from forgetting a value + // another idea is to set all signals to uninitialized or dont care for better debugging + + // match the opcode + match op_code { + OP_0 => { + let funct: u32 = &instr_in & 0x0000_003f; + + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_ENABLE + ); // overwritten by JR and SYSCALL to disabled + + set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_RD); // overwritten by JALR to REG_DEST_31 + set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_RS); // overwritten by JALR, SRA, SRL to shamt or zero + set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_RT); // overwritten by JALR to PC + set!( + cntr_field::REG_WRITE_SRC_OUT, + cntr_unit_signals::WRITE_REG_SRC_ALU + ); + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::NO_BRANCH_INTERRUPT + ); // overiden by jr and jalr + + match funct { + FUNCT_SLL => { + set!( + cntr_field::ALU_SRC_A_OUT, + cntr_unit_signals::ALU_SRC_A_SHAMT + ); + set!(cntr_field::ALU_OP_OUT, alu_op::SLL); + Ok(()) + } + FUNCT_SRL => { + set!( + cntr_field::ALU_SRC_A_OUT, + cntr_unit_signals::ALU_SRC_A_SHAMT + ); + set!(cntr_field::ALU_OP_OUT, alu_op::SRL); + Ok(()) + } + FUNCT_SRA => { + set!( + cntr_field::ALU_SRC_A_OUT, + cntr_unit_signals::ALU_SRC_A_SHAMT + ); + set!(cntr_field::ALU_OP_OUT, alu_op::SRA); + Ok(()) + } + FUNCT_SLLV => { + set!(cntr_field::ALU_OP_OUT, alu_op::SLL); + Ok(()) + } + FUNCT_SRLV => { + set!(cntr_field::ALU_OP_OUT, alu_op::SRL); + Ok(()) + } + FUNCT_SRAV => { + set!(cntr_field::ALU_OP_OUT, alu_op::SRL); + Ok(()) + } + FUNCT_JR => { + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::BRANCH_INTERRUPT + ); + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_DISABLE + ); + Ok(()) + } + FUNCT_JALR => { + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::BRANCH_INTERRUPT + ); + set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_RD); // this is different from syncsim as there its defined as 31, but that dosen't match mips documentation; + set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_ZERO); + set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_PC); + set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + Ok(()) + } + SYSCALL => { + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_DISABLE + ); + set!(cntr_field::CP0_OUT, cntr_unit_signals::CP0_SYSCALL); + Ok(()) + } + FUNCT_ADD => { + set!(cntr_field::ALU_OP_OUT, alu_op::ADD); + Ok(()) + } + FUNCT_ADDU => { + set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + Ok(()) + } + FUNCT_SUB => { + set!(cntr_field::ALU_OP_OUT, alu_op::SUB); + Ok(()) + } + FUNCT_SUBU => { + set!(cntr_field::ALU_OP_OUT, alu_op::SUBU); + Ok(()) + } + FUNCT_AND => { + set!(cntr_field::ALU_OP_OUT, alu_op::AND); + Ok(()) + } + FUNCT_OR => { + set!(cntr_field::ALU_OP_OUT, alu_op::OR); + Ok(()) + } + FUNCT_XOR => { + set!(cntr_field::ALU_OP_OUT, alu_op::XOR); + Ok(()) + } + FUNCT_NOR => { + set!(cntr_field::ALU_OP_OUT, alu_op::NOR); + Ok(()) + } + FUNCT_SLT => { + set!(cntr_field::ALU_OP_OUT, alu_op::SLT); + Ok(()) + } + FUNCT_SLTU => { + set!(cntr_field::ALU_OP_OUT, alu_op::SLTU); + Ok(()) + } + _ => Err(Condition::Error(format!( + "unknown funct {:#08b} for opcode 0b000000", + funct + ))), + } + } + OP_1 => { + // branch stuff, BGEZ BGEZAL BLTZ BLTZAL, + // Note many branch and jump instructions are actually pseudo instructions and will be compiled to others + // BAL => BGEZAL r0 offset + let tmp: u32 = simulator.get_input_signal(&self.a_in).try_into().unwrap(); + let b_funct: u32 = (tmp >> 16) & 0b11111; + + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::BRANCH_INTERRUPT + ); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_SIGNED + ); + match b_funct { + B_FUNCT_BGEZ | B_FUNCT_BLTZ => Ok(()), + B_FUNCT_BGEZAL | B_FUNCT_BLTZAL => { + // save pc to reg + set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_31); + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_ENABLE + ); + set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_ZERO); + set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_PC); + set!( + cntr_field::REG_WRITE_SRC_OUT, + cntr_unit_signals::WRITE_REG_SRC_ALU + ); + Ok(()) + } + _ => Err(Condition::Error(format!( + "unknown funct {:#07b} for opcode 0b000001", + b_funct + ))), + } + } + OP_J => { + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::BRANCH_INTERRUPT + ); + Ok(()) + } + OP_JAL => { + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::BRANCH_INTERRUPT + ); + set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_31); + set!( + cntr_field::REG_WRITE_ENABLE_OUT, + cntr_unit_signals::REG_WRITE_ENABLE + ); + set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_ZERO); + set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_PC); + set!( + cntr_field::REG_WRITE_SRC_OUT, + cntr_unit_signals::WRITE_REG_SRC_ALU + ); + Ok(()) + } + OP_BEQ | OP_BNE | OP_BLEZ | OP_BGTZ => { + set!( + cntr_field::BRANCH_INTERRUPT_OUT, + cntr_unit_signals::BRANCH_INTERRUPT + ); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_SIGNED + ); + Ok(()) + } + OP_ADDI => { + set_i_instr!(); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_SIGNED + ); + set!(cntr_field::ALU_OP_OUT, alu_op::ADD); + Ok(()) + } + OP_ADDIU => { + set_i_instr!(); + set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + Ok(()) + } + OP_SLTI => { + set_i_instr!(); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_SIGNED + ); + set!(cntr_field::ALU_OP_OUT, alu_op::SLT); + Ok(()) + } + OP_SLTIU => { + set_i_instr!(); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_ZERO + ); + set!(cntr_field::ALU_OP_OUT, alu_op::SLTU); + Ok(()) + } + OP_ANDI => { + set_i_instr!(); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_ZERO + ); + set!(cntr_field::ALU_OP_OUT, alu_op::AND); + Ok(()) + } + OP_ORI => { + set_i_instr!(); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_ZERO + ); + set!(cntr_field::ALU_OP_OUT, alu_op::OR); + Ok(()) + } + OP_XORI => { + set_i_instr!(); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_ZERO + ); + set!(cntr_field::ALU_OP_OUT, alu_op::XOR); + Ok(()) + } + OP_LUI => { + set_i_instr!(); + set!( + cntr_field::EXTEND_SELECT_OUT, + cntr_unit_signals::EXTEND_ZERO + ); + set!(cntr_field::ALU_OP_OUT, alu_op::LUI); + Ok(()) + } + OP_CP0 => { + // let cp0_funct:u32 = (&instr_in >> 21) & 0b11111; + // match cp0_funct { + // CP0_FUNCT_MFC0 =>{ + // set!(cntr_field::REG_DEST_OUT,cntr_unit_signals::REG_DEST_RT); + // set!(cntr_field::REG_WRITE_ENABLE_OUT, cntr_unit_signals::REG_WRITE_ENABLE); + + // //TODO no idea why alu would be required for this operation and cant find any path in syncsim, + // // but following blindly. If time permits figure out why and change + // set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); + // set!(cntr_field::ALU_SRC_A_OUT,cntr_unit_signals::ALU_SRC_A_SHAMT); + // set!(cntr_field::ALU_SRC_B_OUT,cntr_unit_signals::ALU_SRC_B_IMM); + // todo!("implement memory mode to complete MFC0") + + // } + // _ => { + // Err(Condition::Error(format!("unknown funct {:#07b}for opcode {:#08b} CP0", cp0_funct, OP_CP0))) + // } + // } + Err(Condition::Error(format!( + "CP0 instructions not yet implemented" + ))) + } + //TODO use mem_mode, now it assumed data_mem uses opcode to determine that itself + OP_LB => { + set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_BYTE); + set_load_instr!(); + Ok(()) + } + OP_LBU => { + set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_BYTE_U); + set_load_instr!(); + Ok(()) + } + OP_LH => { + set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_HALF); + set_load_instr!(); + Ok(()) + } + OP_LHU => { + set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_HALF_U); + set_load_instr!(); + Ok(()) + } + OP_LW => { + set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_WORD); + set_load_instr!(); + Ok(()) + } + + OP_SB => { + set!(cntr_field::MEM_MODE_OUT, data_op::STORE_BYTE); + set_store_instr!(); + Ok(()) + } + OP_SH => { + set!(cntr_field::MEM_MODE_OUT, data_op::STORE_HALF); + set_store_instr!(); + Ok(()) + } + OP_SW => { + set!(cntr_field::MEM_MODE_OUT, data_op::STORE_WORD); + set_store_instr!(); + Ok(()) + } + + OP_LWL | OP_LWR | OP_SWL | OP_SWR => Err(Condition::Error( + "LWL, LWR, SWL and SWR are not implemented".to_string(), + )), + + _ => Err(Condition::Error(format!("Unknown opcode {:#08b}", op_code))), + } + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl ControlUnit { + pub fn new(id: &str, pos: (f32, f32), a_in: Input) -> Self { + ControlUnit { + id: id.to_string(), + pos, + a_in, + } + } + + pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input) -> Rc { + Rc::new(ControlUnit::new(id, pos, a_in)) + } +} +#[cfg(test)] +mod test { + use crate::{common::ComponentStore, components::ProbeOut}; + + use super::*; + + fn setup_simulator() -> Simulator { + let cs = ComponentStore { + store: vec![ + Rc::new(ProbeOut::new("instr")), + ControlUnit::rc_new("cntr", (0.0, 0.0), Input::new("instr", "out")), + ], + }; + Simulator::new(cs).unwrap() + } + /// This tests + /// - beq t3 t0 7 => 000100 01011 01000 0000000000000111 + /// - xori $t6,$s4,32 => 001110 10100 01110 0000000000100000 + /// - sub $t0,$a0,$t0 => 000000 00100 01000 01000 00000 100010 + /// - lh $a1,14($s1) => 100001 10001 00101 0000000000001110 + /// - jal => 000011 10101010101010101010101010 + /// - jalr r10 r18 => 000000_10010_00000_01010_00000_001001 + #[test] + fn test_random_instrs() { + let mut sim = setup_simulator(); + + assert_eq!(sim.cycle, 1); + + println!("testing beq t3 t0 7 => 000100 01011 01000 0000000000000111"); + sim.set_out_value("instr", "out", 0b000100_01011_01000_0000000000000111); + println!("clock sim"); + sim.clock(); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), + cntr_unit_signals::BRANCH_INTERRUPT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), + cntr_unit_signals::REG_WRITE_DISABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), + cntr_unit_signals::MEM_WRITE_DISABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::EXTEND_SELECT_OUT)), + cntr_unit_signals::EXTEND_SIGNED.into() + ); + + println!("testing xori $t6,$s4,32 => 001110 10100 01110 0000000000100000"); + sim.set_out_value("instr", "out", 0b001110_10100_01110_0000000000100000); + println!("clock sim"); + sim.clock(); + // no branch or mem write + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), + cntr_unit_signals::NO_BRANCH_INTERRUPT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), + cntr_unit_signals::MEM_WRITE_DISABLE.into() + ); + + // reg write, src alu and reg_dest rt, since rd is occupied by imm + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), + cntr_unit_signals::REG_WRITE_ENABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), + cntr_unit_signals::WRITE_REG_SRC_ALU.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), + cntr_unit_signals::REG_DEST_RT.into() + ); + + // ALU xor rs and imm zero extend + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::EXTEND_SELECT_OUT)), + cntr_unit_signals::EXTEND_ZERO.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), + cntr_unit_signals::ALU_SRC_A_RS.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), + cntr_unit_signals::ALU_SRC_B_IMM.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), + alu_op::XOR.into() + ); + + print!("testing sub $t0,$a0,$t0 => 000000 00100 01000 01000 00000 100010"); + sim.set_out_value("instr", "out", 0b000000_00100_01000_01000_00000_100010); + println!("clock sim"); + sim.clock(); + // no branch or mem write + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), + cntr_unit_signals::NO_BRANCH_INTERRUPT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), + cntr_unit_signals::MEM_WRITE_DISABLE.into() + ); + + // reg write, src alu and reg_dest rd + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), + cntr_unit_signals::REG_WRITE_ENABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), + cntr_unit_signals::WRITE_REG_SRC_ALU.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), + cntr_unit_signals::REG_DEST_RD.into(), + ); + + // ALU sub rs and rt + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), + cntr_unit_signals::ALU_SRC_A_RS.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), + cntr_unit_signals::ALU_SRC_B_RT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), + alu_op::SUB.into() + ); + + print!("testing lh $a1,14($s1) => 100001 10001 00101 0000000000001110"); + sim.set_out_value("instr", "out", 0b100001_10001_00101_0000000000001110); + println!("clock sim"); + sim.clock(); + // reg write, no branch, no mem write + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), + cntr_unit_signals::NO_BRANCH_INTERRUPT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), + cntr_unit_signals::MEM_WRITE_DISABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), + cntr_unit_signals::REG_WRITE_ENABLE.into() + ); + + // reg dst rt, reg src mem + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), + cntr_unit_signals::WRITE_REG_SRC_MEM.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), + cntr_unit_signals::REG_DEST_RT.into() + ); + + // ADDU rs imm (signed) + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::EXTEND_SELECT_OUT)), + cntr_unit_signals::EXTEND_SIGNED.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), + cntr_unit_signals::ALU_SRC_A_RS.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), + cntr_unit_signals::ALU_SRC_B_IMM.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), + alu_op::ADDU.into() + ); + + println!("testing SW $r2 4($r3) => 101011 00011 00010 0000_0000_0000_0100"); + sim.set_out_value("instr", "out", 0b101011_00011_00010_0000_0000_0000_0100); + println!("clock sim"); + sim.clock(); + // no reg write, no branch, mem write + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), + cntr_unit_signals::NO_BRANCH_INTERRUPT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), + cntr_unit_signals::MEM_WRITE_ENABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), + cntr_unit_signals::REG_WRITE_DISABLE.into() + ); + + // ADDU rs imm (signed) + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::EXTEND_SELECT_OUT)), + cntr_unit_signals::EXTEND_SIGNED.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), + cntr_unit_signals::ALU_SRC_A_RS.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), + cntr_unit_signals::ALU_SRC_B_IMM.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), + alu_op::ADDU.into() + ); + + println!("testing jal => 000011 10101010101010101010101010 "); + sim.set_out_value("instr", "out", 0b000011_10101010101010101010101010); + println!("clock sim"); + sim.clock(); + // reg write, branch, no mem write + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), + cntr_unit_signals::BRANCH_INTERRUPT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), + cntr_unit_signals::MEM_WRITE_DISABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), + cntr_unit_signals::REG_WRITE_ENABLE.into() + ); + + // ALU zero + pc + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), + cntr_unit_signals::ALU_SRC_A_ZERO.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), + cntr_unit_signals::ALU_SRC_B_PC.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), + alu_op::ADDU.into() + ); + + // reg dst 31, reg src alu + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), + cntr_unit_signals::WRITE_REG_SRC_ALU.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), + cntr_unit_signals::REG_DEST_31.into() + ); + + println!("testing jalr r10 r18 => 000000_10010_00000_01010_00000_001001"); + sim.set_out_value("instr", "out", 0b000000_10010_00000_01010_00000_001001); + println!("clock sim"); + sim.clock(); + // reg write, branch, no mem write + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), + cntr_unit_signals::BRANCH_INTERRUPT.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), + cntr_unit_signals::MEM_WRITE_DISABLE.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), + cntr_unit_signals::REG_WRITE_ENABLE.into() + ); + + // ALU zero + pc + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), + cntr_unit_signals::ALU_SRC_A_ZERO.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), + cntr_unit_signals::ALU_SRC_B_PC.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), + alu_op::ADDU.into() + ); + + // reg dst rd, reg src alu + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), + cntr_unit_signals::WRITE_REG_SRC_ALU.into() + ); + assert_eq!( + sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), + cntr_unit_signals::REG_DEST_RD.into() + ); + } +} diff --git a/mips-lib/src/components/mips_dm.rs b/mips-lib/src/components/mips_dm.rs new file mode 100644 index 00000000..7e853aed --- /dev/null +++ b/mips-lib/src/components/mips_dm.rs @@ -0,0 +1,373 @@ +use core::cell::RefCell; +use log::*; +use serde::{Deserialize, Serialize}; +use std::{collections::HashMap, rc::Rc}; +#[cfg(feature = "gui-egui")] +use syncrim::common::EguiComponent; +use syncrim::{ + common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}, + gui_egui::mips_mem_view_window::MemViewWindow, +}; + +use syncrim::components::{ + mips_mem_struct::{MemOpSize, MemWriteReturn, MipsMem}, + RegFile, +}; + +pub mod data_op { + pub const NO_OP: u32 = 0; + pub const LOAD_BYTE: u32 = 1; + pub const LOAD_BYTE_U: u32 = 2; + pub const LOAD_HALF: u32 = 3; + pub const LOAD_HALF_U: u32 = 4; + pub const LOAD_WORD: u32 = 5; + + pub const STORE_BYTE: u32 = 6; + pub const STORE_HALF: u32 = 7; + pub const STORE_WORD: u32 = 8; +} + +pub const DATA_MEM_A_IN_ID: &str = "data_mem_address_in"; +pub const DATA_MEM_OP_IN_ID: &str = "data_mem_op_in"; +pub const DATA_MEM_WRITE_ENABLE_ID: &str = "data_mem_write_enable"; +pub const DATA_MEM_WD_IN_ID: &str = "data_mem_write_data_in"; + +pub const DATA_MEM_READ_DATA_OUT_ID: &str = "data_out"; + +#[derive(Serialize, Deserialize, Clone)] +pub struct DataMem { + pub id: String, + pub pos: (f32, f32), + pub address_input: Input, + pub data_input: Input, + pub op_input: Input, + pub write_enable_input: Input, + // FIXME should probably not skip mem rc here, since we still need them to point to the same MipsMem + #[serde(skip)] + pub mem: Rc>, + pub mem_view: RefCell, + + #[serde(skip)] + history: RefCell>, + // used for the un_clock(), this is because the simulator is not passed in un clock and we dont know what cycle we un clock to + #[serde(skip)] + cycle: RefCell, +} + +impl DataMem { + pub fn new( + id: String, + pos: (f32, f32), + address_input: Input, + data_input: Input, + op_input: Input, + write_enable_input: Input, + mem: Rc>, + ) -> Self { + let mem_view = MemViewWindow::new(id.clone(), "Data memory view".into(), Rc::clone(&mem)) + .set_data_view(); + DataMem { + id: id, + pos: pos, + mem: mem, + address_input: address_input, + data_input: data_input, + op_input: op_input, + write_enable_input: write_enable_input, + mem_view: RefCell::new(mem_view), + history: RefCell::new(HashMap::new()), + cycle: RefCell::default(), // this doesn't mater will be overwritten when clock is called + } + } + pub fn rc_new( + id: String, + pos: (f32, f32), + address_input: Input, + data_input: Input, + op_input: Input, + write_enable_input: Input, + mem: Rc>, + ) -> Rc { + Rc::new(DataMem::new( + id, + pos, + address_input, + data_input, + op_input, + write_enable_input, + mem, + )) + } + pub fn set_mem_view_reg(mut self, reg_rc: Rc) -> Self { + self.mem_view.get_mut().update_regfile(reg_rc); + self + } + fn up_hist(&self, op: MemWriteReturn) { + self.history.borrow_mut().insert(*self.cycle.borrow(), op); + } +} + +#[typetag::serde()] +impl Component for DataMem { + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn to_(&self) { + //println!("InstrMem"); + } + #[cfg(feature = "gui-egui")] + fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { + let dummy_input = Input::new("dummy", "out"); + let memref = Rc::new(RefCell::new(MipsMem::default())); + Box::new(DataMem::rc_new( + id.to_string(), + pos, + dummy_input.clone(), + dummy_input.clone(), + dummy_input.clone(), + dummy_input, + memref, + )) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + DATA_MEM_A_IN_ID => self.address_input = new_input, + DATA_MEM_OP_IN_ID => self.op_input = new_input, + DATA_MEM_WRITE_ENABLE_ID => self.op_input = new_input, + DATA_MEM_WD_IN_ID => self.write_enable_input = new_input, + _ => {} + } + } + + fn get_id_ports(&self) -> (String, Ports) { + ( + self.id.clone(), + Ports::new( + vec![ + &InputPort { + port_id: DATA_MEM_A_IN_ID.to_string(), + input: self.address_input.clone(), + }, + &InputPort { + port_id: DATA_MEM_OP_IN_ID.to_string(), + input: self.op_input.clone(), + }, + &InputPort { + port_id: DATA_MEM_WD_IN_ID.to_string(), + input: self.data_input.clone(), + }, + &InputPort { + port_id: DATA_MEM_WRITE_ENABLE_ID.to_string(), + input: self.write_enable_input.clone(), + }, + ], + OutputType::Combinatorial, + vec![DATA_MEM_READ_DATA_OUT_ID], + ), + ) + } + + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + *self.cycle.borrow_mut() = simulator.cycle; + // get instr at pc/4s + let address: u32 = simulator + .get_input_value(&self.address_input) + .try_into() + .unwrap(); + + // is operation load or store ect + let mem_op: u32 = simulator + .get_input_value(&self.op_input) + .try_into() + .unwrap(); + + let write_enable: bool = simulator + .get_input_value(&self.write_enable_input) + .try_into() + .unwrap(); + + let data: u32 = simulator + .get_input_value(&self.data_input) + .try_into() + .unwrap(); + + // update dynamic symbol PC_IM + self.mem_view + .borrow_mut() + .set_dynamic_symbol("DM_ADRS", address); + + // check if write enable and mem op match + let is_write_enable_valid = match mem_op { + data_op::LOAD_BYTE + | data_op::LOAD_BYTE_U + | data_op::LOAD_HALF + | data_op::LOAD_HALF_U + | data_op::LOAD_WORD => !write_enable, + data_op::STORE_BYTE | data_op::STORE_HALF | data_op::STORE_WORD => write_enable, + _ => true, + }; + + if !is_write_enable_valid { + return Err(Condition::Error(format!( + "write_enable ({}) doesn't match mem_op ({})", + write_enable, mem_op + ))); + } + const SIGNED: bool = true; + const UNSIGNED: bool = false; + + let ret: Result<(), Condition> = match mem_op { + data_op::NO_OP => { + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); + Ok(()) + } + data_op::LOAD_BYTE => { + let val = self + .mem + .borrow() + .get_unaligned(address, MemOpSize::Byte, SIGNED, true); + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); + Ok(()) + } + data_op::LOAD_BYTE_U => { + let val = self + .mem + .borrow() + .get_unaligned(address, MemOpSize::Byte, UNSIGNED, true); + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); + Ok(()) + } + data_op::LOAD_HALF => { + match self + .mem + .borrow() + .get(address, MemOpSize::Half, SIGNED, true) + { + Ok(val) => { + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); + Ok(()) + } + Err(_) => Err(Condition::Error(format!( + "Tried to read unaligned half word, address {:#0x}", + address + ))), + } + } + data_op::LOAD_HALF_U => { + match self + .mem + .borrow() + .get(address, MemOpSize::Half, UNSIGNED, true) + { + Ok(val) => { + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); + Ok(()) + } + Err(_) => Err(Condition::Error(format!( + "Tried to read unaligned half word, address {:#0x}", + address + ))), + } + } + data_op::LOAD_WORD => { + match self + .mem + .borrow() + .get(address, MemOpSize::Word, UNSIGNED, true) + { + Ok(val) => { + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); + Ok(()) + } + Err(_) => Err(Condition::Error(format!( + "Tried to read unaligned word, address {:#0x}", + address + ))), + } + } + data_op::STORE_BYTE => { + self.up_hist( + self.mem + .borrow_mut() + .write(address, data, MemOpSize::Byte, true), + ); + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); + Ok(()) + } + data_op::STORE_HALF => { + match self + .mem + .borrow_mut() + .write_aligned(address, data, MemOpSize::Half, true) + { + Ok(ret) => { + self.up_hist(ret); + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); + Ok(()) + } + Err(_) => Err(Condition::Error(format!( + "Tried to write unaligned half word, address {:#0x}", + address + ))), + } + } + data_op::STORE_WORD => { + match self + .mem + .borrow_mut() + .write_aligned(address, data, MemOpSize::Word, true) + { + Ok(ret) => { + self.up_hist(ret); + simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); + Ok(()) + } + Err(_) => Err(Condition::Error(format!( + "Tried to write unaligned word, address {:#0x}", + address + ))), + } + } + _ => Err(Condition::Error(format!("unknown mem op {}", mem_op))), + }; + // test breakpoint + match ret { + Ok(_) => match mem_op { + data_op::NO_OP => Ok(()), + _ => { + if self.mem_view.borrow().is_break_point(&(address & !0b11)) { + Err(Condition::Halt(format!( + "Read or write at breakpoint address {:#0x}", + address + ))) + } else { + Ok(()) + } + } + }, + Err(_) => ret, + } + } + + fn un_clock(&self) { + *self.cycle.borrow_mut() -= 1; + if let Some(op) = self.history.borrow_mut().remove(&*self.cycle.borrow()) { + self.mem.borrow_mut().revert(op); + }; + } + + fn reset(&self) { + // dont need to reset cycle, since cycle is updated in clock + + let mut hist_vec: Vec<(usize, MemWriteReturn)> = + self.history.borrow_mut().drain().collect(); + // sort vec with largest first + hist_vec.sort_by(|(a, _), (b, _)| a.cmp(b).reverse()); + let mut mem = self.mem.borrow_mut(); + for (_, op) in hist_vec { + mem.revert(op); + } + } +} diff --git a/mips-lib/src/components/mod.rs b/mips-lib/src/components/mod.rs new file mode 100644 index 00000000..cea5f7f3 --- /dev/null +++ b/mips-lib/src/components/mod.rs @@ -0,0 +1,9 @@ +mod full_adder; +mod mips_control_unit; +mod mips_dm; +mod sz_extend; + +pub use full_adder::*; +pub use mips_control_unit::*; +pub use mips_dm::*; +pub use sz_extend::*; diff --git a/mips-lib/src/components/sz_extend.rs b/mips-lib/src/components/sz_extend.rs new file mode 100644 index 00000000..a8aa5d57 --- /dev/null +++ b/mips-lib/src/components/sz_extend.rs @@ -0,0 +1,126 @@ +// use std::fmt::Alignment; +use crate::components::cntr_unit_signals; +use log::*; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::rc::Rc; +#[cfg(feature = "gui-egui")] +use syncrim::common::EguiComponent; +use syncrim::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, +}; +use syncrim::signal; + +pub const SIGNZEROEXTEND_SIGNAL_IN_ID: &str = "signzero_signal_in"; +pub const SIGNZEROEXTEND_CTRL_IN_ID: &str = "signzero_ctrl_in"; + +pub const SIGNZEROEXTEND_OUT_ID: &str = "sz_out"; + +#[derive(Serialize, Deserialize, Clone)] +pub struct SignZeroExtend { + pub(crate) id: Id, + pub(crate) pos: (f32, f32), + pub(crate) signzero_signal_in: Input, + pub(crate) signzero_ctrl_in: Input, +} + +#[typetag::serde] +impl Component for SignZeroExtend { + fn to_(&self) { + trace!("pc+4"); + } + #[cfg(feature = "gui-egui")] + // fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { + // let dummy_input = Input::new("dummy", "out"); + // Box::new(Rc::new(SignZeroExtend { + // id: "dummy".to_string(), + // pos: (0.0, 0.0), + // signzero_extend_in: dummy_input.clone(), + // })) + // } + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new( + vec![ + &InputPort { + port_id: SIGNZEROEXTEND_SIGNAL_IN_ID.to_string(), + input: self.signzero_signal_in.clone(), + }, + &InputPort { + port_id: SIGNZEROEXTEND_CTRL_IN_ID.to_string(), + input: self.signzero_ctrl_in.clone(), + }, + ], + OutputType::Combinatorial, + vec![SIGNZEROEXTEND_OUT_ID], + ), + ) + } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + SIGNZEROEXTEND_SIGNAL_IN_ID => self.signzero_signal_in = new_input, + SIGNZEROEXTEND_CTRL_IN_ID => self.signzero_ctrl_in = new_input, + _ => {} + } + } + + // propagate sign extension to output + // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) + fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { + // get input values + let mut signal: u32 = simulator + .get_input_value(&self.signzero_signal_in) + .try_into() + .unwrap(); + + let ctrl: u32 = simulator + .get_input_value(&self.signzero_ctrl_in) + .try_into() + .unwrap(); + + if ctrl == cntr_unit_signals::EXTEND_SIGNED { + if (signal >> 15) == 1 { + signal = signal | 0xffff_0000; + } + } + + simulator.set_out_value(&self.id, SIGNZEROEXTEND_OUT_ID, SignalValue::Data(signal)); + Ok(()) + } + + fn as_any(&self) -> &dyn Any { + self + } +} + +impl SignZeroExtend { + pub fn new( + id: &str, + pos: (f32, f32), + signzero_signal_in: Input, + signzero_ctrl_in: Input, + ) -> Self { + SignZeroExtend { + id: id.to_string(), + pos, + signzero_signal_in, + signzero_ctrl_in, + } + } + + pub fn rc_new( + id: &str, + pos: (f32, f32), + signzero_signal_in: Input, + signzero_ctrl_in: Input, + ) -> Rc { + Rc::new(SignZeroExtend::new( + id, + pos, + signzero_signal_in, + signzero_ctrl_in, + )) + } +} diff --git a/mips-lib/src/gui_egui/full_adder.rs b/mips-lib/src/gui_egui/full_adder.rs new file mode 100644 index 00000000..c71e4a9f --- /dev/null +++ b/mips-lib/src/gui_egui/full_adder.rs @@ -0,0 +1,204 @@ +use crate::components::{alu_op, FullAdd}; +use egui::{ + Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Stroke, TextWrapMode, Ui, + Vec2, +}; +use syncrim::common::{EguiComponent, Ports, Simulator}; +use syncrim::gui_egui::component_ui::{ + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, +}; +use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use syncrim::gui_egui::gui::EguiExtra; +use syncrim::gui_egui::helper::offset_helper; + +#[typetag::serde] +impl EguiComponent for FullAdd { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + // 41x81 + // middle: 21x 41y (0 0) + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + // The shape + ui.painter().add(Shape::closed_line( + vec![ + oh((-20f32, -40f32), s, o), + oh((0f32, -40f32), s, o), + oh((20f32, -20f32), s, o), + oh((20f32, 20f32), s, o), + oh((0f32, 40f32), s, o), + oh((-20f32, 40f32), s, o), + oh((-20f32, 20f32), s, o), + oh((-10f32, 0f32), s, o), + oh((-20f32, -20f32), s, o), + ], + Stroke { + width: scale, + color: Color32::BLACK, + }, + )); + + let rect = Rect { + min: oh((-20f32, -40f32), s, o), + max: oh((20f32, 40f32), s, o), + }; + let op: String = if let Some(s) = simulator { + match TryInto::::try_into(s.get_input_value(&self.op_in)).unwrap() { + alu_op::ADD => "ADD", + alu_op::ADDU => "ADDU", + alu_op::SUB => "SUB", + alu_op::SUBU => "SUBU", + alu_op::AND => "AND", + alu_op::OR => "OR", + alu_op::XOR => "XOR", + alu_op::NOR => "NOR", + alu_op::SLT => "SLT", + alu_op::SLTU => "SLTU", + alu_op::SLL => "SLL", + alu_op::SRL => "SRL", + alu_op::SRA => "SRA", + alu_op::LUI => "LUI", + _ => "UNDEF", + } + .to_string() + } else { + "no sim".to_string() + }; + + let _area = Area::new(egui::Id::from(self.id.to_string())) + .order(Order::Middle) + .current_pos(offset.to_pos2() + Vec2::new(5.0, 0.0) * scale) + .movable(false) + .enabled(true) + .interactable(false) + .pivot(Align2::CENTER_CENTER) + .constrain(false) + .show(ui.ctx(), |ui| { + ui.set_clip_rect(clip_rect); + ui.style_mut().wrap_mode = Some(TextWrapMode::Extend); + ui.label(RichText::new(format!("ALU\n{}", op)).size(scale * 12f32)) + }); + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + ui.label("Adder"); + }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(syncrim::common::Id, Ports)], + grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let r_vec = FullAdd::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_drag_value(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.a_in, + crate::components::FULL_ADD_A_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.b_in, + crate::components::FULL_ADD_B_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.op_in, + crate::components::FULL_ADD_OP_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown + }, + ); + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(syncrim::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + syncrim::components::SEXT_IN_ID.to_string(), + Pos2::new(-40f32, 0f32) + own_pos, + ), + ( + syncrim::components::SEXT_OUT_ID.to_string(), + Pos2::new(40f32, 0f32) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + 20f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } +} diff --git a/mips-lib/src/gui_egui/mips_control_unit.rs b/mips-lib/src/gui_egui/mips_control_unit.rs new file mode 100644 index 00000000..c8acd068 --- /dev/null +++ b/mips-lib/src/gui_egui/mips_control_unit.rs @@ -0,0 +1,70 @@ +use crate::components::ControlUnit; +use egui::{Rect, Response, RichText, Ui, Vec2}; +use syncrim::common::{EguiComponent, Id, Ports, Simulator}; +use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use syncrim::gui_egui::gui::EguiExtra; +use syncrim::gui_egui::helper::basic_component_gui; + +#[typetag::serde] +impl EguiComponent for ControlUnit { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + _editor_mode: EditorMode, + ) -> Option> { + // size of the component + let width = 100f32 * scale; + let height: f32 = 12f32 * scale; + basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.set_height(height); + ui.set_width(width); + ui.centered_and_justified(|ui| { + ui.label("Control Unit"); + }); + }) + } + + fn render_editor( + &mut self, + ui: &mut egui::Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: egui::Vec2, + scale: f32, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + self.render( + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ); + EditorRenderReturn { + delete: false, + resp: None, + } + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } + + fn top_padding(&self) -> f32 { + 20f32 + } +} diff --git a/mips-lib/src/gui_egui/mips_dm.rs b/mips-lib/src/gui_egui/mips_dm.rs new file mode 100644 index 00000000..0bac1cb2 --- /dev/null +++ b/mips-lib/src/gui_egui/mips_dm.rs @@ -0,0 +1,99 @@ +use crate::components::DataMem; +use egui::{Rect, Response, RichText, Ui, Vec2}; +use syncrim::common::{EguiComponent, Id, Ports, Simulator}; +use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use syncrim::gui_egui::gui::EguiExtra; +use syncrim::gui_egui::helper::basic_component_gui; + +#[typetag::serde] +impl EguiComponent for DataMem { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + _editor_mode: EditorMode, + ) -> Option> { + // we could avoid this if we clone self in our basic_component_ui. + // but instead we let our Closure save stuff here (let path_option, mem_view_vis) + // and apply our changes when basic_component_gui returns our borrow + // this is to avoid cloning all the fields. + // avoiding to clone the fields might be premature optimization + // as instrMem.mem is a reference count and wont actually clone the underlying btree and hashmaps + // + // we save 27 bytes of clone + // and most of that clone might even be optimized away + // yes this was premature optimization + let mut mem_view_vis: bool = self.mem_view.borrow().visible; + + let r = basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + // ui.centered_and_justified(|ui| { + ui.label(RichText::new("Data memory").size(12f32 * scale)); + ui.button( + RichText::new("load file") + .size(12f32 * scale) + .strikethrough(), + ) + .on_hover_text("Use instruction memory to load a file"); + + match mem_view_vis { + false => { + if ui.button("Show mem window").clicked() { + mem_view_vis = true; + } + } + true => { + ui.toggle_value(&mut mem_view_vis, "Hide mem window"); + } + }; + // }); + }); + let mut mem_view = self.mem_view.borrow_mut(); + mem_view.visible = mem_view_vis; + mem_view.render(ui.ctx()); + // return response from basic component gui + r + } + + fn render_editor( + &mut self, + ui: &mut egui::Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: egui::Vec2, + scale: f32, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + self.render( + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ); + EditorRenderReturn { + delete: false, + resp: None, + } + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } + + fn top_padding(&self) -> f32 { + 20f32 + } +} diff --git a/mips-lib/src/gui_egui/mod.rs b/mips-lib/src/gui_egui/mod.rs new file mode 100644 index 00000000..bd54270b --- /dev/null +++ b/mips-lib/src/gui_egui/mod.rs @@ -0,0 +1,4 @@ +mod full_adder; +mod mips_control_unit; +mod mips_dm; +mod sz_extend; diff --git a/mips-lib/src/gui_egui/sz_extend.rs b/mips-lib/src/gui_egui/sz_extend.rs new file mode 100644 index 00000000..fcb178ff --- /dev/null +++ b/mips-lib/src/gui_egui/sz_extend.rs @@ -0,0 +1,83 @@ +use crate::components::SignZeroExtend; +use egui::{Rect, Response, RichText, Ui, Vec2}; +use syncrim::common::{EguiComponent, Id, Ports, SignalValue, Simulator}; +use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use syncrim::gui_egui::gui::EguiExtra; +use syncrim::gui_egui::helper::basic_component_gui; + +#[typetag::serde] +impl EguiComponent for SignZeroExtend { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + _editor_mode: EditorMode, + ) -> Option> { + basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + match &simulator { + Some(sim) => { + ui.label(match sim.get_input_value(&self.signzero_ctrl_in) { + SignalValue::Uninitialized => { + " Sign/Zero extend:\nUninitialized cntr".to_string() + } + SignalValue::Unknown => "Sign/Zero extend:\nextendUnknown".to_string(), + SignalValue::DontCare => "Sign/Zero extend:\nDon't Care".to_string(), + SignalValue::Data(v) => match v { + 0 => "Sign/Zero extend:\nZero", + 1 => "Sign/Zero extend:\nSign", + _ => "Sign/Zero extend:\nInvalid cntr", + } + .to_string(), + }); + } + + None => { + ui.label(RichText::new("Signal Extender:\nNo Sim").size(12f32 * scale)); + } + } + }) + } + + fn render_editor( + &mut self, + ui: &mut egui::Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: egui::Vec2, + scale: f32, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + self.render( + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ); + EditorRenderReturn { + delete: false, + resp: None, + } + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } + + fn top_padding(&self) -> f32 { + 20f32 + } +} diff --git a/mips/src/gui_egui/mod.rs b/mips-lib/src/lib.rs similarity index 51% rename from mips/src/gui_egui/mod.rs rename to mips-lib/src/lib.rs index f188f2c2..b0c0d777 100644 --- a/mips/src/gui_egui/mod.rs +++ b/mips-lib/src/lib.rs @@ -1 +1,3 @@ pub mod components; + +pub mod gui_egui; diff --git a/mips-simple/Cargo.toml b/mips-simple/Cargo.toml new file mode 100644 index 00000000..a43f59a1 --- /dev/null +++ b/mips-simple/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "mips-simple" +version = "0.1.0" +edition = "2021" + +[dependencies] +mips-lib = {path = "../mips-lib/"} +[dependencies.syncrim] +path = "../" +default-features = false + +[features] +default = ["gui-egui"] + +components = ["syncrim/components"] +gui-vizia = ["syncrim/gui-vizia", "components"] +gui-egui = ["syncrim/gui-egui", "components"] diff --git a/mips-simple/src/main.rs b/mips-simple/src/main.rs new file mode 100644 index 00000000..798dacd4 --- /dev/null +++ b/mips-simple/src/main.rs @@ -0,0 +1,243 @@ +// use crate::src::components::cntr_unit_signals; +use mips_lib::components::*; +use std::rc::Rc; +use std::{cell::RefCell, path::PathBuf}; +use syncrim::common::EguiComponent; +#[cfg(feature = "gui-egui")] +use syncrim::gui_egui::editor::Library; +use syncrim::{ + common::{ComponentStore, Input}, + components::*, + fern::fern_setup, + mips_helper_functions::autowire, +}; + +fn main() { + fern_setup(); + + let mem = Rc::new(RefCell::new(MipsMem::default())); + let rc_reg_file = RegFile::rc_new( + "reg_file", + (350.0, 225.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + Input::new("reg_write_addr", REGISTER_OUT_ID), //write address + Input::new("result_reg", REGISTER_OUT_ID), //write data + Input::new("reg_we", REGISTER_OUT_ID), + ); + + let cs = ComponentStore { + store: vec![ + // register that holds instr addr + Register::rc_new( + "pc", + (150.0, 390.0), + Input::new("mux_jump_merge", MUX_OUT_ID), + ), + // step addr from reg by 4 + Constant::rc_new("+4", (150.0, 440.0), 4), + Add::rc_new( + "pc+4", + (200.0, 400.0), + Input::new("+4", CONSTANT_OUT_ID), + Input::new("pc", REGISTER_OUT_ID), + ), + // + // + Rc::new( + InstrMem::new( + "instr_mem".into(), + (250.0, 575.0), + Input::new("pc", REGISTER_OUT_ID), + Rc::clone(&mem), + ) + .set_mem_view_reg(rc_reg_file.clone()), + ), + // + // + // MUX to choose what intruction addr to choose from, branch jump, reg, pc+4 + Mux::rc_new( + "mux_jump_merge", + (100.0, 390.0), + Input::new("branch", BRANCH_OUT_ID), + vec![ + Input::new("pc_add_branch", ADD_OUT_ID), //TODO: describe origin + Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), // goes to addr, RD2 + Input::new("jump_merge", MERGE_OUT_ID), // + Input::new("pc+4", ADD_OUT_ID), + ], + ), + // + // merges to find out jump location + JumpMerge::rc_new( + "jump_merge", + (125.0, 475.0), + Input::new("pc", REGISTER_OUT_ID), //input from reg before pc+4 + Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), //input from instruction mem + ), + // + // splits intructions from ir to fields + InstrSplit::rc_new( + "instruction_split", + (200.0, 225.0), + Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), + ), + // + // + ControlUnit::rc_new( + "control_unit", + (500.0, 50.0), + Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), + ), + // + // + Register::rc_new( + "reg_we", + (850.0, 50.0), + Input::new("control_unit", cntr_field::REG_WRITE_ENABLE_OUT), + ), + // + // extends immediate field + SignZeroExtend::rc_new( + "signzero_extend", + (325.0, 425.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_IMMEDIATE_ID), + Input::new("control_unit", cntr_field::EXTEND_SELECT_OUT), // cu tells it to either sing- or zero- extend + ), + // + // + BranchLogic::rc_new( + "branch", + (475.0, 225.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_OP_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_FUNCT_ID), + Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), + ), + // + // + ZeroExtend::rc_new( + "zero_extend_for_chamt", + (600.0, 150.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_SHAMT_ID), + ), + // + // + Constant::rc_new("0_a_inp", (610.0, 220.0), 0), + Mux::rc_new( + "mux_source_a", + (650.0, 195.0), + Input::new("control_unit", cntr_field::ALU_SRC_A_OUT), + vec![ + Input::new("zero_extend_for_chamt", ZEROEXTEND_OUT_ID), + Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), + Input::new("0_a_inp", CONSTANT_OUT_ID), + ], + ), + // + // + Mux::rc_new( + "mux_source_b", + (650.0, 255.0), + Input::new("control_unit", cntr_field::ALU_SRC_B_OUT), + vec![ + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), + Input::new("pc+4", ADD_OUT_ID), + Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), + ], + ), + // + // + FullAdd::rc_new( + "alu", + (720.0, 225.0), + Input::new("mux_source_a", MUX_OUT_ID), + Input::new("mux_source_b", MUX_OUT_ID), + Input::new("control_unit", cntr_field::ALU_OP_OUT), + ), + // + // + Rc::new( + DataMem::new( + "data_mem".into(), + (600.0, 575.0), + Input::new("alu", FULL_ADD_OUT_ID), // calculated from rs and imm + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), + Input::new("control_unit", cntr_field::MEM_MODE_OUT), + Input::new("control_unit", cntr_field::MEM_WRITE_ENABLE_OUT), + Rc::clone(&mem), + ) + .set_mem_view_reg(rc_reg_file.clone()), + ), + // + // + Mux::rc_new( + "mux_write_back", + (800.0, 225.0), + Input::new("control_unit", cntr_field::REG_WRITE_SRC_OUT), + vec![ + Input::new("alu", FULL_ADD_OUT_ID), + Input::new("data_mem", DATA_MEM_READ_DATA_OUT_ID), //TODO: data meme output + ], + ), + // + // + Register::rc_new( + "result_reg", + (850.0, 225.0), + Input::new("mux_write_back", MUX_OUT_ID), + ), + // + // + ShiftConst::rc_new( + "branch_shift", + (325.0, 480.0), + Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), + 2, + ), + // + // + Add::rc_new( + "pc_add_branch", + (400.0, 475.0), + Input::new("pc+4", ADD_OUT_ID), + Input::new("branch_shift", SHIFT_OUT_ID), + ), + // + // + Constant::rc_new("0x_1F", (350.0, 550.0), 0x_1F), + Mux::rc_new( + "mux_write_addr", + (400.0, 525.0), + Input::new("control_unit", cntr_field::REG_DEST_OUT), + vec![ + Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RD_ID), + Input::new("0x_1F", CONSTANT_OUT_ID), + ], + ), + // + // + Register::rc_new( + "reg_write_addr", + (850.0, 525.0), + Input::new("mux_write_addr", MUX_OUT_ID), + ), + // + // + rc_reg_file, + ], + }; + + let cs = autowire(cs); + + let path = PathBuf::from("add.json"); + cs.save_file(&path); + + #[cfg(feature = "gui-egui")] + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + + #[cfg(feature = "gui-vizia")] + syncrim::gui_vizia::gui(cs, &path); +} diff --git a/mips/Cargo.toml b/mips/Cargo.toml deleted file mode 100644 index 2b675098..00000000 --- a/mips/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "mips" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -serde = "1.0.175" -serde_derive = "1.0.175" -typetag = "0.2.12" -serde_json = "1.0.103" -fern = "0.6.2" -log = "0.4.19" -num_enum = "0.6.1" - -[dependencies.syncrim] -path = "../" -default-features = false - -[features] -default = ["gui-vizia"] - -components = ["syncrim/components"] -gui-vizia = ["syncrim/gui-vizia", "components"] -gui-egui = ["syncrim/gui-egui", "components"] - -[[test]] -name = "component_tests" -required-features = ["components"] - -[[example]] -name = "mips" -required-features = ["components"] - -[[example]] -name = "reg_file" -required-features = ["components"] diff --git a/mips/README.md b/mips/README.md deleted file mode 100644 index 3929433d..00000000 --- a/mips/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# MIPS - -MIPS specific components. diff --git a/mips/examples/mips.rs b/mips/examples/mips.rs deleted file mode 100644 index 0b33da4a..00000000 --- a/mips/examples/mips.rs +++ /dev/null @@ -1,75 +0,0 @@ -// An example MIPS model - -use mips::components::*; -use std::path::PathBuf; -use syncrim::{ - common::{ComponentStore, Input}, - components::*, - fern::fern_setup, -}; - -fn main() { - fern_setup(); - let cs = ComponentStore { - store: vec![ - Add::rc_new( - "add", - (200.0, 120.0), - Input::new("c1", "out"), - Input::new("reg", "out"), - ), - Constant::rc_new("c1", (100.0, 100.0), 4), - Register::rc_new("reg", (100.0, 140.0), Input::new("add", "out")), - Wire::rc_new( - "c1_to_add_a", - vec![(110.0, 100.0), (180.0, 100.0)], - Input::new("c1", "out"), - ), - Wire::rc_new( - "reg_to_add_b", - vec![(110.0, 140.0), (180.0, 140.0)], - Input::new("reg", "out"), - ), - Wire::rc_new( - "add_to_reg", - vec![ - (220.0, 120.0), - (260.0, 120.0), - (260.0, 60.0), - (60.0, 60.0), - (60.0, 140.0), - (90.0, 140.0), - ], - Input::new("add", "out"), - ), - Wire::rc_new( - "pc_to_down", - vec![(140.0, 140.0), (140.0, 180.0), (350.0, 180.0)], - Input::new("reg", "out"), - ), - InstrMem::rc_new( - "instr_mem", - (400.0, 150.0), - Input::new("reg", "out"), - // fake instructions just to show the relation between input address and instruction - vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], - ), - Wire::rc_new( - "w8", - vec![(450.0, 120.0), (520.0, 120.0)], - Input::new("instr_mem", "out"), - ), - Probe::rc_new("p1", (280.0, 160.0), Input::new("reg", "out")), - Probe::rc_new("p2", (500.0, 100.0), Input::new("instr_mem", "out")), - ], - }; - - let path = PathBuf::from("mips.json"); - cs.save_file(&path); - - #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path).ok(); - - #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(cs, &path); -} diff --git a/mips/examples/reg_file.rs b/mips/examples/reg_file.rs deleted file mode 100644 index e02bd63f..00000000 --- a/mips/examples/reg_file.rs +++ /dev/null @@ -1,99 +0,0 @@ -use mips::components::*; -use std::path::PathBuf; -use syncrim::{ - common::{ComponentStore, Input, SignalFmt, SignalSize}, - components::*, - fern::fern_setup, -}; - -fn main() { - fern_setup(); - let cs = ComponentStore { - store: vec![ - Constant::rc_new( - "c_read_reg_1", - (100.0, 100.0), - // Format as binary - (3, SignalFmt::Binary(5)), - ), - Constant::rc_new( - "c_write_addr", - (100.0, 160.0), - // Format as hex with padding - (4, SignalFmt::Binary(5)), - ), - Constant::rc_new("c_write_enable", (100.0, 180.0), true), - Constant::rc_new( - "c_write_data", - (100.0, 220.0), - // Format as hex with padding - (42, SignalFmt::Hex(SignalSize::_32, true)), - ), - Constant::rc_new( - "c_read_reg_2", - (100.0, 300.0), - // Format as binary - (4, SignalFmt::Binary(5)), - ), - // regfile - RegFile::rc_new( - "reg_file", - (300.0, 200.0), - 200.0, - 300.0, - // ports - Input::new("c_read_reg_1", "out"), - Input::new("c_read_reg_2", "out"), - Input::new("c_write_data", "out"), - Input::new("c_write_addr", "out"), - Input::new("c_write_enable", "out"), - ), - Probe::rc_new("p_reg_a", (500.0, 100.0), Input::new("reg_file", "reg_a")), - Probe::rc_new("p_reg_b", (500.0, 300.0), Input::new("reg_file", "reg_b")), - Wire::rc_new( - "w_read_reg_1", - vec![(180.0, 100.0), (200.0, 100.0)], - Input::new("c_read_reg_1", "out"), - ), - Wire::rc_new( - "w_read_reg_2", - vec![(180.0, 300.0), (200.0, 300.0)], - Input::new("c_read_reg_2", "out"), - ), - Wire::rc_new( - "w_write_addr", - vec![(180.0, 160.0), (200.0, 160.0)], - Input::new("c_write_addr", "out"), - ), - Wire::rc_new( - "w_write_enable", - vec![(180.0, 180.0), (200.0, 180.0)], - Input::new("c_write_enable", "out"), - ), - Wire::rc_new( - "w_write_data", - vec![(180.0, 220.0), (200.0, 220.0)], - Input::new("c_write_data", "out"), - ), - Wire::rc_new( - "w_reg_a", - vec![(400.0, 100.0), (490.0, 100.0)], - Input::new("reg_file", "reg_a"), - ), - Wire::rc_new( - "w_reg_b", - vec![(400.0, 300.0), (490.0, 300.0)], - Input::new("reg_file", "reg_b"), - ), - ], - }; - - let path = PathBuf::from("reg_file.json"); - cs.save_file(&path); - - #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path).ok(); - - #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(cs, &path); -} diff --git a/mips/src/components/instr_mem.rs b/mips/src/components/instr_mem.rs deleted file mode 100644 index c9508c52..00000000 --- a/mips/src/components/instr_mem.rs +++ /dev/null @@ -1,80 +0,0 @@ -use serde::{Deserialize, Serialize}; -use std::rc::Rc; -use syncrim::common::{ - Component, Condition, Input, InputPort, OutputType, Ports, SignalUnsigned, SignalValue, - Simulator, -}; - -pub const INSTR_MEM_PC_ID: &str = "pc"; - -pub const INSTR_MEM_OUT_ID: &str = "out"; - -#[derive(Serialize, Deserialize)] -pub struct InstrMem { - pub(crate) id: String, - pub(crate) pos: (f32, f32), - pub(crate) pc: Input, - pub(crate) instr: Vec, -} - -use log::*; - -#[typetag::serde()] -impl Component for InstrMem { - fn to_(&self) { - trace!("InstrMem"); - } - - fn get_id_ports(&self) -> (String, Ports) { - ( - self.id.clone(), - Ports { - inputs: vec![InputPort { - port_id: INSTR_MEM_PC_ID.to_string(), - input: self.pc.clone(), - }], - out_type: OutputType::Combinatorial, - outputs: vec![INSTR_MEM_OUT_ID.to_string()], - }, - ) - } - - fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { - let instr: SignalValue = - match TryInto::::try_into(simulator.get_input_value(&self.pc)) { - Ok(pc) => { - trace!("--- evaluate instr mem: pc {:?}", pc); - // get instr at pc/4 - match self.instr.get((pc / 4) as usize) { - Some(instr) => (*instr).into(), - _ => SignalValue::Unknown, - } - } - _ => SignalValue::Unknown, - }; - - // set output - trace!("--- output {:?}", instr); - simulator.set_out_value(&self.id, INSTR_MEM_OUT_ID, instr); - Ok(()) - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } -} - -impl InstrMem { - pub fn new(id: &str, pos: (f32, f32), pc: Input, instr: Vec) -> Self { - InstrMem { - id: id.to_string(), - pos, - pc, - instr, - } - } - - pub fn rc_new(id: &str, pos: (f32, f32), pc: Input, instr: Vec) -> Rc { - Rc::new(InstrMem::new(id, pos, pc, instr)) - } -} diff --git a/mips/src/components/mod.rs b/mips/src/components/mod.rs deleted file mode 100644 index a5fb9f4d..00000000 --- a/mips/src/components/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod instr_mem; -mod reg_file; - -pub use instr_mem::*; -pub use reg_file::*; diff --git a/mips/src/components/reg_file.rs b/mips/src/components/reg_file.rs deleted file mode 100644 index 4a776f4c..00000000 --- a/mips/src/components/reg_file.rs +++ /dev/null @@ -1,353 +0,0 @@ -use log::*; -use num_enum::TryFromPrimitive; -use serde::{Deserialize, Serialize}; -use std::ops::{Deref, Range}; -use std::{cell::RefCell, rc::Rc}; -use syncrim::common::{ - Component, Condition, Input, InputPort, OutputType, Ports, SignalUnsigned, Simulator, -}; - -#[allow(non_camel_case_types)] -#[rustfmt::skip] -#[derive(Copy, Clone, Debug, TryFromPrimitive)] -#[repr(u8)] -pub enum Reg { - zero = 0, // Constant 0 - at = 1, // Reserved for assembler - v0 = 2, // Expression evaluation and results of function - v1 = 3, // Expression evaluation and results of function - a0 = 4, // Argument 1 - a1 = 5, // Argument 2 - a2 = 6, // Argument 3 - a3 = 7, // Argument 4 - t0 = 8, // Temporary (not preserved across calls) - t1 = 9, // Temporary (not preserved across calls) - t2 = 10, // Temporary (not preserved across calls) - t3 = 11, // Temporary (not preserved across calls) - t4 = 12, // Temporary (not preserved across calls) - t5 = 13, // Temporary (not preserved across calls) - t6 = 14, // Temporary (not preserved across calls) - t7 = 15, // Temporary (not preserved across calls) - s0 = 16, // Temporary (not preserved across calls) - s1 = 17, // Temporary (not preserved across calls) - s2 = 18, // Temporary (not preserved across calls) - s3 = 19, // Temporary (not preserved across calls) - s4 = 20, // Temporary (not preserved across calls) - s5 = 21, // Temporary (not preserved across calls) - s6 = 22, // Temporary (not preserved across calls) - s7 = 23, // Temporary (not preserved across calls) - t8 = 24, // Temporary (not preserved across calls) - t9 = 25, // Temporary (not preserved across calls) - k0 = 26, // Reserved for OS kernel - k1 = 27, // Reserved for OS kernel - gp = 28, // Pointer to global area - sp = 29, // Stack pointer - fp = 30, // Frame pointer - ra = 31, // Return address (used by function calls) -} - -pub const REG_FILE_READ_ADDR1_ID: &str = "read_addr1"; -pub const REG_FILE_READ_ADDR2_ID: &str = "read_addr2"; -pub const REG_FILE_WRITE_DATA_ID: &str = "write_data"; -pub const REG_FILE_WRITE_ADDR_ID: &str = "write_addr"; -pub const REG_FILE_WRITE_ENABLE_ID: &str = "write_enable"; - -pub const REG_FILE_REG_A_OUT: &str = "reg_a"; -pub const REG_FILE_REG_B_OUT: &str = "reg_b"; - -#[derive(Serialize, Deserialize)] -pub struct RegFile { - pub(crate) id: String, - pub(crate) pos: (f32, f32), - pub(crate) width: f32, - pub(crate) height: f32, - - // ports - pub(crate) read_addr1: Input, - pub(crate) read_addr2: Input, - pub(crate) write_data: Input, - pub(crate) write_addr: Input, - pub(crate) write_enable: Input, - - // data - pub(crate) registers: RegStore, - pub(crate) history: RegHistory, -} - -#[derive(Serialize, Deserialize, Clone)] -pub struct RegOp { - read_addr1: u8, - read_addr2: u8, - write_addr2: Option<(u8, u32)>, - old_data: Option, -} -// TODO: Perhaps we want registers to be of Signal type (containing potentially Signal::Unknown) - -#[derive(Serialize, Deserialize, Clone)] -pub struct RegHistory(RefCell>); - -impl RegHistory { - pub fn new() -> Self { - RegHistory(RefCell::new(Vec::new())) - } -} - -impl Default for RegHistory { - fn default() -> Self { - Self::new() - } -} - -#[derive(Serialize, Deserialize, Clone)] -pub struct RegStore(pub Rc>); - -impl RegStore { - pub fn new() -> Self { - RegStore(Rc::new(RefCell::new([0; 32]))) - } - - pub fn full_range() -> Range { - Range { start: 0, end: 32 } - } - - pub fn lo_range() -> Range { - Range { start: 0, end: 16 } - } - - pub fn hi_range() -> Range { - Range { start: 16, end: 32 } - } -} - -impl Default for RegStore { - fn default() -> Self { - Self::new() - } -} - -impl Deref for RegStore { - type Target = RefCell<[u32; 32]>; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl RegFile { - #[allow(clippy::too_many_arguments)] - pub fn new( - id: &str, - pos: (f32, f32), - width: f32, - height: f32, - read_addr1: Input, - read_addr2: Input, - write_data: Input, - write_addr: Input, - write_enable: Input, - ) -> Self { - RegFile { - id: id.to_string(), - pos, - width, - height, - - // ports - read_addr1, - read_addr2, - write_data, - write_addr, - write_enable, - - // data - registers: RegStore::new(), - history: RegHistory::new(), - } - } - - #[allow(clippy::too_many_arguments)] - pub fn rc_new( - id: &str, - pos: (f32, f32), - width: f32, - height: f32, - read_addr1: Input, - read_addr2: Input, - write_data: Input, - write_addr: Input, - write_enable: Input, - ) -> Rc { - Rc::new(RegFile::new( - id, - pos, - width, - height, - read_addr1, - read_addr2, - write_data, - write_addr, - write_enable, - )) - } - - fn read_reg(&self, simulator: &Simulator, input: &Input) -> u32 { - let read_addr: SignalUnsigned = simulator.get_input_value(input).try_into().unwrap(); - trace!("read_addr {}", read_addr); - - // mips always reads 0; - if read_addr > 0 { - self.registers.borrow()[read_addr as usize] - } else { - 0 - } - } -} - -#[typetag::serde()] -impl Component for RegFile { - fn to_(&self) { - trace!("RegFile"); - } - - fn get_id_ports(&self) -> (String, Ports) { - ( - self.id.clone(), - Ports { - inputs: vec![ - InputPort { - port_id: REG_FILE_READ_ADDR1_ID.to_string(), - input: self.read_addr1.clone(), - }, - InputPort { - port_id: REG_FILE_READ_ADDR2_ID.to_string(), - input: self.read_addr2.clone(), - }, - InputPort { - port_id: REG_FILE_WRITE_DATA_ID.to_string(), - input: self.write_data.clone(), - }, - InputPort { - port_id: REG_FILE_WRITE_ADDR_ID.to_string(), - input: self.write_addr.clone(), - }, - InputPort { - port_id: REG_FILE_WRITE_ENABLE_ID.to_string(), - input: self.write_enable.clone(), - }, - ], - out_type: OutputType::Combinatorial, - outputs: vec!["reg_a".into(), "reg_b".into()], - }, - ) - } - - fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { - if simulator.get_input_value(&self.write_enable) == (true as SignalUnsigned).into() { - let data = simulator.get_input_value(&self.write_data); - trace!("data {:?}", data); - let write_addr: SignalUnsigned = simulator - .get_input_value(&self.write_addr) - .try_into() - .unwrap(); - trace!("write_addr {}", write_addr); - self.registers.borrow_mut()[write_addr as usize] = data.try_into().unwrap(); - } - - // read after write - let reg_value_a = self.read_reg(simulator, &self.read_addr1); - trace!("reg_value {}", reg_value_a); - simulator.set_out_value(&self.id, REG_FILE_REG_A_OUT, reg_value_a); - - let reg_value_b = self.read_reg(simulator, &self.read_addr2); - trace!("reg_value {}", reg_value_b); - simulator.set_out_value(&self.id, REG_FILE_REG_B_OUT, reg_value_b); - Ok(()) - } - fn as_any(&self) -> &dyn std::any::Any { - self - } -} - -#[cfg(test)] -mod test { - use super::*; - use std::rc::Rc; - use syncrim::{ - common::{ComponentStore, Input, Simulator}, - components::ProbeOut, - }; - - // an example of integration test for a mips specific component - #[test] - fn test_reg_file() { - let cs = ComponentStore { - store: vec![ - Rc::new(ProbeOut::new("read_reg_1")), - Rc::new(ProbeOut::new("read_reg_2")), - Rc::new(ProbeOut::new("write_data")), - Rc::new(ProbeOut::new("write_addr")), - Rc::new(ProbeOut::new("write_enable")), - // regfile - Rc::new(RegFile { - id: "reg_file".to_string(), - pos: (200.0, 150.0), - width: 100.0, - height: 150.0, - - // ports - read_addr1: Input::new("read_reg_1", "out"), - read_addr2: Input::new("read_reg_2", "out"), - write_data: Input::new("write_data", "out"), - write_addr: Input::new("write_addr", "out"), - write_enable: Input::new("write_enable", "out"), - - // data - registers: RegStore::new(), - history: RegHistory::new(), - }), - ], - }; - - let mut simulator = Simulator::new(cs).unwrap(); - - assert_eq!(simulator.cycle, 1); - - // outputs - let out_reg_1 = &Input::new("reg_file", "reg_a"); - let out_reg_2 = &Input::new("reg_file", "reg_b"); - - // reset - assert_eq!(simulator.get_input_value(out_reg_1), 0.into()); - assert_eq!(simulator.get_input_value(out_reg_2), 0.into()); - - println!(""); - simulator.set_out_value("read_reg_1", "out", 0); - simulator.set_out_value("read_reg_2", "out", 1); - simulator.set_out_value("write_data", "out", 1337); - simulator.set_out_value("write_addr", "out", 1); - simulator.set_out_value("write_enable", "out", true as SignalUnsigned); - - // test write and read to reg # 1 in same cycle - println!("sim_state {:?}", simulator.sim_state); - println!(""); - simulator.clock(); - println!("sim_state {:?}", simulator.sim_state); - assert_eq!(simulator.cycle, 2); - assert_eq!(simulator.get_input_value(out_reg_1), 0.into()); - assert_eq!(simulator.get_input_value(out_reg_2), 1337.into()); - - // test write and read to reg # 0 in same cycle (red #0 should always read 0) - println!(""); - simulator.set_out_value("read_reg_1", "out", 0); - simulator.set_out_value("read_reg_2", "out", 1); - simulator.set_out_value("write_data", "out", 42); - simulator.set_out_value("write_addr", "out", 0); - simulator.set_out_value("write_enable", "out", true as SignalUnsigned); - println!(""); - simulator.clock(); - println!("sim_state {:?}", simulator.sim_state); - assert_eq!(simulator.cycle, 3); - assert_eq!(simulator.get_input_value(out_reg_1), 0.into()); - assert_eq!(simulator.get_input_value(out_reg_2), 1337.into()); - } -} diff --git a/mips/src/gui_egui/components/instr_mem.rs b/mips/src/gui_egui/components/instr_mem.rs deleted file mode 100644 index 65d74270..00000000 --- a/mips/src/gui_egui/components/instr_mem.rs +++ /dev/null @@ -1,5 +0,0 @@ -use crate::components::InstrMem; -use syncrim::common::EguiComponent; - -#[typetag::serde] -impl EguiComponent for InstrMem {} diff --git a/mips/src/gui_egui/components/mod.rs b/mips/src/gui_egui/components/mod.rs deleted file mode 100644 index a063d2de..00000000 --- a/mips/src/gui_egui/components/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod instr_mem; -pub mod reg_file; diff --git a/mips/src/gui_egui/components/reg_file.rs b/mips/src/gui_egui/components/reg_file.rs deleted file mode 100644 index 65486a76..00000000 --- a/mips/src/gui_egui/components/reg_file.rs +++ /dev/null @@ -1,5 +0,0 @@ -use crate::components::RegFile; -use syncrim::common::EguiComponent; - -#[typetag::serde] -impl EguiComponent for RegFile {} diff --git a/mips/src/gui_vizia/components/instr_mem.rs b/mips/src/gui_vizia/components/instr_mem.rs deleted file mode 100644 index 6810c2dc..00000000 --- a/mips/src/gui_vizia/components/instr_mem.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::components::InstrMem; -use syncrim::{ - gui_vizia::{ViziaComponent, V}, - vizia::{ - prelude::*, - vg::{Color, Paint, Path}, - }, -}; - -use log::*; - -#[typetag::serde] -impl ViziaComponent for InstrMem { - // create view - fn left_view(&self, cx: &mut Context) { - trace!("---- Create Left Instr View"); - - View::build(InstMemLeft { display: false }, cx, |cx| { - Label::new(cx, "Inst Mem Left"); - }); - } - - // create view - fn view<'a>(&self, cx: &'a mut Context) -> Handle<'a, V> { - trace!("---- Create InsrMem View"); - V::new(cx, self, |cx| { - InstMem {}.build(cx, |cx| { - Label::new(cx, "Inst Mem") - .left(Percentage(20.0)) - .top(Percentage(45.0)) - .hoverable(false); - }) - }) - .left(Pixels(self.pos.0 - 50.0)) - .top(Pixels(self.pos.1 - 100.0)) - .width(Pixels(100.0)) - .height(Pixels(200.0)) - } -} - -#[derive(Lens, Clone)] -pub struct InstMemLeft { - display: bool, -} - -impl View for InstMemLeft { - fn element(&self) -> Option<&'static str> { - Some("InstMem") - } - - // TODO, what to show here -} - -pub struct InstMem {} - -impl View for InstMem { - fn element(&self) -> Option<&'static str> { - Some("InstMem") - } - - fn draw(&self, cx: &mut DrawContext<'_>, canvas: &mut Canvas) { - let bounds = cx.bounds(); - // trace!("InstMem draw {:?}", bounds); - - let mut path = Path::new(); - let mut paint = Paint::color(Color::rgbf(0.0, 1.0, 1.0)); - paint.set_line_width(cx.logical_to_physical(1.0)); - - path.move_to(bounds.left() + 0.5, bounds.top() + 0.5); - path.line_to(bounds.right() + 0.5, bounds.top() + 0.5); - path.line_to(bounds.right() + 0.5, bounds.bottom() + 0.5); - path.line_to(bounds.left() + 0.5, bounds.bottom() + 0.5); - path.line_to(bounds.left() + 0.5, bounds.top() + 0.5); - - canvas.fill_path(&path, &paint); - } -} diff --git a/mips/src/gui_vizia/components/mod.rs b/mips/src/gui_vizia/components/mod.rs deleted file mode 100644 index a063d2de..00000000 --- a/mips/src/gui_vizia/components/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod instr_mem; -pub mod reg_file; diff --git a/mips/src/gui_vizia/components/reg_file.rs b/mips/src/gui_vizia/components/reg_file.rs deleted file mode 100644 index c123e00b..00000000 --- a/mips/src/gui_vizia/components/reg_file.rs +++ /dev/null @@ -1,129 +0,0 @@ -use crate::components::{Reg, RegFile, RegStore}; -use std::{convert::TryFrom, ops::Range}; -use syncrim::{ - gui_vizia::{ViziaComponent, V}, - vizia::prelude::*, -}; - -use log::*; - -#[derive(Lens)] -pub struct RegTabs { - list: Vec<&'static str>, -} - -impl Model for RegTabs {} - -fn range_view(cx: &mut Context, range: Range) { - for i in range { - let item = - RegFileView::registers.map(move |reg| reg.borrow().get(i as usize).copied().unwrap()); - - HStack::new(cx, |cx| { - Label::new(cx, &format!("{:?}", Reg::try_from(i).unwrap())) - .width(Pixels(50.0)) - .left(Pixels(10.0)); - Label::new(cx, item); - }) - .font_size(12.0) - .size(Auto); - } -} - -#[typetag::serde] -impl ViziaComponent for RegFile { - // create view - fn left_view(&self, cx: &mut Context) { - trace!("---- Create Left Instr View"); - - View::build( - RegFileView { - registers: self.registers.clone(), - }, - cx, - |cx| { - Label::new(cx, "Register File") - .left(Pixels(10.0)) - .top(Pixels(10.0)); - - ScrollView::new(cx, 0.0, 0.0, false, true, |cx| { - range_view(cx, RegStore::full_range()); - }) - // .size(Units::Pixels(300.0)) - .class("bg-default"); - }, - ); - } - - // create view - fn view<'a>(&self, cx: &'a mut Context) -> Handle<'a, V> { - trace!("---- Create RegFile View"); - V::new(cx, self, move |cx| { - View::build( - RegFileView { - registers: self.registers.clone(), - }, - cx, - |cx| { - RegTabs { - list: vec!["Lo", "Hi", "Recent"], - } - .build(cx); - - TabView::new(cx, RegTabs::list, |cx, item| match item.get(cx) { - "Lo" => TabPair::new( - move |cx| { - Label::new(cx, item).hoverable(false); - Element::new(cx).class("indicator"); - }, - |cx| range_view(cx, RegStore::lo_range()), - ), - - "Hi" => TabPair::new( - move |cx| { - Label::new(cx, item).hoverable(false); - Element::new(cx).class("indicator"); - }, - |cx| range_view(cx, RegStore::hi_range()), - ), - - "Recent" => TabPair::new( - move |cx| { - Label::new(cx, item).hoverable(false); - Element::new(cx).class("indicator"); - }, - |cx| { - Element::new(cx) - .size(Pixels(200.0)) - .background_color(Color::blue()); - }, - ), - - _ => unreachable!(), - }) - .width(Pixels(500.0)) - .height(Pixels(300.0)); - }, - ) - }) - .overflow(Overflow::Hidden) - .left(Pixels(self.pos.0 - self.width / 2.0)) - .top(Pixels(self.pos.1 - self.height / 2.0)) - .background_color(Color::lightgrey()) - .border_width(Pixels(1.0)) - .border_color(Color::black()) - .width(Pixels(self.width)) - .height(Pixels(self.height)) - } -} - -#[derive(Lens, Clone)] -pub struct RegFileView { - registers: RegStore, -} - -impl View for RegFileView { - fn element(&self) -> Option<&'static str> { - Some("RegView") - } -} diff --git a/mips/src/gui_vizia/mod.rs b/mips/src/gui_vizia/mod.rs deleted file mode 100644 index f188f2c2..00000000 --- a/mips/src/gui_vizia/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod components; diff --git a/mips/src/lib.rs b/mips/src/lib.rs deleted file mode 100644 index facc98ee..00000000 --- a/mips/src/lib.rs +++ /dev/null @@ -1,8 +0,0 @@ -// Library specific to the MIPS architecture -pub mod components; - -#[cfg(feature = "gui-vizia")] -pub mod gui_vizia; - -#[cfg(feature = "gui-egui")] -pub mod gui_egui; diff --git a/mips/src/main.rs b/mips/src/main.rs deleted file mode 100644 index a3e56e2e..00000000 --- a/mips/src/main.rs +++ /dev/null @@ -1,16 +0,0 @@ -#[allow(unused_imports)] -use mips::components::*; -use std::path::PathBuf; -use syncrim::{common::ComponentStore, fern::fern_setup}; -fn main() { - fern_setup(); - - let path = PathBuf::from("mips.json"); - let cs = ComponentStore::load_file(&path); - - #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(cs, &path); - - #[cfg(not(any(feature = "gui-vizia", feature = "gui-egui")))] - let _ = syncrim::common::Simulator::new(cs); -} diff --git a/mips/tests/component_tests.rs b/mips/tests/component_tests.rs deleted file mode 100644 index b6d6328e..00000000 --- a/mips/tests/component_tests.rs +++ /dev/null @@ -1,7 +0,0 @@ -// An example of a test that should panic (fail) -// Useful to assert that illegal models and/or states does not pass unnoticed -#[test] -#[should_panic(expected = "assertion failed")] -fn should_fail() { - assert!(false) -} diff --git a/src/components/mips_controll_unit.rs b/src/components/mips_controll_unit.rs index 68e65fca..1288153b 100644 --- a/src/components/mips_controll_unit.rs +++ b/src/components/mips_controll_unit.rs @@ -1,1011 +1,204 @@ -// use std::fmt::Alignment; -#[cfg(feature = "gui-egui")] -use crate::common::EguiComponent; -use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, +use crate::common::{EguiComponent, Ports, Simulator}; +use crate::components::{alu_op, FullAdd}; +use crate::gui_egui::component_ui::{ + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::offset_helper; +use egui::{ + Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Stroke, TextWrapMode, Ui, + Vec2, }; -use log::trace; -use serde::{Deserialize, Serialize}; -use std::{any::Any, rc::Rc}; - -use super::alu_op; // values used in communication to the alu -use super::data_op; // values used in communication with the data memory -/// The input and output felid ids for the control unit -pub mod cntr_field { - - pub const INSTR_IN: &str = "control_unit_instr_in"; - - /// const REG_DEST_RT: u32 = 0; - /// const REG_DEST_RD: u32 = 1; - /// const REG_DEST_31: u32 = 2; - pub const REG_DEST_OUT: &str = "reg_dest"; - - /// 0 or 1 - pub const REG_WRITE_ENABLE_OUT: &str = "reg_write_enable"; - - /// const WRITE_REG_SRC_ALU:u32 = 0; - /// const WRITE_REG_SRC_MEM:u32 = 1; - pub const REG_WRITE_SRC_OUT: &str = "reg_write_src"; - - /// se module full_adder:alu_op - pub const ALU_OP_OUT: &str = "alu_op"; - - /// const ALU_SRC_A_OP:u32 = 0; - /// const ALU_SRC_A_RS:u32 = 1; - /// const ALU_SRC_A_ZERO:u32 = 3; - pub const ALU_SRC_A_OUT: &str = "alu_src_a"; - - /// const ALU_SRC_B_RT:u32 = 0; - /// const ALU_SRC_B_PC:u32 = 1; - /// const ALU_SRC_B_IMM:u32 = 2; - pub const ALU_SRC_B_OUT: &str = "alu_src_b"; - - // const EXTEND_ZERO:u32 = 0; - // const EXTEND_SIGNED:u32 = 1; - pub const EXTEND_SELECT_OUT: &str = "extend_select"; - - // 0 or 1 - pub const MEM_WRITE_ENABLE_OUT: &str = "mem_write_enable"; - - // 0 or 1, used for co-processor address stuff - pub const BRANCH_INTERRUPT_OUT: &str = "branch_interrupt"; - - // pub const CP0_MFC0 = 0; - // pub const CP0_MTC0 = 1; - // pub const CP0_RFE = 2; - // pub const CP0_SYSCALL = 3; - pub const CP0_OUT: &str = "cp0_out"; - - pub const MMU_OUT: &str = "mmu_out"; - - //TODO - // Opcode is passed to branch unit wich is responsible to controll branch logic - // pub const BRANCH_TYPE_OUT: &str = "branch"; - - //TODO - // NOTE no mem mode, decided to pass opcode to data mem instead, - // might change when LWL/LWR is implemented along with the load/store controller - pub const MEM_MODE_OUT: &str = "mem_mode"; -} - -const NOP: u32 = 0; -const OP_0: u32 = 0; - -const FUNCT_SLL: u32 = 0; -const FUNCT_SRL: u32 = 0b00_0010; -const FUNCT_SRA: u32 = 0b00_0011; -const FUNCT_SLLV: u32 = 0b00_0100; -const FUNCT_SRLV: u32 = 0b00_0110; -const FUNCT_SRAV: u32 = 0b00_111; -const FUNCT_JR: u32 = 0b00_1000; -const FUNCT_JALR: u32 = 0b00_1001; -const SYSCALL: u32 = 0b00_1100; -const FUNCT_ADD: u32 = 0b10_0000; -const FUNCT_ADDU: u32 = 0b10_0001; -const FUNCT_SUB: u32 = 0b10_0010; -const FUNCT_SUBU: u32 = 0b10_0011; -const FUNCT_AND: u32 = 0b10_0100; -const FUNCT_OR: u32 = 0b10_0101; -const FUNCT_XOR: u32 = 0b10_0110; -const FUNCT_NOR: u32 = 0b10_0111; -const FUNCT_SLT: u32 = 0b10_1010; -const FUNCT_SLTU: u32 = 0b10_1011; - -const OP_1: u32 = 1; - -const B_FUNCT_BLTZ: u32 = 0; -const B_FUNCT_BGEZ: u32 = 1; -const B_FUNCT_BLTZAL: u32 = 0b1_0000; -const B_FUNCT_BGEZAL: u32 = 0b1_0001; - -const OP_J: u32 = 0b00_0010; -const OP_JAL: u32 = 0b00_0011; -const OP_BEQ: u32 = 0b00_0100; -const OP_BNE: u32 = 0b00_0101; -const OP_BLEZ: u32 = 0b00_0110; -const OP_BGTZ: u32 = 0b00_0111; - -const OP_ADDI: u32 = 0b00_1000; -const OP_ADDIU: u32 = 0b00_1001; -const OP_SLTI: u32 = 0b00_1010; -const OP_SLTIU: u32 = 0b00_1011; -const OP_ANDI: u32 = 0b00_1100; -const OP_ORI: u32 = 0b00_1101; -const OP_XORI: u32 = 0b00_1110; -const OP_LUI: u32 = 0b00_1111; - -const OP_CP0: u32 = 0b01_0000; -const CP0_FUNCT_MFC0: u32 = 0; -const CP0_FUNCT_MTF0: u32 = 0b0_0100; -const CP0_FUNCT_SPECIAL: u32 = 0b1_0000; -const CP0_FUNCT_SPECIAL_: u32 = 0b1_0000; - -const OP_LB: u32 = 0b10_0000; -const OP_LH: u32 = 0b10_0001; -const OP_LWL: u32 = 0b10_0010; -const OP_LW: u32 = 0b10_0011; -const OP_LBU: u32 = 0b10_0100; -const OP_LHU: u32 = 0b10_0101; -const OP_LWR: u32 = 0b10_0110; - -const OP_SB: u32 = 0b10_1000; -const OP_SH: u32 = 0b10_1001; -const OP_SWL: u32 = 0b10_1010; -const OP_SW: u32 = 0b10_1011; -const OP_SWR: u32 = 0b10_1110; - -/// module used to get what u32 represent. Used for communication between components -pub mod cntr_unit_signals { - pub const REG_DEST_RT: u32 = 0; - pub const REG_DEST_RD: u32 = 1; - pub const REG_DEST_31: u32 = 2; - - pub const REG_WRITE_DISABLE: u32 = 0; - pub const REG_WRITE_ENABLE: u32 = 1; - - pub const MEM_WRITE_DISABLE: u32 = 0; - pub const MEM_WRITE_ENABLE: u32 = 1; - - pub const ALU_SRC_A_SHAMT: u32 = 0; - pub const ALU_SRC_A_RS: u32 = 1; - pub const ALU_SRC_A_ZERO: u32 = 2; - - pub const ALU_SRC_B_RT: u32 = 0; - pub const ALU_SRC_B_PC: u32 = 1; - pub const ALU_SRC_B_IMM: u32 = 2; - - pub const WRITE_REG_SRC_ALU: u32 = 0; - pub const WRITE_REG_SRC_MEM: u32 = 1; - - pub const NO_BRANCH_INTERRUPT: u32 = 0; - pub const BRANCH_INTERRUPT: u32 = 1; - - pub const EXTEND_ZERO: u32 = 0; - pub const EXTEND_SIGNED: u32 = 1; - - pub const CP0_MFC0: u32 = 0; - pub const CP0_MTC0: u32 = 1; - pub const CP0_RFE: u32 = 2; - pub const CP0_SYSCALL: u32 = 3; - - pub const MMU_NORMAL: u32 = 0; - pub const MMU_CP0: u32 = 1; - pub const MMU_NOP: u32 = 2; - - // Note, it was decided to pass opcode to data mem to handle load - // and store instructions there -} -#[derive(Serialize, Deserialize, Clone)] -pub struct ControlUnit { - pub(crate) id: Id, - pub(crate) pos: (f32, f32), - pub(crate) a_in: Input, -} #[typetag::serde] -impl Component for ControlUnit { - fn to_(&self) { - trace!("control_unit"); - } - #[cfg(feature = "gui-egui")] - fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { - let dummy_input = Input::new("dummy", "out"); - Box::new(Rc::new(ControlUnit { - id: "dummy".to_string(), - pos: (0.0, 0.0), - a_in: dummy_input.clone(), - })) - } - fn get_id_ports(&self) -> (Id, Ports) { - ( - self.id.clone(), - Ports::new( - vec![&InputPort { - port_id: cntr_field::INSTR_IN.to_string(), - input: self.a_in.clone(), - }], - OutputType::Combinatorial, - vec![ - cntr_field::REG_DEST_OUT, - cntr_field::REG_WRITE_ENABLE_OUT, - cntr_field::REG_WRITE_SRC_OUT, - cntr_field::ALU_OP_OUT, - cntr_field::ALU_SRC_A_OUT, - cntr_field::ALU_SRC_B_OUT, - cntr_field::EXTEND_SELECT_OUT, - cntr_field::MEM_WRITE_ENABLE_OUT, - cntr_field::BRANCH_INTERRUPT_OUT, - cntr_field::CP0_OUT, - cntr_field::MMU_OUT, - cntr_field::MEM_MODE_OUT, - ], - ), - ) - } +impl EguiComponent for FullAdd { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + // 41x81 + // middle: 21x 41y (0 0) + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + // The shape + ui.painter().add(Shape::closed_line( + vec![ + oh((-20f32, -40f32), s, o), + oh((0f32, -40f32), s, o), + oh((20f32, -20f32), s, o), + oh((20f32, 20f32), s, o), + oh((0f32, 40f32), s, o), + oh((-20f32, 40f32), s, o), + oh((-20f32, 20f32), s, o), + oh((-10f32, 0f32), s, o), + oh((-20f32, -20f32), s, o), + ], + Stroke { + width: scale, + color: Color32::BLACK, + }, + )); + + let rect = Rect { + min: oh((-20f32, -40f32), s, o), + max: oh((20f32, 40f32), s, o), + }; + let op: String = if let Some(s) = simulator { + match TryInto::::try_into(s.get_input_value(&self.op_in)).unwrap() { + alu_op::ADD => "ADD", + alu_op::ADDU => "ADDU", + alu_op::SUB => "SUB", + alu_op::SUBU => "SUBU", + alu_op::AND => "AND", + alu_op::OR => "OR", + alu_op::XOR => "XOR", + alu_op::NOR => "NOR", + alu_op::SLT => "SLT", + alu_op::SLTU => "SLTU", + alu_op::SLL => "SLL", + alu_op::SRL => "SRL", + alu_op::SRA => "SRA", + alu_op::LUI => "LUI", + _ => "UNDEF", + } + .to_string() + } else { + "no sim".to_string() + }; - fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { - match target_port_id.as_str() { - cntr_field::INSTR_IN => self.a_in = new_input, - _ => {} + let _area = Area::new(egui::Id::from(self.id.to_string())) + .order(Order::Middle) + .current_pos(offset.to_pos2() + Vec2::new(5.0, 0.0) * scale) + .movable(false) + .enabled(true) + .interactable(false) + .pivot(Align2::CENTER_CENTER) + .constrain(false) + .show(ui.ctx(), |ui| { + ui.set_clip_rect(clip_rect); + ui.style_mut().wrap_mode = Some(TextWrapMode::Extend); + ui.label(RichText::new(format!("ALU\n{}", op)).size(scale * 12f32)) + }); + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + ui.label("Adder"); + }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), } + Some(vec![r]) } - fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { - let instr_in: u32 = simulator.get_input_value(&self.a_in).try_into().unwrap(); - - let op_code: u32 = (&instr_in >> 26) & 0x0000_003f; - - /// Sets the given field to the given value - macro_rules! set { - ($field:expr, $signal_val:expr) => { - simulator.set_out_value(&self.id, $field, SignalValue::Data($signal_val)) - }; - } - - /// sets the relevant fields for an i instruction - /// OP rt rs imm - /// ALU_OP and EXTEND ned to be set separately - macro_rules! set_i_instr { - () => { - // set target reg to be RT and read from alu - set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_RT); - set!( - cntr_field::REG_WRITE_ENABLE_OUT, - cntr_unit_signals::REG_WRITE_ENABLE - ); - set!( - cntr_field::REG_WRITE_SRC_OUT, - cntr_unit_signals::WRITE_REG_SRC_ALU - ); - - // set alu src to be RS and imm - set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_RS); - set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_IMM); - }; - } - - /// sets the relevant fields for an load operation - /// reg_src = mem - /// reg_dest = rt - /// addu rs (imm sign extended) - /// MEM MODE needs to be set separately - macro_rules! set_load_instr { - () => { - // set target reg to be RT and read from mem - set!( - cntr_field::REG_WRITE_ENABLE_OUT, - cntr_unit_signals::REG_WRITE_ENABLE - ); - set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_RT); - set!( - cntr_field::REG_WRITE_SRC_OUT, - cntr_unit_signals::WRITE_REG_SRC_MEM - ); - - // set alu to be addu with rs and signed imm - set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); - set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_RS); - set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_IMM); - set!( - cntr_field::EXTEND_SELECT_OUT, - cntr_unit_signals::EXTEND_SIGNED - ); - }; - } - macro_rules! set_store_instr { - () => { - // SET reg_write to disabled nad mem write to enable - set!( - cntr_field::REG_WRITE_ENABLE_OUT, - cntr_unit_signals::REG_WRITE_DISABLE - ); - set!( - cntr_field::MEM_WRITE_ENABLE_OUT, - cntr_unit_signals::MEM_WRITE_ENABLE - ); - - // set alu to be addu with rs and signed imm - set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); - set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_RS); - set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_IMM); - set!( - cntr_field::EXTEND_SELECT_OUT, - cntr_unit_signals::EXTEND_SIGNED - ); - }; - } - - set!( - cntr_field::REG_WRITE_ENABLE_OUT, - cntr_unit_signals::REG_WRITE_DISABLE - ); - set!( - cntr_field::MEM_WRITE_ENABLE_OUT, - cntr_unit_signals::MEM_WRITE_DISABLE - ); - set!( - cntr_field::BRANCH_INTERRUPT_OUT, - cntr_unit_signals::NO_BRANCH_INTERRUPT - ); - set!(cntr_field::MEM_MODE_OUT, data_op::NO_OP); - //TODO an idea would be to init all variables - // let alu_src_a : Signal; - // this would make the compiler force us to populate all paths so to not let any signal be undefined - // It would be more code, but would hopefully be more "secure" as it would stop us from forgetting a value - // another idea is to set all signals to uninitialized or dont care for better debugging - - // match the opcode - match op_code { - OP_0 => { - let funct: u32 = &instr_in & 0x0000_003f; - - set!( - cntr_field::REG_WRITE_ENABLE_OUT, - cntr_unit_signals::REG_WRITE_ENABLE - ); // overwritten by JR and SYSCALL to disabled - - set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_RD); // overwritten by JALR to REG_DEST_31 - set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_RS); // overwritten by JALR, SRA, SRL to shamt or zero - set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_RT); // overwritten by JALR to PC - set!( - cntr_field::REG_WRITE_SRC_OUT, - cntr_unit_signals::WRITE_REG_SRC_ALU - ); - set!( - cntr_field::BRANCH_INTERRUPT_OUT, - cntr_unit_signals::NO_BRANCH_INTERRUPT - ); // overiden by jr and jalr - - match funct { - FUNCT_SLL => { - set!( - cntr_field::ALU_SRC_A_OUT, - cntr_unit_signals::ALU_SRC_A_SHAMT - ); - set!(cntr_field::ALU_OP_OUT, alu_op::SLL); - Ok(()) - } - FUNCT_SRL => { - set!( - cntr_field::ALU_SRC_A_OUT, - cntr_unit_signals::ALU_SRC_A_SHAMT - ); - set!(cntr_field::ALU_OP_OUT, alu_op::SRL); - Ok(()) - } - FUNCT_SRA => { - set!( - cntr_field::ALU_SRC_A_OUT, - cntr_unit_signals::ALU_SRC_A_SHAMT - ); - set!(cntr_field::ALU_OP_OUT, alu_op::SRA); - Ok(()) - } - FUNCT_SLLV => { - set!(cntr_field::ALU_OP_OUT, alu_op::SLL); - Ok(()) - } - FUNCT_SRLV => { - set!(cntr_field::ALU_OP_OUT, alu_op::SRL); - Ok(()) - } - FUNCT_SRAV => { - set!(cntr_field::ALU_OP_OUT, alu_op::SRL); - Ok(()) - } - FUNCT_JR => { - set!( - cntr_field::BRANCH_INTERRUPT_OUT, - cntr_unit_signals::BRANCH_INTERRUPT - ); - set!( - cntr_field::REG_WRITE_ENABLE_OUT, - cntr_unit_signals::REG_WRITE_DISABLE - ); - Ok(()) - } - FUNCT_JALR => { - set!( - cntr_field::BRANCH_INTERRUPT_OUT, - cntr_unit_signals::BRANCH_INTERRUPT - ); - set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_RD); // this is different from syncsim as there its defined as 31, but that dosen't match mips documentation; - set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_ZERO); - set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_PC); - set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); - Ok(()) - } - SYSCALL => { - set!( - cntr_field::REG_WRITE_ENABLE_OUT, - cntr_unit_signals::REG_WRITE_DISABLE - ); - set!(cntr_field::CP0_OUT, cntr_unit_signals::CP0_SYSCALL); - Ok(()) - } - FUNCT_ADD => { - set!(cntr_field::ALU_OP_OUT, alu_op::ADD); - Ok(()) - } - FUNCT_ADDU => { - set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); - Ok(()) - } - FUNCT_SUB => { - set!(cntr_field::ALU_OP_OUT, alu_op::SUB); - Ok(()) - } - FUNCT_SUBU => { - set!(cntr_field::ALU_OP_OUT, alu_op::SUBU); - Ok(()) - } - FUNCT_AND => { - set!(cntr_field::ALU_OP_OUT, alu_op::AND); - Ok(()) - } - FUNCT_OR => { - set!(cntr_field::ALU_OP_OUT, alu_op::OR); - Ok(()) - } - FUNCT_XOR => { - set!(cntr_field::ALU_OP_OUT, alu_op::XOR); - Ok(()) - } - FUNCT_NOR => { - set!(cntr_field::ALU_OP_OUT, alu_op::NOR); - Ok(()) - } - FUNCT_SLT => { - set!(cntr_field::ALU_OP_OUT, alu_op::SLT); - Ok(()) - } - FUNCT_SLTU => { - set!(cntr_field::ALU_OP_OUT, alu_op::SLTU); - Ok(()) - } - _ => Err(Condition::Error(format!( - "unknown funct {:#08b} for opcode 0b000000", - funct - ))), - } - } - OP_1 => { - // branch stuff, BGEZ BGEZAL BLTZ BLTZAL, - // Note many branch and jump instructions are actually pseudo instructions and will be compiled to others - // BAL => BGEZAL r0 offset - let tmp: u32 = simulator.get_input_signal(&self.a_in).try_into().unwrap(); - let b_funct: u32 = (tmp >> 16) & 0b11111; - - set!( - cntr_field::BRANCH_INTERRUPT_OUT, - cntr_unit_signals::BRANCH_INTERRUPT - ); - set!( - cntr_field::EXTEND_SELECT_OUT, - cntr_unit_signals::EXTEND_SIGNED - ); - match b_funct { - B_FUNCT_BGEZ | B_FUNCT_BLTZ => Ok(()), - B_FUNCT_BGEZAL | B_FUNCT_BLTZAL => { - // save pc to reg - set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_31); - set!( - cntr_field::REG_WRITE_ENABLE_OUT, - cntr_unit_signals::REG_WRITE_ENABLE - ); - set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); - set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_ZERO); - set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_PC); - set!( - cntr_field::REG_WRITE_SRC_OUT, - cntr_unit_signals::WRITE_REG_SRC_ALU - ); - Ok(()) - } - _ => Err(Condition::Error(format!( - "unknown funct {:#07b} for opcode 0b000001", - b_funct - ))), - } - } - OP_J => { - set!( - cntr_field::BRANCH_INTERRUPT_OUT, - cntr_unit_signals::BRANCH_INTERRUPT - ); - Ok(()) - } - OP_JAL => { - set!( - cntr_field::BRANCH_INTERRUPT_OUT, - cntr_unit_signals::BRANCH_INTERRUPT - ); - set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_31); - set!( - cntr_field::REG_WRITE_ENABLE_OUT, - cntr_unit_signals::REG_WRITE_ENABLE - ); - set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); - set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_ZERO); - set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_PC); - set!( - cntr_field::REG_WRITE_SRC_OUT, - cntr_unit_signals::WRITE_REG_SRC_ALU - ); - Ok(()) - } - OP_BEQ | OP_BNE | OP_BLEZ | OP_BGTZ => { - set!( - cntr_field::BRANCH_INTERRUPT_OUT, - cntr_unit_signals::BRANCH_INTERRUPT - ); - set!( - cntr_field::EXTEND_SELECT_OUT, - cntr_unit_signals::EXTEND_SIGNED - ); - Ok(()) - } - OP_ADDI => { - set_i_instr!(); - set!( - cntr_field::EXTEND_SELECT_OUT, - cntr_unit_signals::EXTEND_SIGNED - ); - set!(cntr_field::ALU_OP_OUT, alu_op::ADD); - Ok(()) - } - OP_ADDIU => { - set_i_instr!(); - set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); - Ok(()) - } - OP_SLTI => { - set_i_instr!(); - set!( - cntr_field::EXTEND_SELECT_OUT, - cntr_unit_signals::EXTEND_SIGNED - ); - set!(cntr_field::ALU_OP_OUT, alu_op::SLT); - Ok(()) - } - OP_SLTIU => { - set_i_instr!(); - set!( - cntr_field::EXTEND_SELECT_OUT, - cntr_unit_signals::EXTEND_ZERO - ); - set!(cntr_field::ALU_OP_OUT, alu_op::SLTU); - Ok(()) - } - OP_ANDI => { - set_i_instr!(); - set!( - cntr_field::EXTEND_SELECT_OUT, - cntr_unit_signals::EXTEND_ZERO - ); - set!(cntr_field::ALU_OP_OUT, alu_op::AND); - Ok(()) - } - OP_ORI => { - set_i_instr!(); - set!( - cntr_field::EXTEND_SELECT_OUT, - cntr_unit_signals::EXTEND_ZERO - ); - set!(cntr_field::ALU_OP_OUT, alu_op::OR); - Ok(()) - } - OP_XORI => { - set_i_instr!(); - set!( - cntr_field::EXTEND_SELECT_OUT, - cntr_unit_signals::EXTEND_ZERO - ); - set!(cntr_field::ALU_OP_OUT, alu_op::XOR); - Ok(()) - } - OP_LUI => { - set_i_instr!(); - set!( - cntr_field::EXTEND_SELECT_OUT, - cntr_unit_signals::EXTEND_ZERO - ); - set!(cntr_field::ALU_OP_OUT, alu_op::LUI); - Ok(()) - } - OP_CP0 => { - // let cp0_funct:u32 = (&instr_in >> 21) & 0b11111; - // match cp0_funct { - // CP0_FUNCT_MFC0 =>{ - // set!(cntr_field::REG_DEST_OUT,cntr_unit_signals::REG_DEST_RT); - // set!(cntr_field::REG_WRITE_ENABLE_OUT, cntr_unit_signals::REG_WRITE_ENABLE); - - // //TODO no idea why alu would be required for this operation and cant find any path in syncsim, - // // but following blindly. If time permits figure out why and change - // set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); - // set!(cntr_field::ALU_SRC_A_OUT,cntr_unit_signals::ALU_SRC_A_SHAMT); - // set!(cntr_field::ALU_SRC_B_OUT,cntr_unit_signals::ALU_SRC_B_IMM); - // todo!("implement memory mode to complete MFC0") - - // } - // _ => { - // Err(Condition::Error(format!("unknown funct {:#07b}for opcode {:#08b} CP0", cp0_funct, OP_CP0))) - // } - // } - Err(Condition::Error(format!( - "CP0 instructions not yet implemented" - ))) - } - //TODO use mem_mode, now it assumed data_mem uses opcode to determine that itself - OP_LB => { - set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_BYTE); - set_load_instr!(); - Ok(()) - } - OP_LBU => { - set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_BYTE_U); - set_load_instr!(); - Ok(()) - } - OP_LH => { - set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_HALF); - set_load_instr!(); - Ok(()) - } - OP_LHU => { - set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_HALF_U); - set_load_instr!(); - Ok(()) - } - OP_LW => { - set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_WORD); - set_load_instr!(); - Ok(()) - } - - OP_SB => { - set!(cntr_field::MEM_MODE_OUT, data_op::STORE_BYTE); - set_store_instr!(); - Ok(()) - } - OP_SH => { - set!(cntr_field::MEM_MODE_OUT, data_op::STORE_HALF); - set_store_instr!(); - Ok(()) - } - OP_SW => { - set!(cntr_field::MEM_MODE_OUT, data_op::STORE_WORD); - set_store_instr!(); - Ok(()) - } - - OP_LWL | OP_LWR | OP_SWL | OP_SWR => Err(Condition::Error( - "LWL, LWR, SWL and SWR are not implemented".to_string(), - )), - - _ => Err(Condition::Error(format!("Unknown opcode {:#08b}", op_code))), + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let r_vec = FullAdd::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_drag_value(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.a_in, + crate::components::FULL_ADD_A_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.b_in, + crate::components::FULL_ADD_B_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.op_in, + crate::components::FULL_ADD_OP_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown + }, + ); + EditorRenderReturn { + delete, + resp: Some(r_vec), } } - fn as_any(&self) -> &dyn Any { - self + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + crate::components::SEXT_IN_ID.to_string(), + Pos2::new(-40f32, 0f32) + own_pos, + ), + ( + crate::components::SEXT_OUT_ID.to_string(), + Pos2::new(40f32, 0f32) + own_pos, + ), + ] } -} -impl ControlUnit { - pub fn new(id: &str, pos: (f32, f32), a_in: Input) -> Self { - ControlUnit { - id: id.to_string(), - pos, - a_in, - } + fn top_padding(&self) -> f32 { + 20f32 } - pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input) -> Rc { - Rc::new(ControlUnit::new(id, pos, a_in)) + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; } -} -#[cfg(test)] -mod test { - use crate::{common::ComponentStore, components::ProbeOut}; - - use super::*; - - fn setup_simulator() -> Simulator { - let cs = ComponentStore { - store: vec![ - Rc::new(ProbeOut::new("instr")), - ControlUnit::rc_new("cntr", (0.0, 0.0), Input::new("instr", "out")), - ], - }; - Simulator::new(cs).unwrap() - } - /// This tests - /// - beq t3 t0 7 => 000100 01011 01000 0000000000000111 - /// - xori $t6,$s4,32 => 001110 10100 01110 0000000000100000 - /// - sub $t0,$a0,$t0 => 000000 00100 01000 01000 00000 100010 - /// - lh $a1,14($s1) => 100001 10001 00101 0000000000001110 - /// - jal => 000011 10101010101010101010101010 - /// - jalr r10 r18 => 000000_10010_00000_01010_00000_001001 - #[test] - fn test_random_instrs() { - let mut sim = setup_simulator(); - - assert_eq!(sim.cycle, 1); - - println!("testing beq t3 t0 7 => 000100 01011 01000 0000000000000111"); - sim.set_out_value("instr", "out", 0b000100_01011_01000_0000000000000111); - println!("clock sim"); - sim.clock(); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), - cntr_unit_signals::BRANCH_INTERRUPT.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), - cntr_unit_signals::REG_WRITE_DISABLE.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), - cntr_unit_signals::MEM_WRITE_DISABLE.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::EXTEND_SELECT_OUT)), - cntr_unit_signals::EXTEND_SIGNED.into() - ); - - println!("testing xori $t6,$s4,32 => 001110 10100 01110 0000000000100000"); - sim.set_out_value("instr", "out", 0b001110_10100_01110_0000000000100000); - println!("clock sim"); - sim.clock(); - // no branch or mem write - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), - cntr_unit_signals::NO_BRANCH_INTERRUPT.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), - cntr_unit_signals::MEM_WRITE_DISABLE.into() - ); - - // reg write, src alu and reg_dest rt, since rd is occupied by imm - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), - cntr_unit_signals::REG_WRITE_ENABLE.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), - cntr_unit_signals::WRITE_REG_SRC_ALU.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), - cntr_unit_signals::REG_DEST_RT.into() - ); - - // ALU xor rs and imm zero extend - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::EXTEND_SELECT_OUT)), - cntr_unit_signals::EXTEND_ZERO.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), - cntr_unit_signals::ALU_SRC_A_RS.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), - cntr_unit_signals::ALU_SRC_B_IMM.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), - alu_op::XOR.into() - ); - - print!("testing sub $t0,$a0,$t0 => 000000 00100 01000 01000 00000 100010"); - sim.set_out_value("instr", "out", 0b000000_00100_01000_01000_00000_100010); - println!("clock sim"); - sim.clock(); - // no branch or mem write - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), - cntr_unit_signals::NO_BRANCH_INTERRUPT.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), - cntr_unit_signals::MEM_WRITE_DISABLE.into() - ); - // reg write, src alu and reg_dest rd - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), - cntr_unit_signals::REG_WRITE_ENABLE.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), - cntr_unit_signals::WRITE_REG_SRC_ALU.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), - cntr_unit_signals::REG_DEST_RD.into(), - ); - - // ALU sub rs and rt - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), - cntr_unit_signals::ALU_SRC_A_RS.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), - cntr_unit_signals::ALU_SRC_B_RT.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), - alu_op::SUB.into() - ); - - print!("testing lh $a1,14($s1) => 100001 10001 00101 0000000000001110"); - sim.set_out_value("instr", "out", 0b100001_10001_00101_0000000000001110); - println!("clock sim"); - sim.clock(); - // reg write, no branch, no mem write - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), - cntr_unit_signals::NO_BRANCH_INTERRUPT.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), - cntr_unit_signals::MEM_WRITE_DISABLE.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), - cntr_unit_signals::REG_WRITE_ENABLE.into() - ); - - // reg dst rt, reg src mem - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), - cntr_unit_signals::WRITE_REG_SRC_MEM.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), - cntr_unit_signals::REG_DEST_RT.into() - ); - - // ADDU rs imm (signed) - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::EXTEND_SELECT_OUT)), - cntr_unit_signals::EXTEND_SIGNED.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), - cntr_unit_signals::ALU_SRC_A_RS.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), - cntr_unit_signals::ALU_SRC_B_IMM.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), - alu_op::ADDU.into() - ); - - println!("testing SW $r2 4($r3) => 101011 00011 00010 0000_0000_0000_0100"); - sim.set_out_value("instr", "out", 0b101011_00011_00010_0000_0000_0000_0100); - println!("clock sim"); - sim.clock(); - // no reg write, no branch, mem write - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), - cntr_unit_signals::NO_BRANCH_INTERRUPT.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), - cntr_unit_signals::MEM_WRITE_ENABLE.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), - cntr_unit_signals::REG_WRITE_DISABLE.into() - ); - - // ADDU rs imm (signed) - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::EXTEND_SELECT_OUT)), - cntr_unit_signals::EXTEND_SIGNED.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), - cntr_unit_signals::ALU_SRC_A_RS.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), - cntr_unit_signals::ALU_SRC_B_IMM.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), - alu_op::ADDU.into() - ); - - println!("testing jal => 000011 10101010101010101010101010 "); - sim.set_out_value("instr", "out", 0b000011_10101010101010101010101010); - println!("clock sim"); - sim.clock(); - // reg write, branch, no mem write - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), - cntr_unit_signals::BRANCH_INTERRUPT.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), - cntr_unit_signals::MEM_WRITE_DISABLE.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), - cntr_unit_signals::REG_WRITE_ENABLE.into() - ); - - // ALU zero + pc - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), - cntr_unit_signals::ALU_SRC_A_ZERO.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), - cntr_unit_signals::ALU_SRC_B_PC.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), - alu_op::ADDU.into() - ); - - // reg dst 31, reg src alu - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), - cntr_unit_signals::WRITE_REG_SRC_ALU.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), - cntr_unit_signals::REG_DEST_31.into() - ); - - println!("testing jalr r10 r18 => 000000_10010_00000_01010_00000_001001"); - sim.set_out_value("instr", "out", 0b000000_10010_00000_01010_00000_001001); - println!("clock sim"); - sim.clock(); - // reg write, branch, no mem write - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::BRANCH_INTERRUPT_OUT)), - cntr_unit_signals::BRANCH_INTERRUPT.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::MEM_WRITE_ENABLE_OUT)), - cntr_unit_signals::MEM_WRITE_DISABLE.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_ENABLE_OUT)), - cntr_unit_signals::REG_WRITE_ENABLE.into() - ); - - // ALU zero + pc - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_A_OUT)), - cntr_unit_signals::ALU_SRC_A_ZERO.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_SRC_B_OUT)), - cntr_unit_signals::ALU_SRC_B_PC.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::ALU_OP_OUT)), - alu_op::ADDU.into() - ); - - // reg dst rd, reg src alu - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_WRITE_SRC_OUT)), - cntr_unit_signals::WRITE_REG_SRC_ALU.into() - ); - assert_eq!( - sim.get_input_value(&Input::new("cntr", cntr_field::REG_DEST_OUT)), - cntr_unit_signals::REG_DEST_RD.into() - ); + fn get_pos(&self) -> (f32, f32) { + self.pos } } diff --git a/src/components/mod.rs b/src/components/mod.rs index a70d93e0..97a81efd 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -4,15 +4,15 @@ mod clk; mod constant; mod cross; mod equals; -mod full_adder; +//mod full_adder; mod mem; mod mips_branch_logic; -mod mips_controll_unit; -mod mips_dm; +//mod mips_controll_unit; +//mod mips_dm; mod mips_im; mod mips_instruction_splitter; mod mips_jump_merge; -mod mips_mem_struct; +pub mod mips_mem_struct; mod mips_reg_file; mod mux; mod probe; @@ -23,7 +23,7 @@ mod probe_stim; mod register; mod sext; mod shift_left_const; -mod sz_extend; +//mod sz_extend; mod wire; mod zero_extend; @@ -33,15 +33,15 @@ pub use clk::*; pub use constant::*; pub use cross::*; pub use equals::*; -pub use full_adder::*; +pub use mips_mem_struct::*; +//pub use full_adder::*; pub use mem::*; pub use mips_branch_logic::*; -pub use mips_controll_unit::*; -pub use mips_dm::*; +//pub use mips_controll_unit::*; +//pub use mips_dm::*; pub use mips_im::*; pub use mips_instruction_splitter::*; pub use mips_jump_merge::*; -pub use mips_mem_struct::*; pub use mips_reg_file::*; pub use mux::*; pub use probe::*; @@ -52,6 +52,6 @@ pub use probe_stim::*; pub use register::*; pub use sext::*; pub use shift_left_const::*; -pub use sz_extend::*; +//pub use sz_extend::*; pub use wire::*; pub use zero_extend::*; diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index c8109fe6..f4b1584f 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -4,11 +4,11 @@ mod clk; mod constant; mod cross; mod equal; -mod full_adder; +//mod full_adder; mod mem; mod mips_branch_logic; -mod mips_controll_unit; -mod mips_dm; +//mod mips_controll_unit; +//mod mips_dm; mod mips_im; mod mips_instruction_splitter; mod mips_jump_merge; @@ -22,6 +22,6 @@ mod probe_stim; mod register; mod sext; mod shift_left_const; -mod sz_extend; +//mod sz_extend; mod wire; mod zero_extend; diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index e6641f62..de7a20b8 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -138,35 +138,6 @@ impl Default for Library { pos: (0.0, 0.0), clk_in: dummy_input.clone(), }), - Rc::new(ControlUnit { - id: "a_in".to_string(), - pos: (0.0, 0.0), - a_in: dummy_input.clone(), - }), - // Rc::new(InstrMem { - // width: INSTR_MEM_WIDTH, - // height: INSTR_MEM_HEIGHT, - // id: "instruction".to_string(), - // pos: (0.0, 0.0), - // bytes: BTreeMap::new(), - // pc: dummy_input, - // range: Range { - // start: 0, - // end: 0x1000, - // }, - // breakpoints: Rc::new(RefCell::new(HashSet::new())), - // symbols: HashMap::new(), - // le: true, - // }), - Rc::new( - (FullAdd { - id: "dummy".to_string(), - pos: (0.0, 0.0), - a_in: dummy_input.clone(), - b_in: dummy_input.clone(), - op_in: dummy_input.clone(), - }), - ), ]; Library(library) } From c5ca4127b799573a02729dfe2ffbc11be3dcb2ba Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Tue, 3 Sep 2024 12:37:06 +0200 Subject: [PATCH 082/126] moved more components to mips-lib --- mips-lib/Cargo.toml | 1 + .../src}/components/mips_branch_logic.rs | 10 +- mips-lib/src/components/mips_control_unit.rs | 2 +- mips-lib/src/components/mips_dm.rs | 12 +- {src => mips-lib/src}/components/mips_im.rs | 16 +- .../components/mips_instruction_splitter.rs | 10 +- .../src}/components/mips_jump_merge.rs | 10 +- .../src}/components/mips_mem_struct.rs | 0 .../src}/components/mips_reg_file.rs | 12 +- mips-lib/src/components/mod.rs | 12 + .../gui_egui/{ => components}/full_adder.rs | 0 .../gui_egui/components/mips_branch_logic.rs | 8 +- .../{ => components}/mips_control_unit.rs | 0 .../src/gui_egui/{ => components}/mips_dm.rs | 0 .../src}/gui_egui/components/mips_im.rs | 11 +- .../components/mips_instruction_splitter.rs | 8 +- .../gui_egui/components/mips_jump_merge.rs | 8 +- .../src}/gui_egui/components/mips_reg_file.rs | 8 +- mips-lib/src/gui_egui/components/mod.rs | 9 + .../gui_egui/{ => components}/sz_extend.rs | 0 .../src}/gui_egui/mips_mem_view_window.rs | 5 +- mips-lib/src/gui_egui/mod.rs | 6 +- src/components/full_adder.rs | 309 --------------- src/components/mips_controll_unit.rs | 204 ---------- src/components/mips_dm.rs | 373 ------------------ src/components/mod.rs | 18 - src/components/sz_extend.rs | 126 ------ src/gui_egui/components/full_adder.rs | 204 ---------- src/gui_egui/components/mips_controll_unit.rs | 70 ---- src/gui_egui/components/mips_dm.rs | 99 ----- src/gui_egui/components/mod.rs | 9 - src/gui_egui/mod.rs | 1 - 32 files changed, 81 insertions(+), 1480 deletions(-) rename {src => mips-lib/src}/components/mips_branch_logic.rs (99%) rename {src => mips-lib/src}/components/mips_im.rs (92%) rename {src => mips-lib/src}/components/mips_instruction_splitter.rs (98%) rename {src => mips-lib/src}/components/mips_jump_merge.rs (98%) rename {src => mips-lib/src}/components/mips_mem_struct.rs (100%) rename {src => mips-lib/src}/components/mips_reg_file.rs (99%) rename mips-lib/src/gui_egui/{ => components}/full_adder.rs (100%) rename {src => mips-lib/src}/gui_egui/components/mips_branch_logic.rs (85%) rename mips-lib/src/gui_egui/{ => components}/mips_control_unit.rs (100%) rename mips-lib/src/gui_egui/{ => components}/mips_dm.rs (100%) rename {src => mips-lib/src}/gui_egui/components/mips_im.rs (91%) rename {src => mips-lib/src}/gui_egui/components/mips_instruction_splitter.rs (87%) rename {src => mips-lib/src}/gui_egui/components/mips_jump_merge.rs (85%) rename {src => mips-lib/src}/gui_egui/components/mips_reg_file.rs (95%) create mode 100644 mips-lib/src/gui_egui/components/mod.rs rename mips-lib/src/gui_egui/{ => components}/sz_extend.rs (100%) rename {src => mips-lib/src}/gui_egui/mips_mem_view_window.rs (99%) delete mode 100644 src/components/full_adder.rs delete mode 100644 src/components/mips_controll_unit.rs delete mode 100644 src/components/mips_dm.rs delete mode 100644 src/components/sz_extend.rs delete mode 100644 src/gui_egui/components/full_adder.rs delete mode 100644 src/gui_egui/components/mips_controll_unit.rs delete mode 100644 src/gui_egui/components/mips_dm.rs diff --git a/mips-lib/Cargo.toml b/mips-lib/Cargo.toml index 083e9d89..cef76a78 100644 --- a/mips-lib/Cargo.toml +++ b/mips-lib/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +MIPS_disassembly = "0.1.2" anyhow = "1.0.72" clap = { version = "4.3.15", features = ["derive"] } elf = "0.7.4" diff --git a/src/components/mips_branch_logic.rs b/mips-lib/src/components/mips_branch_logic.rs similarity index 99% rename from src/components/mips_branch_logic.rs rename to mips-lib/src/components/mips_branch_logic.rs index 91f3a896..ad41912c 100644 --- a/src/components/mips_branch_logic.rs +++ b/mips-lib/src/components/mips_branch_logic.rs @@ -1,13 +1,13 @@ // use std::fmt::Alignment; -#[cfg(feature = "gui-egui")] -use crate::common::EguiComponent; -use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, -}; use log::*; use serde::{Deserialize, Serialize}; use std::any::Any; use std::rc::Rc; +#[cfg(feature = "gui-egui")] +use syncrim::common::EguiComponent; +use syncrim::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, +}; pub const BRANCH_OP_ID: &str = "branch_op_in"; pub const BRANCH_RT_ID: &str = "branch_rt_in"; diff --git a/mips-lib/src/components/mips_control_unit.rs b/mips-lib/src/components/mips_control_unit.rs index 42618aa4..3f47c790 100644 --- a/mips-lib/src/components/mips_control_unit.rs +++ b/mips-lib/src/components/mips_control_unit.rs @@ -707,7 +707,7 @@ impl ControlUnit { } #[cfg(test)] mod test { - use crate::{common::ComponentStore, components::ProbeOut}; + use syncrim::{common::ComponentStore, components::ProbeOut}; use super::*; diff --git a/mips-lib/src/components/mips_dm.rs b/mips-lib/src/components/mips_dm.rs index 7e853aed..5f7a9fcb 100644 --- a/mips-lib/src/components/mips_dm.rs +++ b/mips-lib/src/components/mips_dm.rs @@ -1,18 +1,14 @@ +use crate::gui_egui::mips_mem_view_window::MemViewWindow; use core::cell::RefCell; use log::*; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, rc::Rc}; #[cfg(feature = "gui-egui")] use syncrim::common::EguiComponent; -use syncrim::{ - common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}, - gui_egui::mips_mem_view_window::MemViewWindow, -}; +use syncrim::common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}; -use syncrim::components::{ - mips_mem_struct::{MemOpSize, MemWriteReturn, MipsMem}, - RegFile, -}; +use crate::components::mips_mem_struct::{MemOpSize, MemWriteReturn, MipsMem}; +use crate::components::RegFile; pub mod data_op { pub const NO_OP: u32 = 0; diff --git a/src/components/mips_im.rs b/mips-lib/src/components/mips_im.rs similarity index 92% rename from src/components/mips_im.rs rename to mips-lib/src/components/mips_im.rs index 81235400..29dbd068 100644 --- a/src/components/mips_im.rs +++ b/mips-lib/src/components/mips_im.rs @@ -1,18 +1,14 @@ -#[cfg(feature = "gui-egui")] -use crate::common::EguiComponent; -use crate::{ - common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}, - gui_egui::mips_mem_view_window::MemViewWindow, -}; use core::cell::RefCell; use log::*; use serde::{Deserialize, Serialize}; use std::{any::Any, rc::Rc}; +#[cfg(feature = "gui-egui")] +use syncrim::common::EguiComponent; +use syncrim::common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}; -use super::{ - mips_mem_struct::{MemOpSize, MipsMem}, - RegFile, -}; +use crate::components::mips_mem_struct::{MemOpSize, MipsMem}; +use crate::components::RegFile; +use crate::gui_egui::mips_mem_view_window::MemViewWindow; pub const INSTR_MEM_PC_ID: &str = "pc"; diff --git a/src/components/mips_instruction_splitter.rs b/mips-lib/src/components/mips_instruction_splitter.rs similarity index 98% rename from src/components/mips_instruction_splitter.rs rename to mips-lib/src/components/mips_instruction_splitter.rs index e606096a..f23bd7fd 100644 --- a/src/components/mips_instruction_splitter.rs +++ b/mips-lib/src/components/mips_instruction_splitter.rs @@ -1,13 +1,13 @@ // use std::fmt::Alignment; -#[cfg(feature = "gui-egui")] -use crate::common::EguiComponent; -use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, -}; use log::*; use serde::{Deserialize, Serialize}; use std::any::Any; use std::rc::Rc; +#[cfg(feature = "gui-egui")] +use syncrim::common::EguiComponent; +use syncrim::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, +}; pub const INSTRUCTION_SPLITTER_IN_ID: &str = "instruction_in"; diff --git a/src/components/mips_jump_merge.rs b/mips-lib/src/components/mips_jump_merge.rs similarity index 98% rename from src/components/mips_jump_merge.rs rename to mips-lib/src/components/mips_jump_merge.rs index c8b62a1d..b626ad52 100644 --- a/src/components/mips_jump_merge.rs +++ b/mips-lib/src/components/mips_jump_merge.rs @@ -1,13 +1,13 @@ // use std::fmt::Alignment; -#[cfg(feature = "gui-egui")] -use crate::common::EguiComponent; -use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, -}; use log::*; use serde::{Deserialize, Serialize}; use std::any::Any; use std::rc::Rc; +#[cfg(feature = "gui-egui")] +use syncrim::common::EguiComponent; +use syncrim::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, +}; pub const MERGE_INSTR_ADDR_ID: &str = "merge_instr_addr_in"; pub const MERGE_JUMP_ADDR_ID: &str = "merge_jump_addr_in"; diff --git a/src/components/mips_mem_struct.rs b/mips-lib/src/components/mips_mem_struct.rs similarity index 100% rename from src/components/mips_mem_struct.rs rename to mips-lib/src/components/mips_mem_struct.rs diff --git a/src/components/mips_reg_file.rs b/mips-lib/src/components/mips_reg_file.rs similarity index 99% rename from src/components/mips_reg_file.rs rename to mips-lib/src/components/mips_reg_file.rs index c37b91aa..4fb5f1dc 100644 --- a/src/components/mips_reg_file.rs +++ b/mips-lib/src/components/mips_reg_file.rs @@ -1,10 +1,4 @@ // use std::fmt::Alignment; -#[cfg(feature = "gui-egui")] -use crate::common::EguiComponent; -use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, - SignalValue, Simulator, -}; use log::*; use serde::{Deserialize, Serialize}; use std::any::Any; @@ -12,6 +6,12 @@ use std::cell::RefCell; use std::collections::BTreeMap; use std::ops::Deref; use std::rc::Rc; +#[cfg(feature = "gui-egui")] +use syncrim::common::EguiComponent; +use syncrim::common::{ + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, + SignalValue, Simulator, +}; pub mod reg_file_fields { pub const RS_ADDRESS_IN_ID: &str = "rs_address_in"; diff --git a/mips-lib/src/components/mod.rs b/mips-lib/src/components/mod.rs index cea5f7f3..4a14d7d3 100644 --- a/mips-lib/src/components/mod.rs +++ b/mips-lib/src/components/mod.rs @@ -1,9 +1,21 @@ mod full_adder; +mod mips_branch_logic; mod mips_control_unit; mod mips_dm; +mod mips_im; +mod mips_instruction_splitter; +mod mips_jump_merge; +mod mips_mem_struct; +mod mips_reg_file; mod sz_extend; pub use full_adder::*; +pub use mips_branch_logic::*; pub use mips_control_unit::*; pub use mips_dm::*; +pub use mips_im::*; +pub use mips_instruction_splitter::*; +pub use mips_jump_merge::*; +pub use mips_mem_struct::*; +pub use mips_reg_file::*; pub use sz_extend::*; diff --git a/mips-lib/src/gui_egui/full_adder.rs b/mips-lib/src/gui_egui/components/full_adder.rs similarity index 100% rename from mips-lib/src/gui_egui/full_adder.rs rename to mips-lib/src/gui_egui/components/full_adder.rs diff --git a/src/gui_egui/components/mips_branch_logic.rs b/mips-lib/src/gui_egui/components/mips_branch_logic.rs similarity index 85% rename from src/gui_egui/components/mips_branch_logic.rs rename to mips-lib/src/gui_egui/components/mips_branch_logic.rs index 42e4399b..ff46a288 100644 --- a/src/gui_egui/components/mips_branch_logic.rs +++ b/mips-lib/src/gui_egui/components/mips_branch_logic.rs @@ -1,9 +1,9 @@ -use crate::common::{EguiComponent, Id, Ports, Simulator}; use crate::components::BranchLogic; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; -use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::basic_component_gui; use egui::{Rect, Response, RichText, Ui, Vec2}; +use syncrim::common::{EguiComponent, Id, Ports, Simulator}; +use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use syncrim::gui_egui::gui::EguiExtra; +use syncrim::gui_egui::helper::basic_component_gui; #[typetag::serde] impl EguiComponent for BranchLogic { diff --git a/mips-lib/src/gui_egui/mips_control_unit.rs b/mips-lib/src/gui_egui/components/mips_control_unit.rs similarity index 100% rename from mips-lib/src/gui_egui/mips_control_unit.rs rename to mips-lib/src/gui_egui/components/mips_control_unit.rs diff --git a/mips-lib/src/gui_egui/mips_dm.rs b/mips-lib/src/gui_egui/components/mips_dm.rs similarity index 100% rename from mips-lib/src/gui_egui/mips_dm.rs rename to mips-lib/src/gui_egui/components/mips_dm.rs diff --git a/src/gui_egui/components/mips_im.rs b/mips-lib/src/gui_egui/components/mips_im.rs similarity index 91% rename from src/gui_egui/components/mips_im.rs rename to mips-lib/src/gui_egui/components/mips_im.rs index 2fa20899..30addfb3 100644 --- a/src/gui_egui/components/mips_im.rs +++ b/mips-lib/src/gui_egui/components/mips_im.rs @@ -3,13 +3,14 @@ use std::cell::RefCell; use std::fs; use std::path::PathBuf; -use crate::common::{EguiComponent, Id, Ports, Simulator}; -use crate::components::{InstrMem, MipsMem}; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; -use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::basic_component_gui; +use crate::components::InstrMem; +use crate::components::MipsMem; use crate::gui_egui::mips_mem_view_window::MemViewWindow; use egui::{Rect, Response, RichText, Ui, Vec2}; +use syncrim::common::{EguiComponent, Id, Ports, Simulator}; +use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use syncrim::gui_egui::gui::EguiExtra; +use syncrim::gui_egui::helper::basic_component_gui; #[typetag::serde] impl EguiComponent for InstrMem { diff --git a/src/gui_egui/components/mips_instruction_splitter.rs b/mips-lib/src/gui_egui/components/mips_instruction_splitter.rs similarity index 87% rename from src/gui_egui/components/mips_instruction_splitter.rs rename to mips-lib/src/gui_egui/components/mips_instruction_splitter.rs index 0d28b653..acd5f35b 100644 --- a/src/gui_egui/components/mips_instruction_splitter.rs +++ b/mips-lib/src/gui_egui/components/mips_instruction_splitter.rs @@ -1,9 +1,9 @@ -use crate::common::{EguiComponent, Id, Ports, Simulator}; use crate::components::InstrSplit; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; -use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::basic_component_gui; use egui::{Rect, Response, RichText, Ui, Vec2}; +use syncrim::common::{EguiComponent, Id, Ports, Simulator}; +use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use syncrim::gui_egui::gui::EguiExtra; +use syncrim::gui_egui::helper::basic_component_gui; #[typetag::serde] impl EguiComponent for InstrSplit { diff --git a/src/gui_egui/components/mips_jump_merge.rs b/mips-lib/src/gui_egui/components/mips_jump_merge.rs similarity index 85% rename from src/gui_egui/components/mips_jump_merge.rs rename to mips-lib/src/gui_egui/components/mips_jump_merge.rs index 9ce5d08d..e4cd2bde 100644 --- a/src/gui_egui/components/mips_jump_merge.rs +++ b/mips-lib/src/gui_egui/components/mips_jump_merge.rs @@ -1,9 +1,9 @@ -use crate::common::{EguiComponent, Id, Ports, Simulator}; use crate::components::JumpMerge; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; -use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::basic_component_gui; use egui::{Rect, Response, RichText, Ui, Vec2}; +use syncrim::common::{EguiComponent, Id, Ports, Simulator}; +use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use syncrim::gui_egui::gui::EguiExtra; +use syncrim::gui_egui::helper::basic_component_gui; #[typetag::serde] impl EguiComponent for JumpMerge { diff --git a/src/gui_egui/components/mips_reg_file.rs b/mips-lib/src/gui_egui/components/mips_reg_file.rs similarity index 95% rename from src/gui_egui/components/mips_reg_file.rs rename to mips-lib/src/gui_egui/components/mips_reg_file.rs index 43e32900..b2129b79 100644 --- a/src/gui_egui/components/mips_reg_file.rs +++ b/mips-lib/src/gui_egui/components/mips_reg_file.rs @@ -1,9 +1,9 @@ -use crate::common::{EguiComponent, Simulator}; use crate::components::{RegFile, RegFormat}; -use crate::gui_egui::editor::EditorMode; -use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::basic_component_gui; use egui::{ComboBox, Rect, Response, RichText, ScrollArea, Ui, Vec2}; +use syncrim::common::{EguiComponent, Simulator}; +use syncrim::gui_egui::editor::EditorMode; +use syncrim::gui_egui::gui::EguiExtra; +use syncrim::gui_egui::helper::basic_component_gui; const REG_NAMES: [&str; 32] = [ "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", diff --git a/mips-lib/src/gui_egui/components/mod.rs b/mips-lib/src/gui_egui/components/mod.rs new file mode 100644 index 00000000..23827327 --- /dev/null +++ b/mips-lib/src/gui_egui/components/mod.rs @@ -0,0 +1,9 @@ +mod full_adder; +mod mips_branch_logic; +mod mips_control_unit; +mod mips_dm; +mod mips_im; +mod mips_instruction_splitter; +mod mips_jump_merge; +mod mips_reg_file; +mod sz_extend; diff --git a/mips-lib/src/gui_egui/sz_extend.rs b/mips-lib/src/gui_egui/components/sz_extend.rs similarity index 100% rename from mips-lib/src/gui_egui/sz_extend.rs rename to mips-lib/src/gui_egui/components/sz_extend.rs diff --git a/src/gui_egui/mips_mem_view_window.rs b/mips-lib/src/gui_egui/mips_mem_view_window.rs similarity index 99% rename from src/gui_egui/mips_mem_view_window.rs rename to mips-lib/src/gui_egui/mips_mem_view_window.rs index 72215b2e..22b061bd 100644 --- a/src/gui_egui/mips_mem_view_window.rs +++ b/mips-lib/src/gui_egui/mips_mem_view_window.rs @@ -1,11 +1,12 @@ -use egui::{scroll_area, RichText, ScrollArea, TextWrapMode, Ui, ViewportBuilder, ViewportId}; +use egui::{RichText, ScrollArea, TextWrapMode, Ui, ViewportBuilder, ViewportId}; use std::{ cell::RefCell, collections::{HashMap, HashSet}, rc::Rc, }; -use crate::components::{InstrMem, MemOpSize, MipsMem, RegFile}; +use crate::components::RegFile; +use crate::components::{MemOpSize, MipsMem}; use MIPS_disassembly; use serde::{Deserialize, Serialize}; diff --git a/mips-lib/src/gui_egui/mod.rs b/mips-lib/src/gui_egui/mod.rs index bd54270b..f6cc5aa2 100644 --- a/mips-lib/src/gui_egui/mod.rs +++ b/mips-lib/src/gui_egui/mod.rs @@ -1,4 +1,2 @@ -mod full_adder; -mod mips_control_unit; -mod mips_dm; -mod sz_extend; +pub mod components; +pub mod mips_mem_view_window; diff --git a/src/components/full_adder.rs b/src/components/full_adder.rs deleted file mode 100644 index 17377a81..00000000 --- a/src/components/full_adder.rs +++ /dev/null @@ -1,309 +0,0 @@ -// use std::fmt::Alignment; -#[cfg(feature = "gui-egui")] -use crate::common::EguiComponent; -use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, -}; -use log::*; -use serde::{Deserialize, Serialize}; -use std::any::Any; -use std::rc::Rc; - -pub const FULL_ADD_A_IN_ID: &str = "full_add_a_in"; -pub const FULL_ADD_B_IN_ID: &str = "full_add_b_in"; -pub const FULL_ADD_OP_IN_ID: &str = "full_add_op_in"; -pub const FULL_ADD_OUT_ID: &str = "alu_out"; -pub const FULL_ADD_OVERFLOW_OUT_ID: &str = "alu_overflow_out"; - -pub mod alu_op { - pub const ADD: u32 = 0; - pub const ADDU: u32 = 1; - pub const SUB: u32 = 2; - pub const SUBU: u32 = 3; - pub const AND: u32 = 4; - pub const OR: u32 = 5; - pub const XOR: u32 = 6; - pub const NOR: u32 = 7; - pub const SLT: u32 = 8; - pub const SLTU: u32 = 9; - pub const SLL: u32 = 10; - pub const SRL: u32 = 11; - pub const SRA: u32 = 12; - pub const LUI: u32 = 13; -} - -#[derive(Serialize, Deserialize, Clone)] -pub struct FullAdd { - pub(crate) id: Id, - pub(crate) pos: (f32, f32), - pub(crate) a_in: Input, - pub(crate) b_in: Input, - pub(crate) op_in: Input, -} - -#[typetag::serde] -impl Component for FullAdd { - fn to_(&self) { - trace!("full_adder"); - } - #[cfg(feature = "gui-egui")] - fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { - let dummy_input = Input::new("dummy", "out"); - Box::new(Rc::new(FullAdd { - id: "dummy".to_string(), - pos: (0.0, 0.0), - a_in: dummy_input.clone(), - b_in: dummy_input.clone(), - op_in: dummy_input.clone(), - })) - } - fn get_id_ports(&self) -> (Id, Ports) { - ( - self.id.clone(), - Ports::new( - vec![ - &InputPort { - port_id: FULL_ADD_A_IN_ID.to_string(), - input: self.a_in.clone(), - }, - &InputPort { - port_id: FULL_ADD_B_IN_ID.to_string(), - input: self.b_in.clone(), - }, - &InputPort { - port_id: FULL_ADD_OP_IN_ID.to_string(), - input: self.op_in.clone(), - }, - ], - OutputType::Combinatorial, - vec![FULL_ADD_OUT_ID, FULL_ADD_OVERFLOW_OUT_ID], - ), - ) - } - - fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { - match target_port_id.as_str() { - FULL_ADD_A_IN_ID => self.a_in = new_input, - FULL_ADD_B_IN_ID => self.b_in = new_input, - FULL_ADD_OP_IN_ID => self.op_in = new_input, - _ => {} - } - } - - fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { - // get input values - let a: u32 = simulator.get_input_value(&self.a_in).try_into().unwrap(); - let b: u32 = simulator.get_input_value(&self.b_in).try_into().unwrap(); - let op: u32 = simulator.get_input_value(&self.op_in).try_into().unwrap(); - - let output: u32; - let mut overflow: u32 = 0; - - match op { - alu_op::ADD => { - // output = a.wrapping_add(b); - - let tmp = (a as i32).checked_add(b as i32); - overflow = match tmp { - Some(val) => { - output = val as u32; - 0 - } - None => { - output = a.wrapping_add(b); - 1 - } - }; - } - alu_op::ADDU => { - output = a.wrapping_add(b); - } - alu_op::SUB => { - let tmp = (a as i32).checked_sub(b as i32); - overflow = match tmp { - Some(val) => { - output = val as u32; - 0 - } - None => { - output = a.wrapping_sub(b); - 1 - } - } - } - alu_op::SUBU => { - output = a.wrapping_sub(b); - } - alu_op::AND => { - output = a & b; - } - alu_op::OR => { - output = a | b; - } - alu_op::XOR => { - output = a ^ b; - } - alu_op::NOR => { - output = !(a | b); - } - alu_op::SLT => { - output = ((a as i32) < (b as i32)) as u32; - } - alu_op::SLTU => { - output = (a < b) as u32; - } - alu_op::SLL => { - output = a << b; - } - alu_op::SRL => { - output = a >> b; - } - alu_op::SRA => { - output = ((a as i32) >> b) as u32; - } - alu_op::LUI => { - output = (a & 0x0000_ffff) | (b << 16); - } - _ => { - return Err(Condition::Error( - "undef alu operation or unimplemented instruction".to_string(), - )); - } - } - simulator.set_out_value(&self.id, FULL_ADD_OUT_ID, SignalValue::Data(output)); - simulator.set_out_value( - &self.id, - FULL_ADD_OVERFLOW_OUT_ID, - SignalValue::Data(overflow), - ); - Ok(()) - } - - fn as_any(&self) -> &dyn Any { - self - } -} - -impl FullAdd { - pub fn new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input, op_in: Input) -> Self { - FullAdd { - id: id.to_string(), - pos, - a_in, - b_in, - op_in, - } - } - - pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input, op_in: Input) -> Rc { - Rc::new(FullAdd::new(id, pos, a_in, b_in, op_in)) - } -} -#[cfg(test)] -mod test { - use super::*; - - use crate::{ - common::{ComponentStore, Input, Simulator}, - components::ProbeOut, - }; - use std::rc::Rc; - - #[test] - fn test_some_alu_op() { - let cs = ComponentStore { - store: vec![ - Rc::new(ProbeOut::new("op")), - Rc::new(ProbeOut::new("a")), - Rc::new(ProbeOut::new("b")), - FullAdd::rc_new( - "ALU", - (0.0, 0.0), - Input::new("a", "out"), - Input::new("b", "out"), - Input::new("op", "out"), - ), - ], - }; - let mut simulator = Simulator::new(cs).unwrap(); - - assert_eq!(simulator.cycle, 1); - - // outputs - let alu_val = &Input::new("ALU", "out"); - - // reset - assert_eq!(simulator.get_input_value(alu_val), (0 + 0).into()); - - println!(""); - simulator.set_out_value("a", "out", 42); - simulator.set_out_value("b", "out", 1337); - simulator.set_out_value("op", "out", alu_op::ADD); - println!("sim_state {:?}", simulator.sim_state); - println!(""); - simulator.clock(); - println!("sim_state {:?}", simulator.sim_state); - assert_eq!(simulator.cycle, 2); - assert_eq!( - simulator.get_input_value(alu_val), - (42 + 1337).into(), - "testing add (1)" - ); - - println!(""); - simulator.set_out_value("a", "out", -100i32 as u32); - simulator.set_out_value("b", "out", 1337); - simulator.set_out_value("op", "out", alu_op::ADD); - println!("sim_state {:?}", simulator.sim_state); - println!(""); - simulator.clock(); - println!("sim_state {:?}", simulator.sim_state); - assert_eq!( - simulator.get_input_value(alu_val), - (1337 - 100).into(), - "testing add (2)" - ); - - println!(""); - simulator.set_out_value("a", "out", -100i32 as u32); - simulator.set_out_value("b", "out", 1337); - simulator.set_out_value("op", "out", alu_op::SUB); - println!("sim_state {:?}", simulator.sim_state); - println!(""); - simulator.clock(); - println!("sim_state {:?}", simulator.sim_state); - assert_eq!( - simulator.get_input_value(alu_val), - ((-100i32 - 1337) as u32).into(), - "testing sub" - ); - - println!(""); - simulator.set_out_value("a", "out", -100i32 as u32); - simulator.set_out_value("b", "out", 1337); - simulator.set_out_value("op", "out", alu_op::SLT); - println!("sim_state {:?}", simulator.sim_state); - println!(""); - simulator.clock(); - println!("sim_state {:?}", simulator.sim_state); - assert_eq!( - simulator.get_input_value(alu_val), - true.into(), - "testing SLT" - ); - - println!(""); - simulator.set_out_value("a", "out", -100i32 as u32); - simulator.set_out_value("b", "out", 1337); - simulator.set_out_value("op", "out", alu_op::SLTU); - println!("sim_state {:?}", simulator.sim_state); - println!(""); - simulator.clock(); - println!("sim_state {:?}", simulator.sim_state); - assert_eq!( - simulator.get_input_value(alu_val), - false.into(), - "testing SLT" - ); - } -} diff --git a/src/components/mips_controll_unit.rs b/src/components/mips_controll_unit.rs deleted file mode 100644 index 1288153b..00000000 --- a/src/components/mips_controll_unit.rs +++ /dev/null @@ -1,204 +0,0 @@ -use crate::common::{EguiComponent, Ports, Simulator}; -use crate::components::{alu_op, FullAdd}; -use crate::gui_egui::component_ui::{ - drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, - rect_with_hover, visualize_ports, -}; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; -use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::offset_helper; -use egui::{ - Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Stroke, TextWrapMode, Ui, - Vec2, -}; - -#[typetag::serde] -impl EguiComponent for FullAdd { - fn render( - &self, - ui: &mut Ui, - _context: &mut EguiExtra, - simulator: Option<&mut Simulator>, - offset: Vec2, - scale: f32, - clip_rect: Rect, - editor_mode: EditorMode, - ) -> Option> { - // 41x81 - // middle: 21x 41y (0 0) - let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; - let offset_old = offset; - let mut offset = offset; - offset.x += self.pos.0 * scale; - offset.y += self.pos.1 * scale; - let s = scale; - let o = offset; - // The shape - ui.painter().add(Shape::closed_line( - vec![ - oh((-20f32, -40f32), s, o), - oh((0f32, -40f32), s, o), - oh((20f32, -20f32), s, o), - oh((20f32, 20f32), s, o), - oh((0f32, 40f32), s, o), - oh((-20f32, 40f32), s, o), - oh((-20f32, 20f32), s, o), - oh((-10f32, 0f32), s, o), - oh((-20f32, -20f32), s, o), - ], - Stroke { - width: scale, - color: Color32::BLACK, - }, - )); - - let rect = Rect { - min: oh((-20f32, -40f32), s, o), - max: oh((20f32, 40f32), s, o), - }; - let op: String = if let Some(s) = simulator { - match TryInto::::try_into(s.get_input_value(&self.op_in)).unwrap() { - alu_op::ADD => "ADD", - alu_op::ADDU => "ADDU", - alu_op::SUB => "SUB", - alu_op::SUBU => "SUBU", - alu_op::AND => "AND", - alu_op::OR => "OR", - alu_op::XOR => "XOR", - alu_op::NOR => "NOR", - alu_op::SLT => "SLT", - alu_op::SLTU => "SLTU", - alu_op::SLL => "SLL", - alu_op::SRL => "SRL", - alu_op::SRA => "SRA", - alu_op::LUI => "LUI", - _ => "UNDEF", - } - .to_string() - } else { - "no sim".to_string() - }; - - let _area = Area::new(egui::Id::from(self.id.to_string())) - .order(Order::Middle) - .current_pos(offset.to_pos2() + Vec2::new(5.0, 0.0) * scale) - .movable(false) - .enabled(true) - .interactable(false) - .pivot(Align2::CENTER_CENTER) - .constrain(false) - .show(ui.ctx(), |ui| { - ui.set_clip_rect(clip_rect); - ui.style_mut().wrap_mode = Some(TextWrapMode::Extend); - ui.label(RichText::new(format!("ALU\n{}", op)).size(scale * 12f32)) - }); - let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - ui.label(format!("Id: {}", self.id.clone())); - ui.label("Adder"); - }); - match editor_mode { - EditorMode::Simulator => (), - _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), - } - Some(vec![r]) - } - - fn render_editor( - &mut self, - ui: &mut Ui, - context: &mut EguiExtra, - simulator: Option<&mut Simulator>, - offset: Vec2, - scale: f32, - clip_rect: Rect, - id_ports: &[(crate::common::Id, Ports)], - grid: &GridOptions, - editor_mode: EditorMode, - ) -> EditorRenderReturn { - let r_vec = FullAdd::render( - self, - ui, - context, - simulator, - offset, - scale, - clip_rect, - editor_mode, - ) - .unwrap(); - let resp = &r_vec[0]; - let delete = drag_logic( - ui.ctx(), - resp, - &mut self.pos, - &mut context.pos_tmp, - scale, - offset, - grid, - ); - - properties_window( - ui, - self.id.clone(), - resp, - &mut context.properties_window, - |ui| { - let mut clicked_dropdown = false; - input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_drag_value(ui, &mut self.pos); - clicked_dropdown |= input_selector( - ui, - &mut self.a_in, - crate::components::FULL_ADD_A_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown |= input_selector( - ui, - &mut self.b_in, - crate::components::FULL_ADD_B_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown |= input_selector( - ui, - &mut self.op_in, - crate::components::FULL_ADD_OP_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown - }, - ); - EditorRenderReturn { - delete, - resp: Some(r_vec), - } - } - - fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { - let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![ - ( - crate::components::SEXT_IN_ID.to_string(), - Pos2::new(-40f32, 0f32) + own_pos, - ), - ( - crate::components::SEXT_OUT_ID.to_string(), - Pos2::new(40f32, 0f32) + own_pos, - ), - ] - } - - fn top_padding(&self) -> f32 { - 20f32 - } - - fn set_pos(&mut self, pos: (f32, f32)) { - self.pos = pos; - } - - fn get_pos(&self) -> (f32, f32) { - self.pos - } -} diff --git a/src/components/mips_dm.rs b/src/components/mips_dm.rs deleted file mode 100644 index e2d9e12e..00000000 --- a/src/components/mips_dm.rs +++ /dev/null @@ -1,373 +0,0 @@ -#[cfg(feature = "gui-egui")] -use crate::common::EguiComponent; -use crate::{ - common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}, - gui_egui::mips_mem_view_window::MemViewWindow, -}; -use core::cell::RefCell; -use log::*; -use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, rc::Rc}; - -use super::{ - mips_mem_struct::{MemOpSize, MemWriteReturn, MipsMem}, - RegFile, -}; - -pub mod data_op { - pub const NO_OP: u32 = 0; - pub const LOAD_BYTE: u32 = 1; - pub const LOAD_BYTE_U: u32 = 2; - pub const LOAD_HALF: u32 = 3; - pub const LOAD_HALF_U: u32 = 4; - pub const LOAD_WORD: u32 = 5; - - pub const STORE_BYTE: u32 = 6; - pub const STORE_HALF: u32 = 7; - pub const STORE_WORD: u32 = 8; -} - -pub const DATA_MEM_A_IN_ID: &str = "data_mem_address_in"; -pub const DATA_MEM_OP_IN_ID: &str = "data_mem_op_in"; -pub const DATA_MEM_WRITE_ENABLE_ID: &str = "data_mem_write_enable"; -pub const DATA_MEM_WD_IN_ID: &str = "data_mem_write_data_in"; - -pub const DATA_MEM_READ_DATA_OUT_ID: &str = "data_out"; - -#[derive(Serialize, Deserialize, Clone)] -pub struct DataMem { - pub id: String, - pub pos: (f32, f32), - pub address_input: Input, - pub data_input: Input, - pub op_input: Input, - pub write_enable_input: Input, - // FIXME should probably not skip mem rc here, since we still need them to point to the same MipsMem - #[serde(skip)] - pub mem: Rc>, - pub mem_view: RefCell, - - #[serde(skip)] - history: RefCell>, - // used for the un_clock(), this is because the simulator is not passed in un clock and we dont know what cycle we un clock to - #[serde(skip)] - cycle: RefCell, -} - -impl DataMem { - pub fn new( - id: String, - pos: (f32, f32), - address_input: Input, - data_input: Input, - op_input: Input, - write_enable_input: Input, - mem: Rc>, - ) -> Self { - let mem_view = MemViewWindow::new(id.clone(), "Data memory view".into(), Rc::clone(&mem)) - .set_data_view(); - DataMem { - id: id, - pos: pos, - mem: mem, - address_input: address_input, - data_input: data_input, - op_input: op_input, - write_enable_input: write_enable_input, - mem_view: RefCell::new(mem_view), - history: RefCell::new(HashMap::new()), - cycle: RefCell::default(), // this doesn't mater will be overwritten when clock is called - } - } - pub fn rc_new( - id: String, - pos: (f32, f32), - address_input: Input, - data_input: Input, - op_input: Input, - write_enable_input: Input, - mem: Rc>, - ) -> Rc { - Rc::new(DataMem::new( - id, - pos, - address_input, - data_input, - op_input, - write_enable_input, - mem, - )) - } - pub fn set_mem_view_reg(mut self, reg_rc: Rc) -> Self { - self.mem_view.get_mut().update_regfile(reg_rc); - self - } - fn up_hist(&self, op: MemWriteReturn) { - self.history.borrow_mut().insert(*self.cycle.borrow(), op); - } -} - -#[typetag::serde()] -impl Component for DataMem { - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn to_(&self) { - //println!("InstrMem"); - } - #[cfg(feature = "gui-egui")] - fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { - let dummy_input = Input::new("dummy", "out"); - let memref = Rc::new(RefCell::new(MipsMem::default())); - Box::new(DataMem::rc_new( - id.to_string(), - pos, - dummy_input.clone(), - dummy_input.clone(), - dummy_input.clone(), - dummy_input, - memref, - )) - } - - fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { - match target_port_id.as_str() { - DATA_MEM_A_IN_ID => self.address_input = new_input, - DATA_MEM_OP_IN_ID => self.op_input = new_input, - DATA_MEM_WRITE_ENABLE_ID => self.op_input = new_input, - DATA_MEM_WD_IN_ID => self.write_enable_input = new_input, - _ => {} - } - } - - fn get_id_ports(&self) -> (String, Ports) { - ( - self.id.clone(), - Ports::new( - vec![ - &InputPort { - port_id: DATA_MEM_A_IN_ID.to_string(), - input: self.address_input.clone(), - }, - &InputPort { - port_id: DATA_MEM_OP_IN_ID.to_string(), - input: self.op_input.clone(), - }, - &InputPort { - port_id: DATA_MEM_WD_IN_ID.to_string(), - input: self.data_input.clone(), - }, - &InputPort { - port_id: DATA_MEM_WRITE_ENABLE_ID.to_string(), - input: self.write_enable_input.clone(), - }, - ], - OutputType::Combinatorial, - vec![DATA_MEM_READ_DATA_OUT_ID], - ), - ) - } - - fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { - *self.cycle.borrow_mut() = simulator.cycle; - // get instr at pc/4s - let address: u32 = simulator - .get_input_value(&self.address_input) - .try_into() - .unwrap(); - - // is operation load or store ect - let mem_op: u32 = simulator - .get_input_value(&self.op_input) - .try_into() - .unwrap(); - - let write_enable: bool = simulator - .get_input_value(&self.write_enable_input) - .try_into() - .unwrap(); - - let data: u32 = simulator - .get_input_value(&self.data_input) - .try_into() - .unwrap(); - - // update dynamic symbol PC_IM - self.mem_view - .borrow_mut() - .set_dynamic_symbol("DM_ADRS", address); - - // check if write enable and mem op match - let is_write_enable_valid = match mem_op { - data_op::LOAD_BYTE - | data_op::LOAD_BYTE_U - | data_op::LOAD_HALF - | data_op::LOAD_HALF_U - | data_op::LOAD_WORD => !write_enable, - data_op::STORE_BYTE | data_op::STORE_HALF | data_op::STORE_WORD => write_enable, - _ => true, - }; - - if !is_write_enable_valid { - return Err(Condition::Error(format!( - "write_enable ({}) doesn't match mem_op ({})", - write_enable, mem_op - ))); - } - const SIGNED: bool = true; - const UNSIGNED: bool = false; - - let ret: Result<(), Condition> = match mem_op { - data_op::NO_OP => { - simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); - Ok(()) - } - data_op::LOAD_BYTE => { - let val = self - .mem - .borrow() - .get_unaligned(address, MemOpSize::Byte, SIGNED, true); - simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); - Ok(()) - } - data_op::LOAD_BYTE_U => { - let val = self - .mem - .borrow() - .get_unaligned(address, MemOpSize::Byte, UNSIGNED, true); - simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); - Ok(()) - } - data_op::LOAD_HALF => { - match self - .mem - .borrow() - .get(address, MemOpSize::Half, SIGNED, true) - { - Ok(val) => { - simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); - Ok(()) - } - Err(_) => Err(Condition::Error(format!( - "Tried to read unaligned half word, address {:#0x}", - address - ))), - } - } - data_op::LOAD_HALF_U => { - match self - .mem - .borrow() - .get(address, MemOpSize::Half, UNSIGNED, true) - { - Ok(val) => { - simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); - Ok(()) - } - Err(_) => Err(Condition::Error(format!( - "Tried to read unaligned half word, address {:#0x}", - address - ))), - } - } - data_op::LOAD_WORD => { - match self - .mem - .borrow() - .get(address, MemOpSize::Word, UNSIGNED, true) - { - Ok(val) => { - simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); - Ok(()) - } - Err(_) => Err(Condition::Error(format!( - "Tried to read unaligned word, address {:#0x}", - address - ))), - } - } - data_op::STORE_BYTE => { - self.up_hist( - self.mem - .borrow_mut() - .write(address, data, MemOpSize::Byte, true), - ); - simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); - Ok(()) - } - data_op::STORE_HALF => { - match self - .mem - .borrow_mut() - .write_aligned(address, data, MemOpSize::Half, true) - { - Ok(ret) => { - self.up_hist(ret); - simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); - Ok(()) - } - Err(_) => Err(Condition::Error(format!( - "Tried to write unaligned half word, address {:#0x}", - address - ))), - } - } - data_op::STORE_WORD => { - match self - .mem - .borrow_mut() - .write_aligned(address, data, MemOpSize::Word, true) - { - Ok(ret) => { - self.up_hist(ret); - simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); - Ok(()) - } - Err(_) => Err(Condition::Error(format!( - "Tried to write unaligned word, address {:#0x}", - address - ))), - } - } - _ => Err(Condition::Error(format!("unknown mem op {}", mem_op))), - }; - // test breakpoint - match ret { - Ok(_) => match mem_op { - data_op::NO_OP => Ok(()), - _ => { - if self.mem_view.borrow().is_break_point(&(address & !0b11)) { - Err(Condition::Halt(format!( - "Read or write at breakpoint address {:#0x}", - address - ))) - } else { - Ok(()) - } - } - }, - Err(_) => ret, - } - } - - fn un_clock(&self) { - *self.cycle.borrow_mut() -= 1; - if let Some(op) = self.history.borrow_mut().remove(&*self.cycle.borrow()) { - self.mem.borrow_mut().revert(op); - }; - } - - fn reset(&self) { - // dont need to reset cycle, since cycle is updated in clock - - let mut hist_vec: Vec<(usize, MemWriteReturn)> = - self.history.borrow_mut().drain().collect(); - // sort vec with largest first - hist_vec.sort_by(|(a, _), (b, _)| a.cmp(b).reverse()); - let mut mem = self.mem.borrow_mut(); - for (_, op) in hist_vec { - mem.revert(op); - } - } -} diff --git a/src/components/mod.rs b/src/components/mod.rs index 97a81efd..2266d426 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -4,16 +4,7 @@ mod clk; mod constant; mod cross; mod equals; -//mod full_adder; mod mem; -mod mips_branch_logic; -//mod mips_controll_unit; -//mod mips_dm; -mod mips_im; -mod mips_instruction_splitter; -mod mips_jump_merge; -pub mod mips_mem_struct; -mod mips_reg_file; mod mux; mod probe; mod probe_assert; @@ -33,16 +24,7 @@ pub use clk::*; pub use constant::*; pub use cross::*; pub use equals::*; -pub use mips_mem_struct::*; -//pub use full_adder::*; pub use mem::*; -pub use mips_branch_logic::*; -//pub use mips_controll_unit::*; -//pub use mips_dm::*; -pub use mips_im::*; -pub use mips_instruction_splitter::*; -pub use mips_jump_merge::*; -pub use mips_reg_file::*; pub use mux::*; pub use probe::*; pub use probe_assert::*; diff --git a/src/components/sz_extend.rs b/src/components/sz_extend.rs deleted file mode 100644 index 2535398f..00000000 --- a/src/components/sz_extend.rs +++ /dev/null @@ -1,126 +0,0 @@ -// use std::fmt::Alignment; -#[cfg(feature = "gui-egui")] -use crate::common::EguiComponent; -use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, -}; -use crate::components::cntr_unit_signals; -use crate::signal; -use log::*; -use serde::{Deserialize, Serialize}; -use std::any::Any; -use std::rc::Rc; - -pub const SIGNZEROEXTEND_SIGNAL_IN_ID: &str = "signzero_signal_in"; -pub const SIGNZEROEXTEND_CTRL_IN_ID: &str = "signzero_ctrl_in"; - -pub const SIGNZEROEXTEND_OUT_ID: &str = "sz_out"; - -#[derive(Serialize, Deserialize, Clone)] -pub struct SignZeroExtend { - pub(crate) id: Id, - pub(crate) pos: (f32, f32), - pub(crate) signzero_signal_in: Input, - pub(crate) signzero_ctrl_in: Input, -} - -#[typetag::serde] -impl Component for SignZeroExtend { - fn to_(&self) { - trace!("pc+4"); - } - #[cfg(feature = "gui-egui")] - // fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { - // let dummy_input = Input::new("dummy", "out"); - // Box::new(Rc::new(SignZeroExtend { - // id: "dummy".to_string(), - // pos: (0.0, 0.0), - // signzero_extend_in: dummy_input.clone(), - // })) - // } - fn get_id_ports(&self) -> (Id, Ports) { - ( - self.id.clone(), - Ports::new( - vec![ - &InputPort { - port_id: SIGNZEROEXTEND_SIGNAL_IN_ID.to_string(), - input: self.signzero_signal_in.clone(), - }, - &InputPort { - port_id: SIGNZEROEXTEND_CTRL_IN_ID.to_string(), - input: self.signzero_ctrl_in.clone(), - }, - ], - OutputType::Combinatorial, - vec![SIGNZEROEXTEND_OUT_ID], - ), - ) - } - - fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { - match target_port_id.as_str() { - SIGNZEROEXTEND_SIGNAL_IN_ID => self.signzero_signal_in = new_input, - SIGNZEROEXTEND_CTRL_IN_ID => self.signzero_ctrl_in = new_input, - _ => {} - } - } - - // propagate sign extension to output - // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) - fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { - // get input values - let mut signal: u32 = simulator - .get_input_value(&self.signzero_signal_in) - .try_into() - .unwrap(); - - let ctrl: u32 = simulator - .get_input_value(&self.signzero_ctrl_in) - .try_into() - .unwrap(); - - if ctrl == cntr_unit_signals::EXTEND_SIGNED { - if (signal >> 15) == 1 { - signal = signal | 0xffff_0000; - } - } - - simulator.set_out_value(&self.id, SIGNZEROEXTEND_OUT_ID, SignalValue::Data(signal)); - Ok(()) - } - - fn as_any(&self) -> &dyn Any { - self - } -} - -impl SignZeroExtend { - pub fn new( - id: &str, - pos: (f32, f32), - signzero_signal_in: Input, - signzero_ctrl_in: Input, - ) -> Self { - SignZeroExtend { - id: id.to_string(), - pos, - signzero_signal_in, - signzero_ctrl_in, - } - } - - pub fn rc_new( - id: &str, - pos: (f32, f32), - signzero_signal_in: Input, - signzero_ctrl_in: Input, - ) -> Rc { - Rc::new(SignZeroExtend::new( - id, - pos, - signzero_signal_in, - signzero_ctrl_in, - )) - } -} diff --git a/src/gui_egui/components/full_adder.rs b/src/gui_egui/components/full_adder.rs deleted file mode 100644 index 1288153b..00000000 --- a/src/gui_egui/components/full_adder.rs +++ /dev/null @@ -1,204 +0,0 @@ -use crate::common::{EguiComponent, Ports, Simulator}; -use crate::components::{alu_op, FullAdd}; -use crate::gui_egui::component_ui::{ - drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, - rect_with_hover, visualize_ports, -}; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; -use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::offset_helper; -use egui::{ - Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Stroke, TextWrapMode, Ui, - Vec2, -}; - -#[typetag::serde] -impl EguiComponent for FullAdd { - fn render( - &self, - ui: &mut Ui, - _context: &mut EguiExtra, - simulator: Option<&mut Simulator>, - offset: Vec2, - scale: f32, - clip_rect: Rect, - editor_mode: EditorMode, - ) -> Option> { - // 41x81 - // middle: 21x 41y (0 0) - let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; - let offset_old = offset; - let mut offset = offset; - offset.x += self.pos.0 * scale; - offset.y += self.pos.1 * scale; - let s = scale; - let o = offset; - // The shape - ui.painter().add(Shape::closed_line( - vec![ - oh((-20f32, -40f32), s, o), - oh((0f32, -40f32), s, o), - oh((20f32, -20f32), s, o), - oh((20f32, 20f32), s, o), - oh((0f32, 40f32), s, o), - oh((-20f32, 40f32), s, o), - oh((-20f32, 20f32), s, o), - oh((-10f32, 0f32), s, o), - oh((-20f32, -20f32), s, o), - ], - Stroke { - width: scale, - color: Color32::BLACK, - }, - )); - - let rect = Rect { - min: oh((-20f32, -40f32), s, o), - max: oh((20f32, 40f32), s, o), - }; - let op: String = if let Some(s) = simulator { - match TryInto::::try_into(s.get_input_value(&self.op_in)).unwrap() { - alu_op::ADD => "ADD", - alu_op::ADDU => "ADDU", - alu_op::SUB => "SUB", - alu_op::SUBU => "SUBU", - alu_op::AND => "AND", - alu_op::OR => "OR", - alu_op::XOR => "XOR", - alu_op::NOR => "NOR", - alu_op::SLT => "SLT", - alu_op::SLTU => "SLTU", - alu_op::SLL => "SLL", - alu_op::SRL => "SRL", - alu_op::SRA => "SRA", - alu_op::LUI => "LUI", - _ => "UNDEF", - } - .to_string() - } else { - "no sim".to_string() - }; - - let _area = Area::new(egui::Id::from(self.id.to_string())) - .order(Order::Middle) - .current_pos(offset.to_pos2() + Vec2::new(5.0, 0.0) * scale) - .movable(false) - .enabled(true) - .interactable(false) - .pivot(Align2::CENTER_CENTER) - .constrain(false) - .show(ui.ctx(), |ui| { - ui.set_clip_rect(clip_rect); - ui.style_mut().wrap_mode = Some(TextWrapMode::Extend); - ui.label(RichText::new(format!("ALU\n{}", op)).size(scale * 12f32)) - }); - let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - ui.label(format!("Id: {}", self.id.clone())); - ui.label("Adder"); - }); - match editor_mode { - EditorMode::Simulator => (), - _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), - } - Some(vec![r]) - } - - fn render_editor( - &mut self, - ui: &mut Ui, - context: &mut EguiExtra, - simulator: Option<&mut Simulator>, - offset: Vec2, - scale: f32, - clip_rect: Rect, - id_ports: &[(crate::common::Id, Ports)], - grid: &GridOptions, - editor_mode: EditorMode, - ) -> EditorRenderReturn { - let r_vec = FullAdd::render( - self, - ui, - context, - simulator, - offset, - scale, - clip_rect, - editor_mode, - ) - .unwrap(); - let resp = &r_vec[0]; - let delete = drag_logic( - ui.ctx(), - resp, - &mut self.pos, - &mut context.pos_tmp, - scale, - offset, - grid, - ); - - properties_window( - ui, - self.id.clone(), - resp, - &mut context.properties_window, - |ui| { - let mut clicked_dropdown = false; - input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_drag_value(ui, &mut self.pos); - clicked_dropdown |= input_selector( - ui, - &mut self.a_in, - crate::components::FULL_ADD_A_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown |= input_selector( - ui, - &mut self.b_in, - crate::components::FULL_ADD_B_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown |= input_selector( - ui, - &mut self.op_in, - crate::components::FULL_ADD_OP_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown - }, - ); - EditorRenderReturn { - delete, - resp: Some(r_vec), - } - } - - fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { - let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![ - ( - crate::components::SEXT_IN_ID.to_string(), - Pos2::new(-40f32, 0f32) + own_pos, - ), - ( - crate::components::SEXT_OUT_ID.to_string(), - Pos2::new(40f32, 0f32) + own_pos, - ), - ] - } - - fn top_padding(&self) -> f32 { - 20f32 - } - - fn set_pos(&mut self, pos: (f32, f32)) { - self.pos = pos; - } - - fn get_pos(&self) -> (f32, f32) { - self.pos - } -} diff --git a/src/gui_egui/components/mips_controll_unit.rs b/src/gui_egui/components/mips_controll_unit.rs deleted file mode 100644 index 7b18a1be..00000000 --- a/src/gui_egui/components/mips_controll_unit.rs +++ /dev/null @@ -1,70 +0,0 @@ -use crate::common::{EguiComponent, Id, Ports, Simulator}; -use crate::components::ControlUnit; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; -use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::basic_component_gui; -use egui::{Rect, Response, RichText, Ui, Vec2}; - -#[typetag::serde] -impl EguiComponent for ControlUnit { - fn render( - &self, - ui: &mut Ui, - _context: &mut EguiExtra, - simulator: Option<&mut Simulator>, - offset: Vec2, - scale: f32, - clip_rect: Rect, - _editor_mode: EditorMode, - ) -> Option> { - // size of the component - let width = 100f32 * scale; - let height: f32 = 12f32 * scale; - basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { - ui.set_height(height); - ui.set_width(width); - ui.centered_and_justified(|ui| { - ui.label("Control Unit"); - }); - }) - } - - fn render_editor( - &mut self, - ui: &mut egui::Ui, - context: &mut EguiExtra, - simulator: Option<&mut Simulator>, - offset: egui::Vec2, - scale: f32, - clip_rect: egui::Rect, - _id_ports: &[(Id, Ports)], - _grid: &GridOptions, - editor_mode: EditorMode, - ) -> EditorRenderReturn { - self.render( - ui, - context, - simulator, - offset, - scale, - clip_rect, - editor_mode, - ); - EditorRenderReturn { - delete: false, - resp: None, - } - } - - fn set_pos(&mut self, pos: (f32, f32)) { - self.pos = pos; - } - - fn get_pos(&self) -> (f32, f32) { - self.pos - } - - fn top_padding(&self) -> f32 { - 20f32 - } -} diff --git a/src/gui_egui/components/mips_dm.rs b/src/gui_egui/components/mips_dm.rs deleted file mode 100644 index 885d6602..00000000 --- a/src/gui_egui/components/mips_dm.rs +++ /dev/null @@ -1,99 +0,0 @@ -use crate::common::{EguiComponent, Id, Ports, Simulator}; -use crate::components::DataMem; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; -use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::basic_component_gui; -use egui::{Rect, Response, RichText, Ui, Vec2}; - -#[typetag::serde] -impl EguiComponent for DataMem { - fn render( - &self, - ui: &mut Ui, - _context: &mut EguiExtra, - simulator: Option<&mut Simulator>, - offset: Vec2, - scale: f32, - clip_rect: Rect, - _editor_mode: EditorMode, - ) -> Option> { - // we could avoid this if we clone self in our basic_component_ui. - // but instead we let our Closure save stuff here (let path_option, mem_view_vis) - // and apply our changes when basic_component_gui returns our borrow - // this is to avoid cloning all the fields. - // avoiding to clone the fields might be premature optimization - // as instrMem.mem is a reference count and wont actually clone the underlying btree and hashmaps - // - // we save 27 bytes of clone - // and most of that clone might even be optimized away - // yes this was premature optimization - let mut mem_view_vis: bool = self.mem_view.borrow().visible; - - let r = basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { - // ui.centered_and_justified(|ui| { - ui.label(RichText::new("Data memory").size(12f32 * scale)); - ui.button( - RichText::new("load file") - .size(12f32 * scale) - .strikethrough(), - ) - .on_hover_text("Use instruction memory to load a file"); - - match mem_view_vis { - false => { - if ui.button("Show mem window").clicked() { - mem_view_vis = true; - } - } - true => { - ui.toggle_value(&mut mem_view_vis, "Hide mem window"); - } - }; - // }); - }); - let mut mem_view = self.mem_view.borrow_mut(); - mem_view.visible = mem_view_vis; - mem_view.render(ui.ctx()); - // return response from basic component gui - r - } - - fn render_editor( - &mut self, - ui: &mut egui::Ui, - context: &mut EguiExtra, - simulator: Option<&mut Simulator>, - offset: egui::Vec2, - scale: f32, - clip_rect: egui::Rect, - _id_ports: &[(Id, Ports)], - _grid: &GridOptions, - editor_mode: EditorMode, - ) -> EditorRenderReturn { - self.render( - ui, - context, - simulator, - offset, - scale, - clip_rect, - editor_mode, - ); - EditorRenderReturn { - delete: false, - resp: None, - } - } - - fn set_pos(&mut self, pos: (f32, f32)) { - self.pos = pos; - } - - fn get_pos(&self) -> (f32, f32) { - self.pos - } - - fn top_padding(&self) -> f32 { - 20f32 - } -} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index f4b1584f..cae8832f 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -4,15 +4,7 @@ mod clk; mod constant; mod cross; mod equal; -//mod full_adder; mod mem; -mod mips_branch_logic; -//mod mips_controll_unit; -//mod mips_dm; -mod mips_im; -mod mips_instruction_splitter; -mod mips_jump_merge; -mod mips_reg_file; mod mux; mod probe; mod probe_assert; @@ -22,6 +14,5 @@ mod probe_stim; mod register; mod sext; mod shift_left_const; -//mod sz_extend; mod wire; mod zero_extend; diff --git a/src/gui_egui/mod.rs b/src/gui_egui/mod.rs index acefb9a5..0d590501 100644 --- a/src/gui_egui/mod.rs +++ b/src/gui_egui/mod.rs @@ -6,7 +6,6 @@ pub mod helper; mod keymap; mod library; mod menu; -pub mod mips_mem_view_window; #[cfg(feature = "components")] pub mod components; From 71543fbd21ba1b53b1618b69892fd29e70061b53 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Tue, 3 Sep 2024 13:33:59 +0200 Subject: [PATCH 083/126] fixed vscode rust analyzer example --- .vscode/settings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 552ed7e1..43263d7b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,9 @@ { "json.schemaDownload.enable": true, "rust-analyzer.linkedProjects": [ - "./mips/Cargo.toml", + "./mips-lib/Cargo.toml", "./Cargo.toml", - ".\\mips\\Cargo.toml" + "./mips-simple/Cargo.toml" ], "cSpell.ignoreWords": [ "Clippy", From 57e8ccaf62442bc545a3f73b4974b3343a42da0a Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Tue, 3 Sep 2024 13:58:39 +0200 Subject: [PATCH 084/126] removed unused imports --- mips-lib/src/components/full_adder.rs | 4 ++-- mips-lib/src/components/mips_branch_logic.rs | 2 -- mips-lib/src/components/mips_control_unit.rs | 10 +++++----- mips-lib/src/components/mips_dm.rs | 2 +- mips-lib/src/components/mips_im.rs | 4 ++-- mips-lib/src/components/mips_jump_merge.rs | 1 - mips-lib/src/components/mips_reg_file.rs | 8 +------- mips-lib/src/components/sz_extend.rs | 2 -- 8 files changed, 11 insertions(+), 22 deletions(-) diff --git a/mips-lib/src/components/full_adder.rs b/mips-lib/src/components/full_adder.rs index b8eb9254..fa699f3b 100644 --- a/mips-lib/src/components/full_adder.rs +++ b/mips-lib/src/components/full_adder.rs @@ -203,11 +203,11 @@ impl FullAdd { mod test { use super::*; - use crate::{ + use std::rc::Rc; + use syncrim::{ common::{ComponentStore, Input, Simulator}, components::ProbeOut, }; - use std::rc::Rc; #[test] fn test_some_alu_op() { diff --git a/mips-lib/src/components/mips_branch_logic.rs b/mips-lib/src/components/mips_branch_logic.rs index ad41912c..23e56690 100644 --- a/mips-lib/src/components/mips_branch_logic.rs +++ b/mips-lib/src/components/mips_branch_logic.rs @@ -3,8 +3,6 @@ use log::*; use serde::{Deserialize, Serialize}; use std::any::Any; use std::rc::Rc; -#[cfg(feature = "gui-egui")] -use syncrim::common::EguiComponent; use syncrim::common::{ Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; diff --git a/mips-lib/src/components/mips_control_unit.rs b/mips-lib/src/components/mips_control_unit.rs index 3f47c790..8618df39 100644 --- a/mips-lib/src/components/mips_control_unit.rs +++ b/mips-lib/src/components/mips_control_unit.rs @@ -68,7 +68,7 @@ pub mod cntr_field { pub const MEM_MODE_OUT: &str = "mem_mode"; } -const NOP: u32 = 0; +// const NOP: u32 = 0; const OP_0: u32 = 0; const FUNCT_SLL: u32 = 0; @@ -115,10 +115,10 @@ const OP_XORI: u32 = 0b00_1110; const OP_LUI: u32 = 0b00_1111; const OP_CP0: u32 = 0b01_0000; -const CP0_FUNCT_MFC0: u32 = 0; -const CP0_FUNCT_MTF0: u32 = 0b0_0100; -const CP0_FUNCT_SPECIAL: u32 = 0b1_0000; -const CP0_FUNCT_SPECIAL_: u32 = 0b1_0000; +// const CP0_FUNCT_MFC0: u32 = 0; +// const CP0_FUNCT_MTF0: u32 = 0b0_0100; +// const CP0_FUNCT_SPECIAL: u32 = 0b1_0000; +// const CP0_FUNCT_SPECIAL_: u32 = 0b1_0000; const OP_LB: u32 = 0b10_0000; const OP_LH: u32 = 0b10_0001; diff --git a/mips-lib/src/components/mips_dm.rs b/mips-lib/src/components/mips_dm.rs index 5f7a9fcb..48005207 100644 --- a/mips-lib/src/components/mips_dm.rs +++ b/mips-lib/src/components/mips_dm.rs @@ -1,6 +1,6 @@ use crate::gui_egui::mips_mem_view_window::MemViewWindow; use core::cell::RefCell; -use log::*; +// use log::*; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, rc::Rc}; #[cfg(feature = "gui-egui")] diff --git a/mips-lib/src/components/mips_im.rs b/mips-lib/src/components/mips_im.rs index 29dbd068..a0c40444 100644 --- a/mips-lib/src/components/mips_im.rs +++ b/mips-lib/src/components/mips_im.rs @@ -1,7 +1,7 @@ use core::cell::RefCell; -use log::*; +// use log::*; use serde::{Deserialize, Serialize}; -use std::{any::Any, rc::Rc}; +use std::rc::Rc; #[cfg(feature = "gui-egui")] use syncrim::common::EguiComponent; use syncrim::common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}; diff --git a/mips-lib/src/components/mips_jump_merge.rs b/mips-lib/src/components/mips_jump_merge.rs index b626ad52..1cd903d0 100644 --- a/mips-lib/src/components/mips_jump_merge.rs +++ b/mips-lib/src/components/mips_jump_merge.rs @@ -4,7 +4,6 @@ use serde::{Deserialize, Serialize}; use std::any::Any; use std::rc::Rc; #[cfg(feature = "gui-egui")] -use syncrim::common::EguiComponent; use syncrim::common::{ Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; diff --git a/mips-lib/src/components/mips_reg_file.rs b/mips-lib/src/components/mips_reg_file.rs index 4fb5f1dc..6193a8a0 100644 --- a/mips-lib/src/components/mips_reg_file.rs +++ b/mips-lib/src/components/mips_reg_file.rs @@ -3,15 +3,9 @@ use log::*; use serde::{Deserialize, Serialize}; use std::any::Any; use std::cell::RefCell; -use std::collections::BTreeMap; -use std::ops::Deref; use std::rc::Rc; #[cfg(feature = "gui-egui")] -use syncrim::common::EguiComponent; -use syncrim::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, - SignalValue, Simulator, -}; +use syncrim::common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}; pub mod reg_file_fields { pub const RS_ADDRESS_IN_ID: &str = "rs_address_in"; diff --git a/mips-lib/src/components/sz_extend.rs b/mips-lib/src/components/sz_extend.rs index a8aa5d57..4b6f8f0e 100644 --- a/mips-lib/src/components/sz_extend.rs +++ b/mips-lib/src/components/sz_extend.rs @@ -5,11 +5,9 @@ use serde::{Deserialize, Serialize}; use std::any::Any; use std::rc::Rc; #[cfg(feature = "gui-egui")] -use syncrim::common::EguiComponent; use syncrim::common::{ Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; -use syncrim::signal; pub const SIGNZEROEXTEND_SIGNAL_IN_ID: &str = "signzero_signal_in"; pub const SIGNZEROEXTEND_CTRL_IN_ID: &str = "signzero_ctrl_in"; From 642197f0bcb8bb408e66f843590c2b05a2cb8b38 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Tue, 3 Sep 2024 14:06:40 +0200 Subject: [PATCH 085/126] resolved problems --- mips-lib/src/gui_egui/components/mips_branch_logic.rs | 2 +- mips-lib/src/gui_egui/components/mips_control_unit.rs | 2 +- mips-lib/src/gui_egui/components/mips_im.rs | 8 ++++---- mips-lib/src/gui_egui/mips_mem_view_window.rs | 2 +- mips-simple/src/main.rs | 2 -- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/mips-lib/src/gui_egui/components/mips_branch_logic.rs b/mips-lib/src/gui_egui/components/mips_branch_logic.rs index ff46a288..ee44d574 100644 --- a/mips-lib/src/gui_egui/components/mips_branch_logic.rs +++ b/mips-lib/src/gui_egui/components/mips_branch_logic.rs @@ -1,5 +1,5 @@ use crate::components::BranchLogic; -use egui::{Rect, Response, RichText, Ui, Vec2}; +use egui::{Rect, Response, Ui, Vec2}; use syncrim::common::{EguiComponent, Id, Ports, Simulator}; use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use syncrim::gui_egui::gui::EguiExtra; diff --git a/mips-lib/src/gui_egui/components/mips_control_unit.rs b/mips-lib/src/gui_egui/components/mips_control_unit.rs index c8acd068..1e128792 100644 --- a/mips-lib/src/gui_egui/components/mips_control_unit.rs +++ b/mips-lib/src/gui_egui/components/mips_control_unit.rs @@ -1,5 +1,5 @@ use crate::components::ControlUnit; -use egui::{Rect, Response, RichText, Ui, Vec2}; +use egui::{Rect, Response, Ui, Vec2}; use syncrim::common::{EguiComponent, Id, Ports, Simulator}; use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use syncrim::gui_egui::gui::EguiExtra; diff --git a/mips-lib/src/gui_egui/components/mips_im.rs b/mips-lib/src/gui_egui/components/mips_im.rs index 30addfb3..4f0cb76f 100644 --- a/mips-lib/src/gui_egui/components/mips_im.rs +++ b/mips-lib/src/gui_egui/components/mips_im.rs @@ -1,11 +1,11 @@ -use std::borrow::BorrowMut; -use std::cell::RefCell; +// use std::borrow::BorrowMut; +// use std::cell::RefCell; use std::fs; use std::path::PathBuf; use crate::components::InstrMem; use crate::components::MipsMem; -use crate::gui_egui::mips_mem_view_window::MemViewWindow; +// use crate::gui_egui::mips_mem_view_window::MemViewWindow; use egui::{Rect, Response, RichText, Ui, Vec2}; use syncrim::common::{EguiComponent, Id, Ports, Simulator}; use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; @@ -59,7 +59,7 @@ impl EguiComponent for InstrMem { if let Some(path) = path_option { let data = fs::read(path).unwrap(); - &self.mem.replace(MipsMem::from_sections(&data).unwrap()); + let _ = &self.mem.replace(MipsMem::from_sections(&data).unwrap()); mem_view_vis = true; }; // {} to drop RefMut as early as possible diff --git a/mips-lib/src/gui_egui/mips_mem_view_window.rs b/mips-lib/src/gui_egui/mips_mem_view_window.rs index 22b061bd..a80aa398 100644 --- a/mips-lib/src/gui_egui/mips_mem_view_window.rs +++ b/mips-lib/src/gui_egui/mips_mem_view_window.rs @@ -122,7 +122,7 @@ impl MemViewWindow { title: String, mem: Rc>, regfile: Rc, - pc_ref: Rc>, + _pc_ref: Rc>, ) -> Self { MemViewWindow::new(id, title, mem).set_regfile(regfile) } diff --git a/mips-simple/src/main.rs b/mips-simple/src/main.rs index 798dacd4..d8f80ecf 100644 --- a/mips-simple/src/main.rs +++ b/mips-simple/src/main.rs @@ -2,8 +2,6 @@ use mips_lib::components::*; use std::rc::Rc; use std::{cell::RefCell, path::PathBuf}; -use syncrim::common::EguiComponent; -#[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ common::{ComponentStore, Input}, From 9f06a8300d26319a078f3feecccb2641a33aa129 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Tue, 3 Sep 2024 14:16:42 +0200 Subject: [PATCH 086/126] resolved problems --- mips-lib/src/components/mips_jump_merge.rs | 1 - mips-lib/src/components/mips_reg_file.rs | 1 - mips-lib/src/components/sz_extend.rs | 1 - 3 files changed, 3 deletions(-) diff --git a/mips-lib/src/components/mips_jump_merge.rs b/mips-lib/src/components/mips_jump_merge.rs index 1cd903d0..760f751b 100644 --- a/mips-lib/src/components/mips_jump_merge.rs +++ b/mips-lib/src/components/mips_jump_merge.rs @@ -3,7 +3,6 @@ use log::*; use serde::{Deserialize, Serialize}; use std::any::Any; use std::rc::Rc; -#[cfg(feature = "gui-egui")] use syncrim::common::{ Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; diff --git a/mips-lib/src/components/mips_reg_file.rs b/mips-lib/src/components/mips_reg_file.rs index 6193a8a0..3225e5f5 100644 --- a/mips-lib/src/components/mips_reg_file.rs +++ b/mips-lib/src/components/mips_reg_file.rs @@ -4,7 +4,6 @@ use serde::{Deserialize, Serialize}; use std::any::Any; use std::cell::RefCell; use std::rc::Rc; -#[cfg(feature = "gui-egui")] use syncrim::common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}; pub mod reg_file_fields { diff --git a/mips-lib/src/components/sz_extend.rs b/mips-lib/src/components/sz_extend.rs index 4b6f8f0e..dfcdf929 100644 --- a/mips-lib/src/components/sz_extend.rs +++ b/mips-lib/src/components/sz_extend.rs @@ -4,7 +4,6 @@ use log::*; use serde::{Deserialize, Serialize}; use std::any::Any; use std::rc::Rc; -#[cfg(feature = "gui-egui")] use syncrim::common::{ Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; From 825b447faf2ae503db3f38f08539f2ad11c2b509 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Tue, 3 Sep 2024 14:19:06 +0200 Subject: [PATCH 087/126] moved mips examples --- examples/mips_example_1.rs | 242 ------------------ {examples => mips-lib/examples}/full_adder.rs | 51 +--- .../examples}/mips_controll_unit.rs | 8 +- .../examples}/mips_im_dm_regfile.rs | 2 +- .../examples}/mips_instruction_splitter.rs | 11 +- .../examples}/mips_jump_merge.rs | 11 +- .../examples}/mips_pipe_example_1.rs | 2 +- .../examples}/mips_reg_file.rs | 3 +- 8 files changed, 14 insertions(+), 316 deletions(-) delete mode 100644 examples/mips_example_1.rs rename {examples => mips-lib/examples}/full_adder.rs (53%) rename {examples => mips-lib/examples}/mips_controll_unit.rs (95%) rename {examples => mips-lib/examples}/mips_im_dm_regfile.rs (98%) rename {examples => mips-lib/examples}/mips_instruction_splitter.rs (94%) rename {examples => mips-lib/examples}/mips_jump_merge.rs (89%) rename {examples => mips-lib/examples}/mips_pipe_example_1.rs (99%) rename {examples => mips-lib/examples}/mips_reg_file.rs (96%) diff --git a/examples/mips_example_1.rs b/examples/mips_example_1.rs deleted file mode 100644 index 5041b2cc..00000000 --- a/examples/mips_example_1.rs +++ /dev/null @@ -1,242 +0,0 @@ -// use crate::src::components::cntr_unit_signals; -use std::rc::Rc; -use std::{cell::RefCell, path::PathBuf}; -use syncrim::common::EguiComponent; -#[cfg(feature = "gui-egui")] -use syncrim::gui_egui::editor::Library; -use syncrim::{ - common::{ComponentStore, Input}, - components::*, - fern::fern_setup, - mips_helper_functions::autowire, -}; - -fn main() { - fern_setup(); - - let mem = Rc::new(RefCell::new(MipsMem::default())); - let rc_reg_file = RegFile::rc_new( - "reg_file", - (350.0, 225.0), - Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), - Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), - Input::new("reg_write_addr", REGISTER_OUT_ID), //write address - Input::new("result_reg", REGISTER_OUT_ID), //write data - Input::new("reg_we", REGISTER_OUT_ID), - ); - - let cs = ComponentStore { - store: vec![ - // register that holds instr addr - Register::rc_new( - "pc", - (150.0, 390.0), - Input::new("mux_jump_merge", MUX_OUT_ID), - ), - // step addr from reg by 4 - Constant::rc_new("+4", (150.0, 440.0), 4), - Add::rc_new( - "pc+4", - (200.0, 400.0), - Input::new("+4", CONSTANT_OUT_ID), - Input::new("pc", REGISTER_OUT_ID), - ), - // - // - Rc::new( - InstrMem::new( - "instr_mem".into(), - (250.0, 575.0), - Input::new("pc", REGISTER_OUT_ID), - Rc::clone(&mem), - ) - .set_mem_view_reg(rc_reg_file.clone()), - ), - // - // - // MUX to choose what intruction addr to choose from, branch jump, reg, pc+4 - Mux::rc_new( - "mux_jump_merge", - (100.0, 390.0), - Input::new("branch", BRANCH_OUT_ID), - vec![ - Input::new("pc_add_branch", ADD_OUT_ID), //TODO: describe origin - Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), // goes to addr, RD2 - Input::new("jump_merge", MERGE_OUT_ID), // - Input::new("pc+4", ADD_OUT_ID), - ], - ), - // - // merges to find out jump location - JumpMerge::rc_new( - "jump_merge", - (125.0, 475.0), - Input::new("pc", REGISTER_OUT_ID), //input from reg before pc+4 - Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), //input from instruction mem - ), - // - // splits intructions from ir to fields - InstrSplit::rc_new( - "instruction_split", - (200.0, 225.0), - Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), - ), - // - // - ControlUnit::rc_new( - "control_unit", - (500.0, 50.0), - Input::new("instr_mem", INSTR_MEM_INSTRUCTION_ID), - ), - // - // - Register::rc_new( - "reg_we", - (850.0, 50.0), - Input::new("control_unit", cntr_field::REG_WRITE_ENABLE_OUT), - ), - // - // extends immediate field - SignZeroExtend::rc_new( - "signzero_extend", - (325.0, 425.0), - Input::new("instruction_split", INSTRUCTION_SPLITTER_IMMEDIATE_ID), - Input::new("control_unit", cntr_field::EXTEND_SELECT_OUT), // cu tells it to either sing- or zero- extend - ), - // - // - BranchLogic::rc_new( - "branch", - (475.0, 225.0), - Input::new("instruction_split", INSTRUCTION_SPLITTER_OP_ID), - Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), - Input::new("instruction_split", INSTRUCTION_SPLITTER_FUNCT_ID), - Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), - Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), - ), - // - // - ZeroExtend::rc_new( - "zero_extend_for_chamt", - (600.0, 150.0), - Input::new("instruction_split", INSTRUCTION_SPLITTER_SHAMT_ID), - ), - // - // - Constant::rc_new("0_a_inp", (610.0, 220.0), 0), - Mux::rc_new( - "mux_source_a", - (650.0, 195.0), - Input::new("control_unit", cntr_field::ALU_SRC_A_OUT), - vec![ - Input::new("zero_extend_for_chamt", ZEROEXTEND_OUT_ID), - Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), - Input::new("0_a_inp", CONSTANT_OUT_ID), - ], - ), - // - // - Mux::rc_new( - "mux_source_b", - (650.0, 255.0), - Input::new("control_unit", cntr_field::ALU_SRC_B_OUT), - vec![ - Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), - Input::new("pc+4", ADD_OUT_ID), - Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), - ], - ), - // - // - FullAdd::rc_new( - "alu", - (720.0, 225.0), - Input::new("mux_source_a", MUX_OUT_ID), - Input::new("mux_source_b", MUX_OUT_ID), - Input::new("control_unit", cntr_field::ALU_OP_OUT), - ), - // - // - Rc::new( - DataMem::new( - "data_mem".into(), - (600.0, 575.0), - Input::new("alu", FULL_ADD_OUT_ID), // calculated from rs and imm - Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), - Input::new("control_unit", cntr_field::MEM_MODE_OUT), - Input::new("control_unit", cntr_field::MEM_WRITE_ENABLE_OUT), - Rc::clone(&mem), - ) - .set_mem_view_reg(rc_reg_file.clone()), - ), - // - // - Mux::rc_new( - "mux_write_back", - (800.0, 225.0), - Input::new("control_unit", cntr_field::REG_WRITE_SRC_OUT), - vec![ - Input::new("alu", FULL_ADD_OUT_ID), - Input::new("data_mem", DATA_MEM_READ_DATA_OUT_ID), //TODO: data meme output - ], - ), - // - // - Register::rc_new( - "result_reg", - (850.0, 225.0), - Input::new("mux_write_back", MUX_OUT_ID), - ), - // - // - ShiftConst::rc_new( - "branch_shift", - (325.0, 480.0), - Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), - 2, - ), - // - // - Add::rc_new( - "pc_add_branch", - (400.0, 475.0), - Input::new("pc+4", ADD_OUT_ID), - Input::new("branch_shift", SHIFT_OUT_ID), - ), - // - // - Constant::rc_new("0x_1F", (350.0, 550.0), 0x_1F), - Mux::rc_new( - "mux_write_addr", - (400.0, 525.0), - Input::new("control_unit", cntr_field::REG_DEST_OUT), - vec![ - Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), - Input::new("instruction_split", INSTRUCTION_SPLITTER_RD_ID), - Input::new("0x_1F", CONSTANT_OUT_ID), - ], - ), - // - // - Register::rc_new( - "reg_write_addr", - (850.0, 525.0), - Input::new("mux_write_addr", MUX_OUT_ID), - ), - // - // - rc_reg_file, - ], - }; - - let cs = autowire(cs); - - let path = PathBuf::from("add.json"); - cs.save_file(&path); - - #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); - - #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(cs, &path); -} diff --git a/examples/full_adder.rs b/mips-lib/examples/full_adder.rs similarity index 53% rename from examples/full_adder.rs rename to mips-lib/examples/full_adder.rs index d31ea440..b5c2151e 100644 --- a/examples/full_adder.rs +++ b/mips-lib/examples/full_adder.rs @@ -1,14 +1,10 @@ -use std::rc::Rc; -use std::{ - any::{Any, TypeId}, - path::PathBuf, -}; -use syncrim::common::EguiComponent; +use mips_lib::components::*; +use std::path::PathBuf; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; +use syncrim::mips_helper_functions::autowire; use syncrim::{ common::{ComponentStore, Input}, - component_store, components::*, fern::fern_setup, }; @@ -69,44 +65,3 @@ fn main() { #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); } - -fn autowire(mut cs: ComponentStore) -> ComponentStore { - let mut tmp_vec: Vec> = vec![]; - - // look through the list of components - for c in &cs.store { - let (id, ports) = c.get_id_ports(); - println!("{}", id); - - let number_of_inputs = ports.inputs.len(); - - for n in 0..number_of_inputs { - // println!("{:?}", ports.inputs[n].input.id); - // println!("{:?}", ports.inputs[n]); - - let id_tmp = format!("{id}_w{n}"); - let input = ports.inputs[n].input.clone(); - let starting_pos = c.get_pos(); - - // creates temporary vales to use when constatnt inputs are there for testing - let mut destination_pos = (starting_pos.0 - 50.0, starting_pos.1); - let default_input = Input::new(&ports.inputs[n].input.id, "out"); - - // look through the list again and act when you find a matching id - for d in &cs.store { - let (id2, ports2) = d.get_id_ports(); - // look if the id matches the one you are looking for - if id2 == ports.inputs[n].input.id { - // collect the components destination and use it to make a complete wire - destination_pos = d.get_pos(); - let w = - Wire::rc_new(&id_tmp, vec![starting_pos, destination_pos], input.clone()); - tmp_vec.push(w); - } - } - } - } - cs.store.append(&mut tmp_vec); - - return cs; -} diff --git a/examples/mips_controll_unit.rs b/mips-lib/examples/mips_controll_unit.rs similarity index 95% rename from examples/mips_controll_unit.rs rename to mips-lib/examples/mips_controll_unit.rs index 091e8448..9e743616 100644 --- a/examples/mips_controll_unit.rs +++ b/mips-lib/examples/mips_controll_unit.rs @@ -1,15 +1,11 @@ +use mips_lib::components::*; +use std::path::PathBuf; use std::rc::Rc; -use std::{ - any::{Any, TypeId}, - path::PathBuf, -}; -use syncrim::common::EguiComponent; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::mips_helper_functions::autowire; use syncrim::{ common::{ComponentStore, Input}, - component_store, components::*, fern::fern_setup, }; diff --git a/examples/mips_im_dm_regfile.rs b/mips-lib/examples/mips_im_dm_regfile.rs similarity index 98% rename from examples/mips_im_dm_regfile.rs rename to mips-lib/examples/mips_im_dm_regfile.rs index 3398611b..b8942c7e 100644 --- a/examples/mips_im_dm_regfile.rs +++ b/mips-lib/examples/mips_im_dm_regfile.rs @@ -1,7 +1,7 @@ +use mips_lib::components::*; use std::cell::RefCell; use std::path::PathBuf; use std::rc::Rc; -use syncrim::common::EguiComponent; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ diff --git a/examples/mips_instruction_splitter.rs b/mips-lib/examples/mips_instruction_splitter.rs similarity index 94% rename from examples/mips_instruction_splitter.rs rename to mips-lib/examples/mips_instruction_splitter.rs index cbcb10e5..f1d8d4f3 100644 --- a/examples/mips_instruction_splitter.rs +++ b/mips-lib/examples/mips_instruction_splitter.rs @@ -1,18 +1,13 @@ -use std::rc::Rc; -use std::{ - any::{Any, TypeId}, - path::PathBuf, -}; -use syncrim::common::EguiComponent; +use mips_lib::components::*; +use std::path::PathBuf; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; +use syncrim::mips_helper_functions::autowire; use syncrim::{ common::{ComponentStore, Input}, - component_store, components::*, fern::fern_setup, }; - fn main() { fern_setup(); let cs = ComponentStore { diff --git a/examples/mips_jump_merge.rs b/mips-lib/examples/mips_jump_merge.rs similarity index 89% rename from examples/mips_jump_merge.rs rename to mips-lib/examples/mips_jump_merge.rs index a12762c6..129fcf8f 100644 --- a/examples/mips_jump_merge.rs +++ b/mips-lib/examples/mips_jump_merge.rs @@ -1,18 +1,13 @@ -use std::rc::Rc; -use std::{ - any::{Any, TypeId}, - path::PathBuf, -}; -use syncrim::common::EguiComponent; +use mips_lib::components::*; +use std::path::PathBuf; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; +use syncrim::mips_helper_functions::autowire; use syncrim::{ common::{ComponentStore, Input}, - component_store, components::*, fern::fern_setup, }; - fn main() { fern_setup(); let cs = ComponentStore { diff --git a/examples/mips_pipe_example_1.rs b/mips-lib/examples/mips_pipe_example_1.rs similarity index 99% rename from examples/mips_pipe_example_1.rs rename to mips-lib/examples/mips_pipe_example_1.rs index 60f305ab..1917e660 100644 --- a/examples/mips_pipe_example_1.rs +++ b/mips-lib/examples/mips_pipe_example_1.rs @@ -1,7 +1,7 @@ // use crate::src::components::cntr_unit_signals; +use mips_lib::components::*; use std::rc::Rc; use std::{cell::RefCell, path::PathBuf}; -use syncrim::common::EguiComponent; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ diff --git a/examples/mips_reg_file.rs b/mips-lib/examples/mips_reg_file.rs similarity index 96% rename from examples/mips_reg_file.rs rename to mips-lib/examples/mips_reg_file.rs index 68955872..e65283aa 100644 --- a/examples/mips_reg_file.rs +++ b/mips-lib/examples/mips_reg_file.rs @@ -1,6 +1,5 @@ +use mips_lib::components::*; use std::path::PathBuf; -use std::rc::Rc; -use syncrim::common::EguiComponent; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ From bff42145eff0f75c9ae8ddff9d31fbcd984cdc00 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Tue, 3 Sep 2024 15:00:36 +0200 Subject: [PATCH 088/126] clippy --- examples/clk.rs | 2 -- src/components/and.rs | 3 +-- src/components/equals.rs | 5 +---- src/components/mem.rs | 2 -- src/components/shift_left_const.rs | 1 - src/components/zero_extend.rs | 1 - src/gui_egui/components/and.rs | 2 +- src/gui_egui/components/equal.rs | 2 +- src/gui_egui/components/shift_left_const.rs | 2 +- src/gui_egui/components/zero_extend.rs | 2 +- src/gui_egui/menu.rs | 2 +- 11 files changed, 7 insertions(+), 17 deletions(-) diff --git a/examples/clk.rs b/examples/clk.rs index 15fafbd1..b3dd3baa 100644 --- a/examples/clk.rs +++ b/examples/clk.rs @@ -1,6 +1,4 @@ use std::path::PathBuf; -use std::rc::Rc; -use syncrim::common::EguiComponent; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ diff --git a/src/components/and.rs b/src/components/and.rs index e706e153..4f0d0ae2 100644 --- a/src/components/and.rs +++ b/src/components/and.rs @@ -1,8 +1,7 @@ #[cfg(feature = "gui-egui")] use crate::common::EguiComponent; use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, - SignalValue, Simulator, + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; use log::*; use serde::{Deserialize, Serialize}; diff --git a/src/components/equals.rs b/src/components/equals.rs index 85120e68..484c49ed 100644 --- a/src/components/equals.rs +++ b/src/components/equals.rs @@ -1,9 +1,6 @@ //TODO: add so it can take undefiend number of inputs -#[cfg(feature = "gui-egui")] -use crate::common::EguiComponent; use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalSigned, SignalUnsigned, - SignalValue, Simulator, + Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; use log::*; use serde::{Deserialize, Serialize}; diff --git a/src/components/mem.rs b/src/components/mem.rs index a5d7daf0..a151f953 100644 --- a/src/components/mem.rs +++ b/src/components/mem.rs @@ -169,8 +169,6 @@ impl Memory { trace!("{:x?}", data); - let tmp: SignalValue = 0x34.into(); - match size { 1 => { // Loading one byte diff --git a/src/components/shift_left_const.rs b/src/components/shift_left_const.rs index a09eedff..b6428315 100644 --- a/src/components/shift_left_const.rs +++ b/src/components/shift_left_const.rs @@ -4,7 +4,6 @@ use crate::common::EguiComponent; use crate::common::{ Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; -use crate::signal; use log::*; use serde::{Deserialize, Serialize}; use std::any::Any; diff --git a/src/components/zero_extend.rs b/src/components/zero_extend.rs index a4f8f7be..8bc3d18e 100644 --- a/src/components/zero_extend.rs +++ b/src/components/zero_extend.rs @@ -4,7 +4,6 @@ use crate::common::EguiComponent; use crate::common::{ Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; -use crate::signal; use log::*; use serde::{Deserialize, Serialize}; use std::any::Any; diff --git a/src/gui_egui/components/and.rs b/src/gui_egui/components/and.rs index e6c8615c..8407d1ca 100644 --- a/src/gui_egui/components/and.rs +++ b/src/gui_egui/components/and.rs @@ -3,7 +3,7 @@ use crate::components::And; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::basic_component_gui; -use egui::{Rect, Response, RichText, Ui, Vec2}; +use egui::{Rect, Response, Ui, Vec2}; #[typetag::serde] impl EguiComponent for And { diff --git a/src/gui_egui/components/equal.rs b/src/gui_egui/components/equal.rs index e83e1b15..853f0bf8 100644 --- a/src/gui_egui/components/equal.rs +++ b/src/gui_egui/components/equal.rs @@ -3,7 +3,7 @@ use crate::components::Equal; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::basic_component_gui; -use egui::{Rect, Response, RichText, Ui, Vec2}; +use egui::{Rect, Response, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Equal { diff --git a/src/gui_egui/components/shift_left_const.rs b/src/gui_egui/components/shift_left_const.rs index d383998c..bd1c3a65 100644 --- a/src/gui_egui/components/shift_left_const.rs +++ b/src/gui_egui/components/shift_left_const.rs @@ -3,7 +3,7 @@ use crate::components::ShiftConst; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::basic_component_gui; -use egui::{Rect, Response, RichText, Ui, Vec2}; +use egui::{Rect, Response, Ui, Vec2}; #[typetag::serde] impl EguiComponent for ShiftConst { diff --git a/src/gui_egui/components/zero_extend.rs b/src/gui_egui/components/zero_extend.rs index 7a0703cb..ff46b192 100644 --- a/src/gui_egui/components/zero_extend.rs +++ b/src/gui_egui/components/zero_extend.rs @@ -3,7 +3,7 @@ use crate::components::ZeroExtend; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::basic_component_gui; -use egui::{Rect, Response, RichText, Ui, Vec2}; +use egui::{Rect, Response, Ui, Vec2}; #[typetag::serde] impl EguiComponent for ZeroExtend { diff --git a/src/gui_egui/menu.rs b/src/gui_egui/menu.rs index ed722dc9..71455274 100644 --- a/src/gui_egui/menu.rs +++ b/src/gui_egui/menu.rs @@ -3,7 +3,7 @@ use crate::gui_egui::{ gui::Gui, keymap, }; -use egui::{menu, Button, Color32, DragValue, KeyboardShortcut, Response, RichText, Ui}; +use egui::{menu, Button, DragValue, KeyboardShortcut, Response, Ui}; pub(crate) struct Menu {} impl Menu { From 1eb800583037d51a506ddb9c1a056bcc3d6672af Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Tue, 3 Sep 2024 15:17:29 +0200 Subject: [PATCH 089/126] fixed spelling and added word to cspell ignore --- .vscode/settings.json | 39 ++++++++++++++++++- mips-lib/examples/mips_im_dm_regfile.rs | 2 +- .../examples/mips_instruction_splitter.rs | 2 +- mips-lib/examples/mips_pipe_example_1.rs | 14 +++---- mips-lib/src/components/mips_branch_logic.rs | 2 +- src/components/equals.rs | 2 +- src/simulator.rs | 2 +- 7 files changed, 49 insertions(+), 14 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 43263d7b..61f88a6d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -63,12 +63,47 @@ "usize", "vizia", "winit", - "xffff" + "xffff", + "ADDU", + "autowire", + "BGEZ", + "BGEZAL", + "BGTZ", + "BLEZ", + "BLTZAL", + "cntr", + "funct", + "hline", + "instrs", + "memref", + "MIPSCLK", + "muxes", + "NOTYPE", + "shamt", + "signzero", + "SIGNZEROEXTEND", + "SLLV", + "SLTI", + "SLTIU", + "SLTU", + "SRAV", + "SRLV", + "strtab", + "SUBU", + "symtype", + "syncsim", + "SYSCALL", + "vline", + "winapi", + "winuser", + "XORI", + "ZEROEXTEND" ], "[rust]": { "editor.defaultFormatter": "rust-lang.rust-analyzer", "editor.formatOnSave": true - } + }, + //, // "rust-analyzer.cargo.unsetTest": [ // "syncrim" diff --git a/mips-lib/examples/mips_im_dm_regfile.rs b/mips-lib/examples/mips_im_dm_regfile.rs index b8942c7e..ade809e1 100644 --- a/mips-lib/examples/mips_im_dm_regfile.rs +++ b/mips-lib/examples/mips_im_dm_regfile.rs @@ -13,7 +13,7 @@ use syncrim::{ fn main() { fern_setup(); - // create an empty memory that both IM and DM can refrence + // create an empty memory that both IM and DM can reference let mem = Rc::new(RefCell::new(MipsMem::default())); let reg_file = RegFile::rc_new( "reg_file", diff --git a/mips-lib/examples/mips_instruction_splitter.rs b/mips-lib/examples/mips_instruction_splitter.rs index f1d8d4f3..9741c22e 100644 --- a/mips-lib/examples/mips_instruction_splitter.rs +++ b/mips-lib/examples/mips_instruction_splitter.rs @@ -49,7 +49,7 @@ fn main() { Input::new("instruction_splitter", INSTRUCTION_SPLITTER_FUNCT_ID), ), Probe::rc_new( - "immiediate", + "immediate", (270.0, 240.0), Input::new("instruction_splitter", INSTRUCTION_SPLITTER_IMMEDIATE_ID), ), diff --git a/mips-lib/examples/mips_pipe_example_1.rs b/mips-lib/examples/mips_pipe_example_1.rs index 1917e660..63b709a2 100644 --- a/mips-lib/examples/mips_pipe_example_1.rs +++ b/mips-lib/examples/mips_pipe_example_1.rs @@ -60,7 +60,7 @@ fn main() { ), // // - // MUX to choose what intruction addr to choose from, branch jump, reg, pc+4 + // MUX to choose what instruction addr to choose from, branch jump, reg, pc+4 Mux::rc_new( "mux_jump_merge", (140.0, 390.0), @@ -96,14 +96,14 @@ fn main() { Input::new("jump_merge", MERGE_OUT_ID), ), // - // splits intructions from ir to fields + // splits instructions from ir to fields InstrSplit::rc_new( "instruction_split", (280.0, 140.0), Input::new("InMem_reg", REGISTER_OUT_ID), ), // - // First CU, handles, selcet for signzero_extend and mux_write_addr + // First CU, handles, select for sign/zero_extend and mux_write_addr ControlUnit::rc_new( "control_unit_1", (280.0, 100.0), @@ -117,7 +117,7 @@ fn main() { Input::new("control_EX_reg", REGISTER_OUT_ID), ), // - // Third CU, handles, write_back_mux, and DMs memread and memwrite + // Third CU, handles, write_back_mux, and DMs mem-read and mem-write ControlUnit::rc_new( "control_unit_3", (480.0, 100.0), @@ -227,7 +227,7 @@ fn main() { // // Register::rc_new( - //TODO: make 2 more controll units + //TODO: make 2 more control units "control_EX_reg", (3450.0, 1400.0), Input::new("InMem_reg", REGISTER_OUT_ID), @@ -272,7 +272,7 @@ fn main() { // // ZeroExtend::rc_new( - "zero_extend_for_chamt", + "zero_extend_for_shamt", (550.0, 170.0), Input::new("zero_extend_reg", REGISTER_OUT_ID), ), @@ -284,7 +284,7 @@ fn main() { (650.0, 220.0), Input::new("control_unit_2", cntr_field::ALU_SRC_A_OUT), vec![ - Input::new("zero_extend_for_chamt", SIGNZEROEXTEND_OUT_ID), + Input::new("zero_extend_for_shamt", SIGNZEROEXTEND_OUT_ID), Input::new("operand_a_reg", REGISTER_OUT_ID), Input::new("0_a_inp", "out"), ], diff --git a/mips-lib/src/components/mips_branch_logic.rs b/mips-lib/src/components/mips_branch_logic.rs index 23e56690..ef46b2f2 100644 --- a/mips-lib/src/components/mips_branch_logic.rs +++ b/mips-lib/src/components/mips_branch_logic.rs @@ -11,7 +11,7 @@ pub const BRANCH_OP_ID: &str = "branch_op_in"; pub const BRANCH_RT_ID: &str = "branch_rt_in"; pub const BRANCH_FUNCT_ID: &str = "branch_funct_in"; -pub const BRANCH_RS_VALUE_ID: &str = "branch_rs_vlaue_id"; +pub const BRANCH_RS_VALUE_ID: &str = "branch_rs_value_id"; pub const BRANCH_RT_VALUE_ID: &str = "branch_rt_value_id"; pub const BRANCH_OUT_ID: &str = "branch_out"; diff --git a/src/components/equals.rs b/src/components/equals.rs index 484c49ed..51e1c78d 100644 --- a/src/components/equals.rs +++ b/src/components/equals.rs @@ -1,4 +1,4 @@ -//TODO: add so it can take undefiend number of inputs +//TODO: add so it can take undefined number of inputs use crate::common::{ Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, }; diff --git a/src/simulator.rs b/src/simulator.rs index e7da119e..062e4210 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -255,7 +255,7 @@ impl Simulator { self.history.push(self.sim_state.clone()); trace!("cycle:{}", self.cycle); for component in self.ordered_components.clone() { - //trace!("evaling component:{}", component.get_id_ports().0); + //trace!("evaluating component:{}", component.get_id_ports().0); match component.clock(self) { Ok(_) => {} Err(cond) => match cond { From 80c389943dbe0006de98505587623e9225360a28 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Tue, 3 Sep 2024 15:25:30 +0200 Subject: [PATCH 090/126] more spelling fixes --- mips-lib/src/components/mips_control_unit.rs | 6 +++--- mips-lib/src/components/mips_mem_struct.rs | 4 ++-- .../src/gui_egui/components/mips_instruction_splitter.rs | 2 +- mips-lib/src/gui_egui/components/mips_reg_file.rs | 2 +- mips-lib/src/gui_egui/mips_mem_view_window.rs | 2 +- src/components/mem.rs | 6 +++--- src/components/zero_extend.rs | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/mips-lib/src/components/mips_control_unit.rs b/mips-lib/src/components/mips_control_unit.rs index 8618df39..999e2155 100644 --- a/mips-lib/src/components/mips_control_unit.rs +++ b/mips-lib/src/components/mips_control_unit.rs @@ -59,7 +59,7 @@ pub mod cntr_field { pub const MMU_OUT: &str = "mmu_out"; //TODO - // Opcode is passed to branch unit wich is responsible to controll branch logic + // Opcode is passed to branch unit which is responsible to control branch logic // pub const BRANCH_TYPE_OUT: &str = "branch"; //TODO @@ -354,7 +354,7 @@ impl Component for ControlUnit { set!( cntr_field::BRANCH_INTERRUPT_OUT, cntr_unit_signals::NO_BRANCH_INTERRUPT - ); // overiden by jr and jalr + ); // overwritten by jr and jalr match funct { FUNCT_SLL => { @@ -409,7 +409,7 @@ impl Component for ControlUnit { cntr_field::BRANCH_INTERRUPT_OUT, cntr_unit_signals::BRANCH_INTERRUPT ); - set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_RD); // this is different from syncsim as there its defined as 31, but that dosen't match mips documentation; + set!(cntr_field::REG_DEST_OUT, cntr_unit_signals::REG_DEST_RD); // this is different from syncsim as there its defined as 31, but that doesn't match mips documentation; set!(cntr_field::ALU_SRC_A_OUT, cntr_unit_signals::ALU_SRC_A_ZERO); set!(cntr_field::ALU_SRC_B_OUT, cntr_unit_signals::ALU_SRC_B_PC); set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); diff --git a/mips-lib/src/components/mips_mem_struct.rs b/mips-lib/src/components/mips_mem_struct.rs index e9123316..8f5b9cf3 100644 --- a/mips-lib/src/components/mips_mem_struct.rs +++ b/mips-lib/src/components/mips_mem_struct.rs @@ -31,7 +31,7 @@ impl MemWriteReturn { pub fn op_size(&self) -> MemOpSize { self.op_size.clone() } - /// return the bytes befre the write where [0] is at address, [1] is at address + 1 and [N] is at address + N + /// return the bytes before the write where [0] is at address, [1] is at address + 1 and [N] is at address + N pub fn before_bytes(&self) -> Vec { match self.op_size { MemOpSize::Byte => vec![self.bytes[0]], @@ -256,7 +256,7 @@ impl MipsMem { for sym_entry in sym_table { let sym_name = string_table.get(sym_entry.st_name as usize).unwrap(); - // if the symboltype is NOTYPE, bind is LOCAL and has a string add it + // if the symbol type is NOTYPE, bind is LOCAL and has a string add it if sym_entry.st_symtype() == 0x0 && sym_entry.st_bind() == 0x0 && sym_name != "" { sym_hash_map.insert(sym_entry.st_value as u32, sym_name.to_string()); diff --git a/mips-lib/src/gui_egui/components/mips_instruction_splitter.rs b/mips-lib/src/gui_egui/components/mips_instruction_splitter.rs index acd5f35b..b2ec778d 100644 --- a/mips-lib/src/gui_egui/components/mips_instruction_splitter.rs +++ b/mips-lib/src/gui_egui/components/mips_instruction_splitter.rs @@ -24,7 +24,7 @@ impl EguiComponent for InstrSplit { ui.set_height(height); ui.set_width(width); ui.centered_and_justified(|ui| { - ui.label(RichText::new("instruction\nspliter").size(12f32 * scale)); + ui.label(RichText::new("instruction\n splitter").size(12f32 * scale)); }); }) } diff --git a/mips-lib/src/gui_egui/components/mips_reg_file.rs b/mips-lib/src/gui_egui/components/mips_reg_file.rs index b2129b79..350d079b 100644 --- a/mips-lib/src/gui_egui/components/mips_reg_file.rs +++ b/mips-lib/src/gui_egui/components/mips_reg_file.rs @@ -31,7 +31,7 @@ impl EguiComponent for RegFile { // A toggle button for showing register names ui.toggle_value(&mut *self.show_reg_names.borrow_mut(), "Show names"); - // showsing the display format of the register + // showing the display format of the register let mut tmp: RegFormat = self.reg_format.borrow().clone(); ComboBox::from_id_source(&self.id) .selected_text(format!("{:?}", tmp)) diff --git a/mips-lib/src/gui_egui/mips_mem_view_window.rs b/mips-lib/src/gui_egui/mips_mem_view_window.rs index a80aa398..8ccc7b63 100644 --- a/mips-lib/src/gui_egui/mips_mem_view_window.rs +++ b/mips-lib/src/gui_egui/mips_mem_view_window.rs @@ -31,7 +31,7 @@ pub struct MemViewWindow { #[serde(skip)] custom_address: u32, - // used for formatning the view + // used for formatting the view big_endian: bool, format: DataFormat, diff --git a/src/components/mem.rs b/src/components/mem.rs index a151f953..6aa300f4 100644 --- a/src/components/mem.rs +++ b/src/components/mem.rs @@ -144,8 +144,8 @@ impl Memory { /// /// let mem = Memory::default(); // creates a memory with only zeros /// - /// let align_addrs = mem.align(0xa3f5, 4); - /// assert_eq!(SignalValue::from(0xa3f4), align_addrs) + /// let align_adrs = mem.align(0xa3f5, 4); + /// assert_eq!(SignalValue::from(0xa3f4), align_adrs) /// ``` pub fn align(&self, addr: usize, size: usize) -> SignalValue { ((addr % size != 0) as SignalUnsigned).into() @@ -179,7 +179,7 @@ impl Memory { } } 2 => { - // Loading half word, most stuff here is for tracing and degbuggning + // Loading half word, most stuff here is for tracing and debugging if sign { if big_endian { // sign big endian diff --git a/src/components/zero_extend.rs b/src/components/zero_extend.rs index 8bc3d18e..3e1ef677 100644 --- a/src/components/zero_extend.rs +++ b/src/components/zero_extend.rs @@ -64,7 +64,7 @@ impl Component for ZeroExtend { .try_into() .unwrap(); - let output: u32 = signal_in & 0x0000_FFFF; // already zero exrtended + let output: u32 = signal_in & 0x0000_FFFF; // already zero extended simulator.set_out_value(&self.id, ZEROEXTEND_OUT_ID, SignalValue::Data(output)); Ok(()) From 965ec3fcc834c6c0634869132d3ef19eb88d95ca Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Tue, 3 Sep 2024 15:25:46 +0200 Subject: [PATCH 091/126] wip --- src/common.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common.rs b/src/common.rs index 7bd688e8..fe5d4753 100644 --- a/src/common.rs +++ b/src/common.rs @@ -137,6 +137,10 @@ pub trait EguiComponent: Component { } } + fn get_port_location(&self, id: Input) -> egui::Pos2 { + self.get_pos().into() + } + fn top_padding(&self) -> f32 { todo!("Create top_padding for this EguiComponent"); } From 987f2086fa0d9a15fed0c1fb2a4394c005143c61 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Wed, 4 Sep 2024 10:21:28 +0200 Subject: [PATCH 092/126] updated get_port_locaton to use option --- src/common.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common.rs b/src/common.rs index fe5d4753..55997330 100644 --- a/src/common.rs +++ b/src/common.rs @@ -137,8 +137,8 @@ pub trait EguiComponent: Component { } } - fn get_port_location(&self, id: Input) -> egui::Pos2 { - self.get_pos().into() + fn get_port_location(&self, id: Input) -> Option<(f32, f32)> { + None } fn top_padding(&self) -> f32 { @@ -184,7 +184,7 @@ impl Ports { } } -#[derive(Serialize, Deserialize, Clone, Debug)] +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] pub struct Input { pub id: Id, pub field: Id, From 217e25c087c911a62394d056ad138570530e886f Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Wed, 4 Sep 2024 12:07:02 +0200 Subject: [PATCH 093/126] updated aoutowire to use port location, register as an example --- src/common.rs | 2 +- src/gui_egui/components/register.rs | 27 ++++++++++++++++++++++++++- src/mips_helper_functions.rs | 13 +++++++++++-- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/common.rs b/src/common.rs index 55997330..e40f2975 100644 --- a/src/common.rs +++ b/src/common.rs @@ -137,7 +137,7 @@ pub trait EguiComponent: Component { } } - fn get_port_location(&self, id: Input) -> Option<(f32, f32)> { + fn get_port_location(&self, _id: Input) -> Option<(f32, f32)> { None } diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index 5331e498..42a85233 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -1,4 +1,5 @@ -use crate::common::{EguiComponent, Input, Ports, SignalUnsigned, Simulator}; +use crate::common::{self, EguiComponent, Input, Ports, SignalUnsigned, Simulator}; +use crate::component_store; use crate::components::{Register, REGISTER_OUT_ID}; use crate::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, @@ -158,6 +159,30 @@ impl EguiComponent for Register { ] } + fn get_port_location(&self, input: Input) -> Option<(f32, f32)> { + let own_pos = self.get_pos(); + let input_pos_change = (-10f32, 0f32); + let output_pos_change = (10f32, 0f32); + + if input == self.r_in { + // looks input + return Some(( + own_pos.0 + input_pos_change.0, + own_pos.1 + input_pos_change.1, + )); + } else if input == Input::new(&self.id, REGISTER_OUT_ID) { + // look output + return Some(( + own_pos.0 + output_pos_change.0, + own_pos.1 + output_pos_change.1, + )); + } + + println!("{:?} == {:?}\n\n", self.r_in, input); + + return self.get_pos().into(); + } + fn top_padding(&self) -> f32 { 20f32 } diff --git a/src/mips_helper_functions.rs b/src/mips_helper_functions.rs index 1125512e..10a365bc 100644 --- a/src/mips_helper_functions.rs +++ b/src/mips_helper_functions.rs @@ -1,6 +1,6 @@ use std::rc::Rc; -use crate::common::{ComponentStore, EguiComponent}; +use crate::common::{ComponentStore, EguiComponent, Input}; use crate::components::Wire; pub fn autowire(mut cs: ComponentStore) -> ComponentStore { @@ -23,13 +23,22 @@ pub fn autowire(mut cs: ComponentStore) -> ComponentStore { .expect(&format!("can't find comonent with id {}", source_port.id)); // create wire with correct source destination and positions + let s_id = &source_port.id; let s_field = &source_port.field; let d_id = &dest_comp_id; let d_field = &dest_comp_field; + wires.push(Wire::rc_new( &format!("from {}:{} to {}:{}", s_id, s_field, d_id, d_field), - vec![source_component.get_pos(), destination_component.get_pos()], + vec![ + source_component + .get_port_location(Input::new(s_id, s_field)) + .unwrap_or(source_component.get_pos()), + destination_component + .get_port_location(Input::new(s_id, s_field)) + .unwrap_or(destination_component.get_pos()), + ], source_port.clone(), )) } From 5ee9184b860dbb1c8485481938027f4cf9575563 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 4 Sep 2024 15:34:34 +0200 Subject: [PATCH 094/126] added get port location to alu and reg file --- .../src/gui_egui/components/full_adder.rs | 38 ++++++++++--------- .../src/gui_egui/components/mips_reg_file.rs | 32 ++++++++++++++-- 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/mips-lib/src/gui_egui/components/full_adder.rs b/mips-lib/src/gui_egui/components/full_adder.rs index c71e4a9f..6a69e069 100644 --- a/mips-lib/src/gui_egui/components/full_adder.rs +++ b/mips-lib/src/gui_egui/components/full_adder.rs @@ -1,9 +1,9 @@ -use crate::components::{alu_op, FullAdd}; +use crate::components::{alu_op, FullAdd, FULL_ADD_OUT_ID, FULL_ADD_OVERFLOW_OUT_ID}; use egui::{ - Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Stroke, TextWrapMode, Ui, - Vec2, + vec2, Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Stroke, + TextWrapMode, Ui, Vec2, }; -use syncrim::common::{EguiComponent, Ports, Simulator}; +use syncrim::common::{EguiComponent, Input, Ports, Simulator}; use syncrim::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, visualize_ports, @@ -176,20 +176,6 @@ impl EguiComponent for FullAdd { } } - fn ports_location(&self) -> Vec<(syncrim::common::Id, Pos2)> { - let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![ - ( - syncrim::components::SEXT_IN_ID.to_string(), - Pos2::new(-40f32, 0f32) + own_pos, - ), - ( - syncrim::components::SEXT_OUT_ID.to_string(), - Pos2::new(40f32, 0f32) + own_pos, - ), - ] - } - fn top_padding(&self) -> f32 { 20f32 } @@ -201,4 +187,20 @@ impl EguiComponent for FullAdd { fn get_pos(&self) -> (f32, f32) { self.pos } + + fn get_port_location(&self, id: Input) -> Option<(f32, f32)> { + if id == self.a_in { + Some((Pos2::from(self.pos) + vec2(-20.0, -30.0)).into()) + } else if id == self.b_in { + Some((Pos2::from(self.pos) + vec2(-20.0, 30.0)).into()) + } else if id == Input::new(&self.id, FULL_ADD_OUT_ID) { + Some((Pos2::from(self.pos) + vec2(20.0, 0.0)).into()) + } else if id == Input::new(&self.id, FULL_ADD_OVERFLOW_OUT_ID) { + Some((Pos2::from(self.pos) + vec2(20.0, 5.0)).into()) + } else if id == self.op_in { + Some((Pos2::from(self.pos) + vec2(-10.0, -40.0)).into()) + } else { + None + } + } } diff --git a/mips-lib/src/gui_egui/components/mips_reg_file.rs b/mips-lib/src/gui_egui/components/mips_reg_file.rs index 350d079b..719d8b6f 100644 --- a/mips-lib/src/gui_egui/components/mips_reg_file.rs +++ b/mips-lib/src/gui_egui/components/mips_reg_file.rs @@ -1,6 +1,6 @@ -use crate::components::{RegFile, RegFormat}; -use egui::{ComboBox, Rect, Response, RichText, ScrollArea, Ui, Vec2}; -use syncrim::common::{EguiComponent, Simulator}; +use crate::components::{reg_file_fields, RegFile, RegFormat}; +use egui::{vec2, ComboBox, Pos2, Rect, Response, RichText, ScrollArea, Ui, Vec2}; +use syncrim::common::{EguiComponent, Input, Simulator}; use syncrim::gui_egui::editor::EditorMode; use syncrim::gui_egui::gui::EguiExtra; use syncrim::gui_egui::helper::basic_component_gui; @@ -91,6 +91,32 @@ impl EguiComponent for RegFile { }) } + fn get_port_location(&self, id: Input) -> Option<(f32, f32)> { + // components size = (120,250) + let margin = egui::style::Spacing::default().window_margin; + + // inputs + if id == self.rs_address_in { + Some((Pos2::from(self.pos) + vec2(0f32, -125.0 - margin.top)).into()) + } else if id == self.rt_address_in { + Some((Pos2::from(self.pos) + vec2(0f32, 125.0 + margin.bottom)).into()) + } else if id == self.write_enable_in { + Some((Pos2::from(self.pos) + vec2(-60.0 - margin.left, 70.0)).into()) + } else if id == self.write_address_in { + Some((Pos2::from(self.pos) + vec2(-60.0 - margin.left, 90.0)).into()) + } else if id == self.write_data_in { + Some((Pos2::from(self.pos) + vec2(-60.0 - margin.left, 110.0)).into()) + // outputs + } else if id == Input::new(&self.id, reg_file_fields::RS_VALUE_OUT_ID) { + Some((Pos2::from(self.pos) + vec2(60.0 + margin.right, 40.0)).into()) + } else if id == Input::new(&self.id, reg_file_fields::RT_VALUE_OUT_ID) { + Some((Pos2::from(self.pos) + vec2(60.0 + margin.right, -40.0)).into()) + // no match + } else { + None + } + } + fn top_padding(&self) -> f32 { 20f32 } From 0d28c2637803101356dc429d8a8256d5c2a455d7 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 4 Sep 2024 16:25:27 +0200 Subject: [PATCH 095/126] better error message for editor --- src/gui_egui/editor.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index de7a20b8..8cd62985 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -362,7 +362,10 @@ impl Editor { _ => e.components.retain_mut(|c| { let old_key = c.as_ref().get_id_ports().0; let mut context = e.contexts.remove(&old_key).unwrap(); - let render_return = (*Rc::get_mut(c).unwrap()).render_editor( + let debug_id = c.get_id_ports().0; + let render_return = (*Rc::get_mut(c) + .expect(&format!("More than one reference exist to {}, can't get mut, therefore not render editor", debug_id))) + .render_editor( ui, &mut context, None, From 8c112952a7629db44806e4e19eb149205e9a232c Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 5 Sep 2024 12:58:52 +0200 Subject: [PATCH 096/126] updated memory to use id to a phys mem component --- .vscode/settings.json | 4 +- mips-lib/examples/mips_im_dm_regfile.rs | 5 +- mips-lib/examples/mips_pipe_example_1.rs | 6 +- mips-lib/src/components/mips_dm.rs | 174 ++++++++++-------- mips-lib/src/components/mips_im.rs | 60 +++--- mips-lib/src/components/mod.rs | 4 +- .../{mips_mem_struct.rs => physical_mem.rs} | 79 +++++++- mips-lib/src/gui_egui/components/mips_dm.rs | 23 ++- mips-lib/src/gui_egui/components/mips_im.rs | 35 +++- mips-lib/src/gui_egui/components/mod.rs | 1 + .../src/gui_egui/components/physical_mem.rs | 63 +++++++ mips-lib/src/gui_egui/mips_mem_view_window.rs | 107 +++++------ mips-simple/src/main.rs | 6 +- 13 files changed, 367 insertions(+), 200 deletions(-) rename mips-lib/src/components/{mips_mem_struct.rs => physical_mem.rs} (83%) create mode 100644 mips-lib/src/gui_egui/components/physical_mem.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index 61f88a6d..2f25db43 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,8 +1,8 @@ { "json.schemaDownload.enable": true, "rust-analyzer.linkedProjects": [ - "./mips-lib/Cargo.toml", - "./Cargo.toml", + // "./mips-lib/Cargo.toml", + // "./Cargo.toml", "./mips-simple/Cargo.toml" ], "cSpell.ignoreWords": [ diff --git a/mips-lib/examples/mips_im_dm_regfile.rs b/mips-lib/examples/mips_im_dm_regfile.rs index ade809e1..feae08f2 100644 --- a/mips-lib/examples/mips_im_dm_regfile.rs +++ b/mips-lib/examples/mips_im_dm_regfile.rs @@ -27,6 +27,7 @@ fn main() { let cs = ComponentStore { store: vec![ + Rc::new(PhysicalMem::new("phys_mem", (0.0, 0.0))), ProbeEdit::rc_new("rs_addr", (60.0, 100.0)), ProbeEdit::rc_new("rt_addr", (60.0, 140.0)), ProbeEdit::rc_new("write_addr", (60.0, 180.0)), @@ -48,7 +49,7 @@ fn main() { "instr_mem".into(), (200.0, 500.0), Input::new("pc", "out"), - Rc::clone(&mem), + "phys_mem".into(), ) .set_mem_view_reg(Rc::clone(®_file)), ), @@ -64,7 +65,7 @@ fn main() { Input::new("data_write_data", "out"), Input::new("data_mem_op", "out"), Input::new("data_write_enable", "out"), - Rc::clone(&mem), + "phys_mem".into(), ) .set_mem_view_reg(Rc::clone(®_file)), ), diff --git a/mips-lib/examples/mips_pipe_example_1.rs b/mips-lib/examples/mips_pipe_example_1.rs index 63b709a2..fbe5ce56 100644 --- a/mips-lib/examples/mips_pipe_example_1.rs +++ b/mips-lib/examples/mips_pipe_example_1.rs @@ -14,7 +14,6 @@ use syncrim::{ fn main() { fern_setup(); - let mem = Rc::new(RefCell::new(MipsMem::default())); let rc_reg_file = RegFile::rc_new( "reg_file", (360.0, 170.0), @@ -37,6 +36,7 @@ fn main() { let cs = ComponentStore { store: vec![ + Rc::new(PhysicalMem::new("phys_mem", (0.0, 0.0))), // register that holds instr addr Register::rc_new("pc", (170.0, 410.0), Input::new("mux_jump_merge", "out")), // step addr from reg by 4 @@ -54,7 +54,7 @@ fn main() { "instr_mem".into(), (280.0, 600.0), Input::new("pc", "out"), - Rc::clone(&mem), + "phys_mem".into(), ) .set_mem_view_reg(rc_reg_file.clone()), ), @@ -322,7 +322,7 @@ fn main() { Input::new("data_MEM_reg", REGISTER_OUT_ID), Input::new("control_unit_3", cntr_field::MEM_MODE_OUT), Input::new("control_unit_3", cntr_field::MEM_WRITE_ENABLE_OUT), - Rc::clone(&mem), + "phys_mem".into(), ) .set_mem_view_reg(rc_reg_file.clone()), ), diff --git a/mips-lib/src/components/mips_dm.rs b/mips-lib/src/components/mips_dm.rs index 48005207..103a404c 100644 --- a/mips-lib/src/components/mips_dm.rs +++ b/mips-lib/src/components/mips_dm.rs @@ -1,5 +1,6 @@ use crate::gui_egui::mips_mem_view_window::MemViewWindow; use core::cell::RefCell; +use std::cell::RefMut; // use log::*; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, rc::Rc}; @@ -7,9 +8,11 @@ use std::{collections::HashMap, rc::Rc}; use syncrim::common::EguiComponent; use syncrim::common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}; -use crate::components::mips_mem_struct::{MemOpSize, MemWriteReturn, MipsMem}; +use crate::components::physical_mem::{MemOpSize, MemWriteReturn, MipsMem}; use crate::components::RegFile; +use super::PhysicalMem; + pub mod data_op { pub const NO_OP: u32 = 0; pub const LOAD_BYTE: u32 = 1; @@ -40,14 +43,8 @@ pub struct DataMem { pub write_enable_input: Input, // FIXME should probably not skip mem rc here, since we still need them to point to the same MipsMem #[serde(skip)] - pub mem: Rc>, + pub phys_mem_id: String, pub mem_view: RefCell, - - #[serde(skip)] - history: RefCell>, - // used for the un_clock(), this is because the simulator is not passed in un clock and we dont know what cycle we un clock to - #[serde(skip)] - cycle: RefCell, } impl DataMem { @@ -58,21 +55,19 @@ impl DataMem { data_input: Input, op_input: Input, write_enable_input: Input, - mem: Rc>, + phys_mem_id: String, ) -> Self { - let mem_view = MemViewWindow::new(id.clone(), "Data memory view".into(), Rc::clone(&mem)) - .set_data_view(); + let mem_view = + MemViewWindow::new(id.clone(), "Data memory view".into()).set_data_view(None); DataMem { id: id, pos: pos, - mem: mem, + phys_mem_id: phys_mem_id, address_input: address_input, data_input: data_input, op_input: op_input, write_enable_input: write_enable_input, mem_view: RefCell::new(mem_view), - history: RefCell::new(HashMap::new()), - cycle: RefCell::default(), // this doesn't mater will be overwritten when clock is called } } pub fn rc_new( @@ -82,7 +77,7 @@ impl DataMem { data_input: Input, op_input: Input, write_enable_input: Input, - mem: Rc>, + phys_mem_id: String, ) -> Rc { Rc::new(DataMem::new( id, @@ -91,15 +86,48 @@ impl DataMem { data_input, op_input, write_enable_input, - mem, + phys_mem_id, )) } + pub fn set_mem_view_reg(mut self, reg_rc: Rc) -> Self { self.mem_view.get_mut().update_regfile(reg_rc); self } - fn up_hist(&self, op: MemWriteReturn) { - self.history.borrow_mut().insert(*self.cycle.borrow(), op); + + /// This gets a &PhysicalMem from the component named self.phys_mem_id + /// + /// # Panics + /// + /// Panics if This functions panics if phys_mem_id is not found in simulator + /// or phys_mem_id is not of type PhysicalMem + fn get_phys_mem<'a>(&self, sim: &'a Simulator) -> &'a PhysicalMem { + let v = &sim.ordered_components; + let comp = v + .into_iter() + .find(|x| x.get_id_ports().0 == self.phys_mem_id) + .expect(&format!("cant find {} in simulator", self.phys_mem_id)); + // deref to get &dyn EguiComponent + let comp_any = (*comp).as_any(); + let phys_mem: &PhysicalMem = comp_any + .downcast_ref() + .expect("can't downcast to physical memory"); + phys_mem + } + + fn get_mut_mem<'a>(&self, sim: &'a Simulator) -> RefMut<'a, MipsMem> { + self.get_phys_mem(sim).mem.borrow_mut() + } + + fn up_hist(&self, sim: &Simulator, op: MemWriteReturn, cycle: usize) { + self.get_phys_mem(sim) + .history + .borrow_mut() + .insert(cycle, op); + } + fn up_cycle(&self, sim: &Simulator) { + let cycle = sim.cycle; + let _ = self.get_phys_mem(sim).cycle.replace(cycle); } } @@ -115,7 +143,6 @@ impl Component for DataMem { #[cfg(feature = "gui-egui")] fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { let dummy_input = Input::new("dummy", "out"); - let memref = Rc::new(RefCell::new(MipsMem::default())); Box::new(DataMem::rc_new( id.to_string(), pos, @@ -123,7 +150,7 @@ impl Component for DataMem { dummy_input.clone(), dummy_input.clone(), dummy_input, - memref, + "dummy".into(), )) } @@ -166,7 +193,8 @@ impl Component for DataMem { } fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { - *self.cycle.borrow_mut() = simulator.cycle; + let cycle = simulator.cycle; + self.up_cycle(&simulator); // get instr at pc/4s let address: u32 = simulator .get_input_value(&self.address_input) @@ -220,27 +248,30 @@ impl Component for DataMem { Ok(()) } data_op::LOAD_BYTE => { - let val = self - .mem - .borrow() - .get_unaligned(address, MemOpSize::Byte, SIGNED, true); + let val = self.get_mut_mem(&simulator).get_unaligned( + address, + MemOpSize::Byte, + SIGNED, + true, + ); simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); Ok(()) } data_op::LOAD_BYTE_U => { - let val = self - .mem - .borrow() - .get_unaligned(address, MemOpSize::Byte, UNSIGNED, true); + let val = self.get_mut_mem(&simulator).get_unaligned( + address, + MemOpSize::Byte, + UNSIGNED, + true, + ); simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); Ok(()) } data_op::LOAD_HALF => { - match self - .mem - .borrow() - .get(address, MemOpSize::Half, SIGNED, true) - { + let l_ret = + self.get_mut_mem(&simulator) + .get(address, MemOpSize::Half, SIGNED, true); + match l_ret { Ok(val) => { simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); Ok(()) @@ -252,11 +283,10 @@ impl Component for DataMem { } } data_op::LOAD_HALF_U => { - match self - .mem - .borrow() - .get(address, MemOpSize::Half, UNSIGNED, true) - { + let l_ret = + self.get_mut_mem(&simulator) + .get(address, MemOpSize::Half, UNSIGNED, true); + match l_ret { Ok(val) => { simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); Ok(()) @@ -268,11 +298,10 @@ impl Component for DataMem { } } data_op::LOAD_WORD => { - match self - .mem - .borrow() - .get(address, MemOpSize::Word, UNSIGNED, true) - { + let l_ret = + self.get_mut_mem(&simulator) + .get(address, MemOpSize::Word, UNSIGNED, true); + match l_ret { Ok(val) => { simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); Ok(()) @@ -284,22 +313,23 @@ impl Component for DataMem { } } data_op::STORE_BYTE => { - self.up_hist( - self.mem - .borrow_mut() - .write(address, data, MemOpSize::Byte, true), - ); + let ret = self + .get_mut_mem(&simulator) + .write(address, data, MemOpSize::Byte, true); + self.up_hist(&simulator, ret, cycle); simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); Ok(()) } data_op::STORE_HALF => { - match self - .mem - .borrow_mut() - .write_aligned(address, data, MemOpSize::Half, true) - { + let w_ret = self.get_mut_mem(&simulator).write_aligned( + address, + data, + MemOpSize::Half, + true, + ); + match w_ret { Ok(ret) => { - self.up_hist(ret); + self.up_hist(&simulator, ret, cycle); simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); Ok(()) } @@ -310,13 +340,15 @@ impl Component for DataMem { } } data_op::STORE_WORD => { - match self - .mem - .borrow_mut() - .write_aligned(address, data, MemOpSize::Word, true) - { + let w_ret = self.get_mut_mem(&simulator).write_aligned( + address, + data, + MemOpSize::Word, + true, + ); + match w_ret { Ok(ret) => { - self.up_hist(ret); + self.up_hist(&simulator, ret, cycle); simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); Ok(()) } @@ -346,24 +378,4 @@ impl Component for DataMem { Err(_) => ret, } } - - fn un_clock(&self) { - *self.cycle.borrow_mut() -= 1; - if let Some(op) = self.history.borrow_mut().remove(&*self.cycle.borrow()) { - self.mem.borrow_mut().revert(op); - }; - } - - fn reset(&self) { - // dont need to reset cycle, since cycle is updated in clock - - let mut hist_vec: Vec<(usize, MemWriteReturn)> = - self.history.borrow_mut().drain().collect(); - // sort vec with largest first - hist_vec.sort_by(|(a, _), (b, _)| a.cmp(b).reverse()); - let mut mem = self.mem.borrow_mut(); - for (_, op) in hist_vec { - mem.revert(op); - } - } } diff --git a/mips-lib/src/components/mips_im.rs b/mips-lib/src/components/mips_im.rs index a0c40444..ca5b39f9 100644 --- a/mips-lib/src/components/mips_im.rs +++ b/mips-lib/src/components/mips_im.rs @@ -6,10 +6,12 @@ use std::rc::Rc; use syncrim::common::EguiComponent; use syncrim::common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}; -use crate::components::mips_mem_struct::{MemOpSize, MipsMem}; +use crate::components::physical_mem::{MemOpSize, MipsMem}; use crate::components::RegFile; use crate::gui_egui::mips_mem_view_window::MemViewWindow; +use super::PhysicalMem; + pub const INSTR_MEM_PC_ID: &str = "pc"; pub const INSTR_MEM_INSTRUCTION_ID: &str = "instruction"; @@ -19,30 +21,20 @@ pub struct InstrMem { pub id: String, pub pos: (f32, f32), pub pc: Input, - // should probably not skip mem rc here, since we still need them to point to the same MipsMem - #[serde(skip)] - pub mem: Rc>, + // All components who deal with memory acess this + pub phys_mem_id: String, pub mem_view: RefCell, } impl InstrMem { - pub fn new( - id: String, - pos: (f32, f32), - pc_input: Input, - mem: Rc>, - ) -> InstrMem { - let mem_view = MemViewWindow::new( - id.clone(), - "instruction memory view".into(), - Rc::clone(&mem), - ) - .set_code_view(); + pub fn new(id: String, pos: (f32, f32), pc_input: Input, phys_mem_id: String) -> InstrMem { + let mem_view = + MemViewWindow::new(id.clone(), "instruction memory view".into()).set_code_view(None); InstrMem { id: id, pos: pos, pc: pc_input, - mem: mem, + phys_mem_id: phys_mem_id, mem_view: RefCell::new(mem_view), } } @@ -50,9 +42,9 @@ impl InstrMem { id: String, pos: (f32, f32), pc_input: Input, - mem: Rc>, + phys_mem_id: String, ) -> Rc { - Rc::new(InstrMem::new(id, pos, pc_input, mem)) + Rc::new(InstrMem::new(id, pos, pc_input, phys_mem_id)) } pub fn set_mem_view_reg(mut self, reg_rc: Rc) -> Self { self.mem_view.get_mut().update_regfile(reg_rc); @@ -72,17 +64,12 @@ impl Component for InstrMem { #[cfg(feature = "gui-egui")] fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { let dummy_input = Input::new("dummy", "out"); - let memref = Rc::new(RefCell::new(MipsMem::default())); Box::new(Rc::new(InstrMem { id: id.into(), pos: pos, pc: dummy_input, - mem: memref.clone(), - mem_view: RefCell::new(MemViewWindow::new( - "dummy".into(), - "IM dummy".into(), - memref, - )), + phys_mem_id: "dummy".into(), + mem_view: RefCell::new(MemViewWindow::new("dummy".into(), "IM dummy".into())), })) } @@ -110,12 +97,31 @@ impl Component for InstrMem { // get instr at pc/4 let pc: u32 = simulator.get_input_value(&self.pc).try_into().unwrap(); + // this is inside a {} to make sure our simulator borrow is returned before its used to set signal + let option_instr = { + let v = &simulator.ordered_components; + let comp = v + .into_iter() + .find(|x| x.get_id_ports().0 == self.phys_mem_id) + .expect(&format!("cant find {} in simulator", self.phys_mem_id)); + // deref to get Rc + // deref again to get &dyn EguiComponent + let comp_any = (**comp).as_any(); + let phys_mem: &PhysicalMem = comp_any + .downcast_ref() + .expect("can't downcast to physical memory"); + phys_mem + .mem + .borrow_mut() + .get(pc, MemOpSize::Word, false, true) + }; + // update dynamic symbol PC_IM self.mem_view.borrow_mut().set_dynamic_symbol("PC_IM", pc); // Get a word at PC with the size of 32bits, read as big endian, // sign extend doesn't mater since we have 32 bits so extending to 32bits does nothing - match self.mem.borrow().get(pc, MemOpSize::Word, false, true) { + match option_instr { Ok(instr) => { simulator.set_out_value(&self.id, INSTR_MEM_INSTRUCTION_ID, instr); // check if pc is at breakpoint diff --git a/mips-lib/src/components/mod.rs b/mips-lib/src/components/mod.rs index 4a14d7d3..406a81de 100644 --- a/mips-lib/src/components/mod.rs +++ b/mips-lib/src/components/mod.rs @@ -5,8 +5,8 @@ mod mips_dm; mod mips_im; mod mips_instruction_splitter; mod mips_jump_merge; -mod mips_mem_struct; mod mips_reg_file; +mod physical_mem; mod sz_extend; pub use full_adder::*; @@ -16,6 +16,6 @@ pub use mips_dm::*; pub use mips_im::*; pub use mips_instruction_splitter::*; pub use mips_jump_merge::*; -pub use mips_mem_struct::*; pub use mips_reg_file::*; +pub use physical_mem::*; pub use sz_extend::*; diff --git a/mips-lib/src/components/mips_mem_struct.rs b/mips-lib/src/components/physical_mem.rs similarity index 83% rename from mips-lib/src/components/mips_mem_struct.rs rename to mips-lib/src/components/physical_mem.rs index 8f5b9cf3..c474fa52 100644 --- a/mips-lib/src/components/mips_mem_struct.rs +++ b/mips-lib/src/components/physical_mem.rs @@ -1,10 +1,81 @@ use elf::{endian::AnyEndian, ElfBytes}; -use std::collections::{BTreeMap, HashMap}; +use std::{ + any::Any, + cell::RefCell, + collections::{BTreeMap, HashMap}, +}; +use syncrim::{ + common::{Component, Ports}, + signal::Id, +}; use serde::{Deserialize, Serialize}; -/// A men contains two fields. One with the memory mapped data in a BTreeMap. -/// And a hashmap with symbols. -#[derive(Default, Serialize, Deserialize)] + +/// Used to contain the "physical memory" which instruction memory and data memory uses +#[derive(Serialize, Deserialize, Clone)] +pub struct PhysicalMem { + pub id: String, + pub pos: (f32, f32), + #[serde(skip)] + pub mem: RefCell, + #[serde(skip)] + pub history: RefCell>, + // used for the un_clock(), this is because the simulator is not passed in un clock and we dont know what cycle we un clock to + #[serde(skip)] + pub cycle: RefCell, +} + +impl PhysicalMem { + pub fn new(id: impl Into, pos: (f32, f32)) -> Self { + Self { + id: id.into(), + pos: pos, + mem: RefCell::default(), + history: RefCell::default(), + cycle: RefCell::default(), + } + } +} + +#[typetag::serde] +impl Component for PhysicalMem { + #[doc = " returns the (id, Ports) of the component"] + fn get_id_ports(&self) -> (Id, Ports) { + ( + self.id.clone(), + Ports::new(vec![], syncrim::common::OutputType::Combinatorial, vec![]), + ) + } + + #[doc = " any"] + fn as_any(&self) -> &dyn Any { + self + } + + fn un_clock(&self) { + *self.cycle.borrow_mut() -= 1; + if let Some(op) = self.history.borrow_mut().remove(&*self.cycle.borrow()) { + self.mem.borrow_mut().revert(op); + }; + } + + fn reset(&self) { + // dont need to reset cycle, since cycle is updated in clock + + let mut hist_vec: Vec<(usize, MemWriteReturn)> = + self.history.borrow_mut().drain().collect(); + // sort vec with largest first + hist_vec.sort_by(|(a, _), (b, _)| a.cmp(b).reverse()); + let mut mem = self.mem.borrow_mut(); + for (_, op) in hist_vec { + mem.revert(op); + } + } +} + +/// A men contains three fields. One with the memory mapped data in a BTreeMap, +/// hashmap with symbols and a hashmap with sections +#[derive(Default, Serialize, Deserialize, Clone)] pub struct MipsMem { symbols: HashMap, sections: HashMap, diff --git a/mips-lib/src/gui_egui/components/mips_dm.rs b/mips-lib/src/gui_egui/components/mips_dm.rs index 0bac1cb2..28bbb32a 100644 --- a/mips-lib/src/gui_egui/components/mips_dm.rs +++ b/mips-lib/src/gui_egui/components/mips_dm.rs @@ -1,4 +1,4 @@ -use crate::components::DataMem; +use crate::components::{DataMem, PhysicalMem}; use egui::{Rect, Response, RichText, Ui, Vec2}; use syncrim::common::{EguiComponent, Id, Ports, Simulator}; use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; @@ -51,9 +51,24 @@ impl EguiComponent for DataMem { }; // }); }); - let mut mem_view = self.mem_view.borrow_mut(); - mem_view.visible = mem_view_vis; - mem_view.render(ui.ctx()); + if let Some(sim) = simulator { + let v = &sim.ordered_components; + let comp = v + .into_iter() + .find(|x| x.get_id_ports().0 == self.phys_mem_id) + .expect(&format!("cant find {} in simulator", self.phys_mem_id)); + // deref to get &dyn EguiComponent + let comp_any = (*comp).as_any(); + let phys_mem: &PhysicalMem = comp_any + .downcast_ref() + .expect("can't downcast to physical memory"); + // {} to drop RefMut as early as possible + { + let mut mem_view = self.mem_view.borrow_mut(); + mem_view.visible = mem_view_vis; + mem_view.render(ui.ctx(), &*phys_mem.mem.borrow()); + } + } // return response from basic component gui r } diff --git a/mips-lib/src/gui_egui/components/mips_im.rs b/mips-lib/src/gui_egui/components/mips_im.rs index 4f0cb76f..5541cbb4 100644 --- a/mips-lib/src/gui_egui/components/mips_im.rs +++ b/mips-lib/src/gui_egui/components/mips_im.rs @@ -5,6 +5,7 @@ use std::path::PathBuf; use crate::components::InstrMem; use crate::components::MipsMem; +use crate::components::PhysicalMem; // use crate::gui_egui::mips_mem_view_window::MemViewWindow; use egui::{Rect, Response, RichText, Ui, Vec2}; use syncrim::common::{EguiComponent, Id, Ports, Simulator}; @@ -57,17 +58,31 @@ impl EguiComponent for InstrMem { // }); }); - if let Some(path) = path_option { - let data = fs::read(path).unwrap(); - let _ = &self.mem.replace(MipsMem::from_sections(&data).unwrap()); - mem_view_vis = true; - }; - // {} to drop RefMut as early as possible - { - let mut mem_view = self.mem_view.borrow_mut(); - mem_view.visible = mem_view_vis; - mem_view.render(ui.ctx()); + if let Some(sim) = simulator { + let v = &sim.ordered_components; + let comp = v + .into_iter() + .find(|x| x.get_id_ports().0 == self.phys_mem_id) + .expect(&format!("cant find {} in simulator", self.phys_mem_id)); + // deref to get &dyn EguiComponent + let comp_any = (*comp).as_any(); + let phys_mem: &PhysicalMem = comp_any + .downcast_ref() + .expect("can't downcast to physical memory"); + + if let Some(path) = path_option { + let data = fs::read(path).unwrap(); + let _ = phys_mem.mem.replace(MipsMem::from_sections(&data).unwrap()); + mem_view_vis = true; + }; + // {} to drop RefMut as early as possible + { + let mut mem_view = self.mem_view.borrow_mut(); + mem_view.visible = mem_view_vis; + mem_view.render(ui.ctx(), &*phys_mem.mem.borrow()); + } } + // return response from basic component gui r } diff --git a/mips-lib/src/gui_egui/components/mod.rs b/mips-lib/src/gui_egui/components/mod.rs index 23827327..b28720e3 100644 --- a/mips-lib/src/gui_egui/components/mod.rs +++ b/mips-lib/src/gui_egui/components/mod.rs @@ -6,4 +6,5 @@ mod mips_im; mod mips_instruction_splitter; mod mips_jump_merge; mod mips_reg_file; +mod physical_mem; mod sz_extend; diff --git a/mips-lib/src/gui_egui/components/physical_mem.rs b/mips-lib/src/gui_egui/components/physical_mem.rs new file mode 100644 index 00000000..b88e1229 --- /dev/null +++ b/mips-lib/src/gui_egui/components/physical_mem.rs @@ -0,0 +1,63 @@ +use crate::components::PhysicalMem; +use egui::{Rect, Response, RichText, Ui, Vec2}; +use syncrim::common::{EguiComponent, Id, Ports, Simulator}; +use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; +use syncrim::gui_egui::gui::EguiExtra; +use syncrim::gui_egui::helper::basic_component_gui; + +#[typetag::serde] +impl EguiComponent for PhysicalMem { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + _editor_mode: EditorMode, + ) -> Option> { + basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.label("Physical memory"); + }) + } + + fn render_editor( + &mut self, + ui: &mut egui::Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: egui::Vec2, + scale: f32, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + self.render( + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ); + EditorRenderReturn { + delete: false, + resp: None, + } + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } + + fn top_padding(&self) -> f32 { + 20f32 + } +} diff --git a/mips-lib/src/gui_egui/mips_mem_view_window.rs b/mips-lib/src/gui_egui/mips_mem_view_window.rs index 8ccc7b63..7c2a710d 100644 --- a/mips-lib/src/gui_egui/mips_mem_view_window.rs +++ b/mips-lib/src/gui_egui/mips_mem_view_window.rs @@ -16,7 +16,6 @@ pub struct MemViewWindow { pub visible: bool, title: String, id: String, - mem: Rc>, row_offset: u32, max_rows: u32, /// when set to top, the given address will be displayed at the top of the scroll area @@ -92,14 +91,13 @@ fn set_address(adrs: &GoAddress, new_adrs: u32) -> GoAddress { impl MemViewWindow { // creates a new memory view window with id string and the given memory - pub fn new(id: String, title: String, mem: Rc>) -> Self { + pub fn new(id: String, title: String) -> Self { MemViewWindow { title: title, id: id, visible: false, row_offset: 0, max_rows: 1024, - mem: mem, go_to_address: GoAddress::None, go_type: GoAddress::Top(0), custom_address: 0, @@ -124,7 +122,7 @@ impl MemViewWindow { regfile: Rc, _pc_ref: Rc>, ) -> Self { - MemViewWindow::new(id, title, mem).set_regfile(regfile) + MemViewWindow::new(id, title).set_regfile(regfile) } /// set a reference to a regfile which allows for jumping and displaying registers @@ -157,25 +155,20 @@ impl MemViewWindow { } /// This sets the format to hex + mips and if possible goes to the section .text - pub fn set_code_view(mut self) -> MemViewWindow { + pub fn set_code_view(mut self, mem: Option<&MipsMem>) -> MemViewWindow { // find if value ".text" exists, if so go to that - match self - .mem - .borrow() - .get_section_table() - .iter() - .find_map( - |(adrs, name)| { - if name == ".text" { - Some(adrs) - } else { - None - } - }, - ) { - Some(adrs) => self.go_to_address = GoAddress::Top(*adrs), - None => self.go_to_address = GoAddress::None, - }; + if let Some(m) = mem { + match m.get_section_table().iter().find_map(|(adrs, name)| { + if name == ".text" { + Some(adrs) + } else { + None + } + }) { + Some(adrs) => self.go_to_address = GoAddress::Top(*adrs), + None => self.go_to_address = GoAddress::None, + }; + } // set self.format = DataFormat::HexAndMips; @@ -187,25 +180,20 @@ impl MemViewWindow { } /// This sets the format to byte + utf8 and if possible goes to the section .data - pub fn set_data_view(mut self) -> MemViewWindow { - // find if value ".text" exists - match self - .mem - .borrow() - .get_section_table() - .iter() - .find_map( - |(adrs, name)| { - if name == ".data" { - Some(adrs) - } else { - None - } - }, - ) { - Some(adrs) => self.go_to_address = GoAddress::Top(*adrs), - None => self.go_to_address = GoAddress::Top(0x1000), - }; + pub fn set_data_view(mut self, mem: Option<&MipsMem>) -> MemViewWindow { + if let Some(m) = mem { + // find if value ".text" exists + match m.get_section_table().iter().find_map(|(adrs, name)| { + if name == ".data" { + Some(adrs) + } else { + None + } + }) { + Some(adrs) => self.go_to_address = GoAddress::Top(*adrs), + None => self.go_to_address = GoAddress::Top(0x1000), + }; + } self.format = DataFormat::ByteAndUtf8; self } @@ -214,7 +202,7 @@ impl MemViewWindow { self.break_points.contains(address) } - pub fn render(&mut self, ctx: &egui::Context) { + pub fn render(&mut self, ctx: &egui::Context, mem: &MipsMem) { if !self.visible { return (); }; @@ -230,7 +218,7 @@ impl MemViewWindow { } // Render top panel with go to, format and show menus - self.render_top(ctx); + self.render_top(ctx, mem); egui::CentralPanel::default().show(ctx, |ui| { let h = ui.text_style_height(&egui::TextStyle::Body); @@ -242,7 +230,7 @@ impl MemViewWindow { ui.style_mut().wrap_mode = Some(TextWrapMode::Truncate); ui.set_width(ui.available_width()); for i in draw_range.clone() { - self.render_scroll_area_item(ui, i); + self.render_scroll_area_item(ui, i, mem); } }); }) @@ -250,7 +238,7 @@ impl MemViewWindow { ); } - fn render_top(&mut self, ctx: &egui::Context) { + fn render_top(&mut self, ctx: &egui::Context, mem: &MipsMem) { egui::TopBottomPanel::top(self.id.clone()).show(ctx, |ui| { egui::menu::bar(ui, |ui| { ui.menu_button("Go to", |ui| { @@ -267,7 +255,7 @@ impl MemViewWindow { // add submenu with a button for each symbol, which sets self.go_to_address ui.menu_button("symbol", |ui| { ScrollArea::vertical().show(ui, |ui| { - let because_lifetimes_sad = self.mem.borrow().get_symbol_table(); + let because_lifetimes_sad = mem.get_symbol_table(); let mut symbols = because_lifetimes_sad.iter().collect::>(); symbols.sort_by(|a, b| a.0.partial_cmp(b.0).unwrap()); @@ -281,7 +269,7 @@ impl MemViewWindow { }); }); ui.menu_button("section", |ui| { - let because_lifetimes_sad = self.mem.borrow().get_section_table(); + let because_lifetimes_sad = mem.get_section_table(); let mut sections = because_lifetimes_sad.iter().collect::>(); sections.sort_by(|a, b| a.0.partial_cmp(b.0).unwrap()); @@ -471,7 +459,7 @@ impl MemViewWindow { }); } /// NOTE borrows mem - fn render_scroll_area_item(&mut self, ui: &mut Ui, scroll_area_row: usize) { + fn render_scroll_area_item(&mut self, ui: &mut Ui, scroll_area_row: usize, mem: &MipsMem) { let more_row_text = RichText::new(format!("show {} more rows", &self.max_rows / 2)); if scroll_area_row == 0 { if self.row_offset == 0 { @@ -499,8 +487,8 @@ impl MemViewWindow { false => "", }, address, - self.format_row(address), - match self.get_symbols_etc_at_address(&address) { + self.format_row(address, mem), + match self.get_symbols_etc_at_address(&address, mem) { Some(string) => format!("\t<= {}", string), None => String::new(), } @@ -518,18 +506,13 @@ impl MemViewWindow { } } /// NOTE BORROWS MEM - fn format_row(&self, adrs: u32) -> String { - let data_u32 = - self.mem - .borrow() - .get_unaligned(adrs, MemOpSize::Word, false, self.big_endian); - let bytes = self - .mem - .borrow() + fn format_row(&self, adrs: u32, mem: &MipsMem) -> String { + let data_u32 = mem.get_unaligned(adrs, MemOpSize::Word, false, self.big_endian); + let bytes = mem .get_unaligned(adrs, MemOpSize::Word, false, true) .to_be_bytes(); // TODO get symbol table clones the hashmap, this is infective - let sym_tab = self.mem.borrow().get_symbol_table(); + let sym_tab = mem.get_symbol_table(); match self.format { DataFormat::Hex => { format!("{:#010x}", data_u32) @@ -618,10 +601,10 @@ impl MemViewWindow { // TODO symbol or sect might not be word aligned, // since we check word aligned addresses we might miss the symbol/reg ect - fn get_symbols_etc_at_address(&self, adrs: &u32) -> Option { + fn get_symbols_etc_at_address(&self, adrs: &u32, mem: &MipsMem) -> Option { let mut out_vec: Vec<&str> = vec![]; - let sym = self.mem.borrow().get_symbol_table(); - let sect = self.mem.borrow().get_section_table(); + let sym = mem.get_symbol_table(); + let sect = mem.get_section_table(); for (name, _) in self .dynamic_symbols diff --git a/mips-simple/src/main.rs b/mips-simple/src/main.rs index d8f80ecf..8dc431ff 100644 --- a/mips-simple/src/main.rs +++ b/mips-simple/src/main.rs @@ -13,7 +13,6 @@ use syncrim::{ fn main() { fern_setup(); - let mem = Rc::new(RefCell::new(MipsMem::default())); let rc_reg_file = RegFile::rc_new( "reg_file", (350.0, 225.0), @@ -26,6 +25,7 @@ fn main() { let cs = ComponentStore { store: vec![ + Rc::new(PhysicalMem::new("phys_mem", (0.0, 0.0))), // register that holds instr addr Register::rc_new( "pc", @@ -47,7 +47,7 @@ fn main() { "instr_mem".into(), (250.0, 575.0), Input::new("pc", REGISTER_OUT_ID), - Rc::clone(&mem), + "phys_mem".into(), ) .set_mem_view_reg(rc_reg_file.clone()), ), @@ -164,7 +164,7 @@ fn main() { Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), Input::new("control_unit", cntr_field::MEM_MODE_OUT), Input::new("control_unit", cntr_field::MEM_WRITE_ENABLE_OUT), - Rc::clone(&mem), + "phys_mem".into(), ) .set_mem_view_reg(rc_reg_file.clone()), ), From 47fd0daf27186cff5c9a90a3f2101a4f2c727d85 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 5 Sep 2024 14:03:40 +0200 Subject: [PATCH 097/126] updated to use another method to allow mem_view to se registers --- mips-lib/examples/mips_im_dm_regfile.rs | 58 ++++++++----------- mips-lib/examples/mips_pipe_example_1.rs | 40 ++++++------- mips-lib/src/components/mips_dm.rs | 14 ++--- mips-lib/src/components/mips_im.rs | 18 ++++-- mips-lib/src/gui_egui/components/mips_dm.rs | 21 ++++++- mips-lib/src/gui_egui/components/mips_im.rs | 19 +++++- mips-lib/src/gui_egui/mips_mem_view_window.rs | 44 +++++--------- mips-simple/src/main.rs | 58 +++++++++---------- 8 files changed, 138 insertions(+), 134 deletions(-) diff --git a/mips-lib/examples/mips_im_dm_regfile.rs b/mips-lib/examples/mips_im_dm_regfile.rs index feae08f2..2eeb7b96 100644 --- a/mips-lib/examples/mips_im_dm_regfile.rs +++ b/mips-lib/examples/mips_im_dm_regfile.rs @@ -13,18 +13,6 @@ use syncrim::{ fn main() { fern_setup(); - // create an empty memory that both IM and DM can reference - let mem = Rc::new(RefCell::new(MipsMem::default())); - let reg_file = RegFile::rc_new( - "reg_file", - (200.0, 200.0), - Input::new("rs_addr", "out"), - Input::new("rt_addr", "out"), - Input::new("write_addr", "out"), - Input::new("write_data", "out"), - Input::new("write_enable", "out"), - ); - let cs = ComponentStore { store: vec![ Rc::new(PhysicalMem::new("phys_mem", (0.0, 0.0))), @@ -44,32 +32,36 @@ fn main() { Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), ), ProbeEdit::rc_new("pc", (60.0, 500.0)), - Rc::new( - InstrMem::new( - "instr_mem".into(), - (200.0, 500.0), - Input::new("pc", "out"), - "phys_mem".into(), - ) - .set_mem_view_reg(Rc::clone(®_file)), - ), + Rc::new(InstrMem::new( + "instr_mem".into(), + (200.0, 500.0), + Input::new("pc", "out"), + "phys_mem".into(), + "reg_file".into(), + )), ProbeEdit::rc_new("data_adrs", (60.0, 660.0)), ProbeEdit::rc_new("data_write_enable", (60.0, 700.0)), ProbeEdit::rc_new("data_mem_op", (60.0, 740.0)), ProbeEdit::rc_new("data_write_data", (60.0, 780.0)), - Rc::new( - DataMem::new( - "data_mem".into(), - (200.0, 700.0), - Input::new("data_adrs", "out"), - Input::new("data_write_data", "out"), - Input::new("data_mem_op", "out"), - Input::new("data_write_enable", "out"), - "phys_mem".into(), - ) - .set_mem_view_reg(Rc::clone(®_file)), + Rc::new(DataMem::new( + "data_mem".into(), + (200.0, 700.0), + Input::new("data_adrs", "out"), + Input::new("data_write_data", "out"), + Input::new("data_mem_op", "out"), + Input::new("data_write_enable", "out"), + "phys_mem".into(), + "reg_file".into(), + )), + RegFile::rc_new( + "reg_file", + (200.0, 200.0), + Input::new("rs_addr", "out"), + Input::new("rt_addr", "out"), + Input::new("write_addr", "out"), + Input::new("write_data", "out"), + Input::new("write_enable", "out"), ), - reg_file, ], }; diff --git a/mips-lib/examples/mips_pipe_example_1.rs b/mips-lib/examples/mips_pipe_example_1.rs index fbe5ce56..1bf8d94a 100644 --- a/mips-lib/examples/mips_pipe_example_1.rs +++ b/mips-lib/examples/mips_pipe_example_1.rs @@ -1,7 +1,7 @@ // use crate::src::components::cntr_unit_signals; use mips_lib::components::*; +use std::path::PathBuf; use std::rc::Rc; -use std::{cell::RefCell, path::PathBuf}; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ @@ -49,15 +49,13 @@ fn main() { ), // // - Rc::new( - InstrMem::new( - "instr_mem".into(), - (280.0, 600.0), - Input::new("pc", "out"), - "phys_mem".into(), - ) - .set_mem_view_reg(rc_reg_file.clone()), - ), + Rc::new(InstrMem::new( + "instr_mem".into(), + (280.0, 600.0), + Input::new("pc", "out"), + "phys_mem".into(), + "reg_file".into(), + )), // // // MUX to choose what instruction addr to choose from, branch jump, reg, pc+4 @@ -314,18 +312,16 @@ fn main() { ), // // - Rc::new( - DataMem::new( - "data_mem".into(), - (600.0, 580.0), - Input::new("alu_reg", REGISTER_OUT_ID), // calculated from rs and imm - Input::new("data_MEM_reg", REGISTER_OUT_ID), - Input::new("control_unit_3", cntr_field::MEM_MODE_OUT), - Input::new("control_unit_3", cntr_field::MEM_WRITE_ENABLE_OUT), - "phys_mem".into(), - ) - .set_mem_view_reg(rc_reg_file.clone()), - ), + Rc::new(DataMem::new( + "data_mem".into(), + (600.0, 580.0), + Input::new("alu_reg", REGISTER_OUT_ID), // calculated from rs and imm + Input::new("data_MEM_reg", REGISTER_OUT_ID), + Input::new("control_unit_3", cntr_field::MEM_MODE_OUT), + Input::new("control_unit_3", cntr_field::MEM_WRITE_ENABLE_OUT), + "phys_mem".into(), + "reg_file".into(), + )), // // Register::rc_new( diff --git a/mips-lib/src/components/mips_dm.rs b/mips-lib/src/components/mips_dm.rs index 103a404c..5181c45d 100644 --- a/mips-lib/src/components/mips_dm.rs +++ b/mips-lib/src/components/mips_dm.rs @@ -41,9 +41,8 @@ pub struct DataMem { pub data_input: Input, pub op_input: Input, pub write_enable_input: Input, - // FIXME should probably not skip mem rc here, since we still need them to point to the same MipsMem - #[serde(skip)] pub phys_mem_id: String, + pub regfile_id: String, pub mem_view: RefCell, } @@ -56,6 +55,7 @@ impl DataMem { op_input: Input, write_enable_input: Input, phys_mem_id: String, + regfile_id: String, ) -> Self { let mem_view = MemViewWindow::new(id.clone(), "Data memory view".into()).set_data_view(None); @@ -68,6 +68,7 @@ impl DataMem { op_input: op_input, write_enable_input: write_enable_input, mem_view: RefCell::new(mem_view), + regfile_id: regfile_id, } } pub fn rc_new( @@ -78,6 +79,7 @@ impl DataMem { op_input: Input, write_enable_input: Input, phys_mem_id: String, + regfile_id: String, ) -> Rc { Rc::new(DataMem::new( id, @@ -87,14 +89,9 @@ impl DataMem { op_input, write_enable_input, phys_mem_id, + regfile_id, )) } - - pub fn set_mem_view_reg(mut self, reg_rc: Rc) -> Self { - self.mem_view.get_mut().update_regfile(reg_rc); - self - } - /// This gets a &PhysicalMem from the component named self.phys_mem_id /// /// # Panics @@ -151,6 +148,7 @@ impl Component for DataMem { dummy_input.clone(), dummy_input, "dummy".into(), + "dummy".into(), )) } diff --git a/mips-lib/src/components/mips_im.rs b/mips-lib/src/components/mips_im.rs index ca5b39f9..c9947a37 100644 --- a/mips-lib/src/components/mips_im.rs +++ b/mips-lib/src/components/mips_im.rs @@ -23,11 +23,18 @@ pub struct InstrMem { pub pc: Input, // All components who deal with memory acess this pub phys_mem_id: String, + pub regfile_id: String, pub mem_view: RefCell, } impl InstrMem { - pub fn new(id: String, pos: (f32, f32), pc_input: Input, phys_mem_id: String) -> InstrMem { + pub fn new( + id: String, + pos: (f32, f32), + pc_input: Input, + phys_mem_id: String, + regfile_id: String, + ) -> InstrMem { let mem_view = MemViewWindow::new(id.clone(), "instruction memory view".into()).set_code_view(None); InstrMem { @@ -36,6 +43,7 @@ impl InstrMem { pc: pc_input, phys_mem_id: phys_mem_id, mem_view: RefCell::new(mem_view), + regfile_id: regfile_id, } } pub fn rc_new( @@ -43,12 +51,9 @@ impl InstrMem { pos: (f32, f32), pc_input: Input, phys_mem_id: String, + regfile_id: String, ) -> Rc { - Rc::new(InstrMem::new(id, pos, pc_input, phys_mem_id)) - } - pub fn set_mem_view_reg(mut self, reg_rc: Rc) -> Self { - self.mem_view.get_mut().update_regfile(reg_rc); - self + Rc::new(InstrMem::new(id, pos, pc_input, phys_mem_id, regfile_id)) } } @@ -70,6 +75,7 @@ impl Component for InstrMem { pc: dummy_input, phys_mem_id: "dummy".into(), mem_view: RefCell::new(MemViewWindow::new("dummy".into(), "IM dummy".into())), + regfile_id: "dummy".into(), })) } diff --git a/mips-lib/src/gui_egui/components/mips_dm.rs b/mips-lib/src/gui_egui/components/mips_dm.rs index 28bbb32a..6939c19e 100644 --- a/mips-lib/src/gui_egui/components/mips_dm.rs +++ b/mips-lib/src/gui_egui/components/mips_dm.rs @@ -1,4 +1,4 @@ -use crate::components::{DataMem, PhysicalMem}; +use crate::components::{DataMem, PhysicalMem, RegFile}; use egui::{Rect, Response, RichText, Ui, Vec2}; use syncrim::common::{EguiComponent, Id, Ports, Simulator}; use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; @@ -51,7 +51,24 @@ impl EguiComponent for DataMem { }; // }); }); - if let Some(sim) = simulator { + + if let Some(sim) = &simulator { + let v = &sim.ordered_components; + let comp = v + .into_iter() + .find(|x| x.get_id_ports().0 == self.regfile_id) + .expect(&format!("cant find {} in simulator", self.regfile_id)); + // deref to get &dyn EguiComponent + let comp_any = (*comp).as_any(); + let regfile: &RegFile = comp_any + .downcast_ref() + .expect("can't downcast to physical memory"); + self.mem_view + .borrow_mut() + .set_reg_values(regfile.registers.borrow().clone()); + } + + if let Some(sim) = &simulator { let v = &sim.ordered_components; let comp = v .into_iter() diff --git a/mips-lib/src/gui_egui/components/mips_im.rs b/mips-lib/src/gui_egui/components/mips_im.rs index 5541cbb4..d68b1604 100644 --- a/mips-lib/src/gui_egui/components/mips_im.rs +++ b/mips-lib/src/gui_egui/components/mips_im.rs @@ -6,6 +6,7 @@ use std::path::PathBuf; use crate::components::InstrMem; use crate::components::MipsMem; use crate::components::PhysicalMem; +use crate::components::RegFile; // use crate::gui_egui::mips_mem_view_window::MemViewWindow; use egui::{Rect, Response, RichText, Ui, Vec2}; use syncrim::common::{EguiComponent, Id, Ports, Simulator}; @@ -58,7 +59,23 @@ impl EguiComponent for InstrMem { // }); }); - if let Some(sim) = simulator { + if let Some(sim) = &simulator { + let v = &sim.ordered_components; + let comp = v + .into_iter() + .find(|x| x.get_id_ports().0 == self.regfile_id) + .expect(&format!("cant find {} in simulator", self.regfile_id)); + // deref to get &dyn EguiComponent + let comp_any = (*comp).as_any(); + let regfile: &RegFile = comp_any + .downcast_ref() + .expect("can't downcast to physical memory"); + self.mem_view + .borrow_mut() + .set_reg_values(regfile.registers.borrow().clone()); + } + + if let Some(sim) = &simulator { let v = &sim.ordered_components; let comp = v .into_iter() diff --git a/mips-lib/src/gui_egui/mips_mem_view_window.rs b/mips-lib/src/gui_egui/mips_mem_view_window.rs index 7c2a710d..c782796d 100644 --- a/mips-lib/src/gui_egui/mips_mem_view_window.rs +++ b/mips-lib/src/gui_egui/mips_mem_view_window.rs @@ -38,7 +38,7 @@ pub struct MemViewWindow { show_settings: ShowSettings, // used for show register - reg_ref: Option>, + register_values: Option<[u32; 32]>, // used to show pc and jump to pc // why not a Rc? because that would cause circular dependency and a memory leak @@ -109,30 +109,15 @@ impl MemViewWindow { program_counter: false, registers: [false; 32], }, - reg_ref: None, + register_values: None, dynamic_symbols: HashMap::new(), break_points: HashSet::new(), } } - pub fn new_with_reg( - id: String, - title: String, - mem: Rc>, - regfile: Rc, - _pc_ref: Rc>, - ) -> Self { - MemViewWindow::new(id, title).set_regfile(regfile) - } - - /// set a reference to a regfile which allows for jumping and displaying registers - pub fn set_regfile(mut self, regfile_rc: Rc) -> Self { - self.reg_ref = Some(regfile_rc); - self - } - - pub fn update_regfile(&mut self, regfile_rc: Rc) { - self.reg_ref = Some(regfile_rc) + /// set register values, allows to display where they point as well as jump to them + pub fn set_reg_values(&mut self, reg_values: [u32; 32]) { + self.register_values = Some(reg_values); } /// Set the extra symbols address, if no symbol exist add that symbol pub fn set_dynamic_symbol(&mut self, symbol: &str, adrs: u32) { @@ -335,33 +320,32 @@ impl MemViewWindow { } } - if let Some(reg) = &self.reg_ref { + if let Some(reg) = &self.register_values { ui.separator(); - let gp = reg.get_registers(28); + let gp = reg[28]; if ui.button(format!("Global pointer ({:#0x})", gp)).clicked() { self.go_to_address = set_address(&self.go_type, gp) } - let sp = reg.get_registers(29); + let sp = reg[29]; if ui.button(format!("Stack pointer ({:#0x})", sp)).clicked() { self.go_to_address = set_address(&self.go_type, sp) } - let fp = reg.get_registers(30); + let fp = reg[30]; if ui.button(format!("Frame pointer ({:#0x})", fp)).clicked() { self.go_to_address = set_address(&self.go_type, fp) } - let ra = reg.get_registers(31); + let ra = reg[31]; if ui.button(format!("Return address ({:#0x})", gp)).clicked() { self.go_to_address = set_address(&self.go_type, ra) } ui.separator(); - // TODO add "go to other register" ui.menu_button("Other Register", |ui| { ScrollArea::vertical().show(ui, |ui| { for (i, name) in REG_NAMES.iter().enumerate() { - let val = reg.get_registers(i); + let val = reg[i]; if ui.button(format!("${} {:#0x}", name, val)).clicked() { self.go_to_address = set_address(&self.go_type, val); ui.close_menu(); @@ -421,7 +405,7 @@ impl MemViewWindow { ui.menu_button("Show", |ui| { ui.checkbox(&mut self.show_settings.symbols, "Symbols"); ui.checkbox(&mut self.show_settings.sections, "Sections"); - if let Some(_) = &self.reg_ref { + if let Some(_) = &self.register_values { ui.separator(); ui.checkbox(&mut self.show_settings.registers[28], "Global Pointer"); @@ -620,9 +604,9 @@ impl MemViewWindow { out_vec.push(sym.get(adrs).unwrap()) } - if let Some(reg) = &self.reg_ref { + if let Some(reg) = &self.register_values { for (i, show) in self.show_settings.registers.iter().enumerate() { - if *show && (reg.get_registers(i) & !0b11) == *adrs { + if *show && (reg[i] & !0b11) == *adrs { out_vec.push(REG_NAMES[i]) } } diff --git a/mips-simple/src/main.rs b/mips-simple/src/main.rs index 8dc431ff..6a3d454e 100644 --- a/mips-simple/src/main.rs +++ b/mips-simple/src/main.rs @@ -13,16 +13,6 @@ use syncrim::{ fn main() { fern_setup(); - let rc_reg_file = RegFile::rc_new( - "reg_file", - (350.0, 225.0), - Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), - Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), - Input::new("reg_write_addr", REGISTER_OUT_ID), //write address - Input::new("result_reg", REGISTER_OUT_ID), //write data - Input::new("reg_we", REGISTER_OUT_ID), - ); - let cs = ComponentStore { store: vec![ Rc::new(PhysicalMem::new("phys_mem", (0.0, 0.0))), @@ -42,15 +32,13 @@ fn main() { ), // // - Rc::new( - InstrMem::new( - "instr_mem".into(), - (250.0, 575.0), - Input::new("pc", REGISTER_OUT_ID), - "phys_mem".into(), - ) - .set_mem_view_reg(rc_reg_file.clone()), - ), + Rc::new(InstrMem::new( + "instr_mem".into(), + (250.0, 575.0), + Input::new("pc", REGISTER_OUT_ID), + "phys_mem".into(), + "reg_file".into(), + )), // // // MUX to choose what intruction addr to choose from, branch jump, reg, pc+4 @@ -156,18 +144,16 @@ fn main() { ), // // - Rc::new( - DataMem::new( - "data_mem".into(), - (600.0, 575.0), - Input::new("alu", FULL_ADD_OUT_ID), // calculated from rs and imm - Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), - Input::new("control_unit", cntr_field::MEM_MODE_OUT), - Input::new("control_unit", cntr_field::MEM_WRITE_ENABLE_OUT), - "phys_mem".into(), - ) - .set_mem_view_reg(rc_reg_file.clone()), - ), + Rc::new(DataMem::new( + "data_mem".into(), + (600.0, 575.0), + Input::new("alu", FULL_ADD_OUT_ID), // calculated from rs and imm + Input::new("reg_file", reg_file_fields::RT_VALUE_OUT_ID), + Input::new("control_unit", cntr_field::MEM_MODE_OUT), + Input::new("control_unit", cntr_field::MEM_WRITE_ENABLE_OUT), + "phys_mem".into(), + "reg_file".into(), + )), // // Mux::rc_new( @@ -224,7 +210,15 @@ fn main() { ), // // - rc_reg_file, + RegFile::rc_new( + "reg_file", + (350.0, 225.0), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), + Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), + Input::new("reg_write_addr", REGISTER_OUT_ID), //write address + Input::new("result_reg", REGISTER_OUT_ID), //write data + Input::new("reg_we", REGISTER_OUT_ID), + ), ], }; From 046b8daaf6ec76513eb1189d248c2aa72d7d644b Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 5 Sep 2024 15:46:22 +0200 Subject: [PATCH 098/126] propagate response from wire --- src/gui_egui/components/wire.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index f3efb344..508358ac 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -87,10 +87,15 @@ impl EguiComponent for Wire { color: Color32::BLACK, }, )); + let mut r: Vec = vec![]; for val in line_vec.windows(2) { let first_pos = val[0]; let last_pos = val[1]; + r.push( + ui.allocate_ui_at_rect(Rect::from_two_pos(first_pos, last_pos), |_| {}) + .response, + ); if let Some(cursor) = ui.ctx().pointer_latest_pos() { if min_from_line(first_pos.to_vec2(), last_pos.to_vec2(), cursor.to_vec2()) < TOOLTIP_DISTANCE @@ -113,7 +118,7 @@ impl EguiComponent for Wire { _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), } - Some(vec![]) + Some(r) } fn render_editor( From 4de6fc139c8626a547b34409fdf434e8213fd7ba Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Sat, 7 Sep 2024 17:34:50 +0200 Subject: [PATCH 099/126] updated add and mux to have scale variable --- mips-simple/src/main.rs | 21 ++++++++++++++------- src/components/add.rs | 20 ++++++++++++++++++++ src/components/mux.rs | 19 +++++++++++++++++++ src/gui_egui/components/add.rs | 14 +++++++------- src/gui_egui/components/mux.rs | 26 +++++++++++++++++--------- src/gui_egui/editor.rs | 2 ++ 6 files changed, 79 insertions(+), 23 deletions(-) diff --git a/mips-simple/src/main.rs b/mips-simple/src/main.rs index 6a3d454e..73e1c3a7 100644 --- a/mips-simple/src/main.rs +++ b/mips-simple/src/main.rs @@ -24,11 +24,12 @@ fn main() { ), // step addr from reg by 4 Constant::rc_new("+4", (150.0, 440.0), 4), - Add::rc_new( + Add::rc_new_with_scale( "pc+4", (200.0, 400.0), Input::new("+4", CONSTANT_OUT_ID), Input::new("pc", REGISTER_OUT_ID), + 0.6, ), // // @@ -42,7 +43,7 @@ fn main() { // // // MUX to choose what intruction addr to choose from, branch jump, reg, pc+4 - Mux::rc_new( + Mux::rc_new_with_scale( "mux_jump_merge", (100.0, 390.0), Input::new("branch", BRANCH_OUT_ID), @@ -52,6 +53,7 @@ fn main() { Input::new("jump_merge", MERGE_OUT_ID), // Input::new("pc+4", ADD_OUT_ID), ], + 0.6, ), // // merges to find out jump location @@ -111,7 +113,7 @@ fn main() { // // Constant::rc_new("0_a_inp", (610.0, 220.0), 0), - Mux::rc_new( + Mux::rc_new_with_scale( "mux_source_a", (650.0, 195.0), Input::new("control_unit", cntr_field::ALU_SRC_A_OUT), @@ -120,10 +122,11 @@ fn main() { Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), Input::new("0_a_inp", CONSTANT_OUT_ID), ], + 0.6, ), // // - Mux::rc_new( + Mux::rc_new_with_scale( "mux_source_b", (650.0, 255.0), Input::new("control_unit", cntr_field::ALU_SRC_B_OUT), @@ -132,6 +135,7 @@ fn main() { Input::new("pc+4", ADD_OUT_ID), Input::new("signzero_extend", SIGNZEROEXTEND_OUT_ID), ], + 0.6, ), // // @@ -156,7 +160,7 @@ fn main() { )), // // - Mux::rc_new( + Mux::rc_new_with_scale( "mux_write_back", (800.0, 225.0), Input::new("control_unit", cntr_field::REG_WRITE_SRC_OUT), @@ -164,6 +168,7 @@ fn main() { Input::new("alu", FULL_ADD_OUT_ID), Input::new("data_mem", DATA_MEM_READ_DATA_OUT_ID), //TODO: data meme output ], + 0.6, ), // // @@ -182,16 +187,17 @@ fn main() { ), // // - Add::rc_new( + Add::rc_new_with_scale( "pc_add_branch", (400.0, 475.0), Input::new("pc+4", ADD_OUT_ID), Input::new("branch_shift", SHIFT_OUT_ID), + 0.6, ), // // Constant::rc_new("0x_1F", (350.0, 550.0), 0x_1F), - Mux::rc_new( + Mux::rc_new_with_scale( "mux_write_addr", (400.0, 525.0), Input::new("control_unit", cntr_field::REG_DEST_OUT), @@ -200,6 +206,7 @@ fn main() { Input::new("instruction_split", INSTRUCTION_SPLITTER_RD_ID), Input::new("0x_1F", CONSTANT_OUT_ID), ], + 0.6, ), // // diff --git a/src/components/add.rs b/src/components/add.rs index 2741e43e..f1bf95cd 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -20,6 +20,7 @@ pub struct Add { pub(crate) pos: (f32, f32), pub(crate) a_in: Input, pub(crate) b_in: Input, + pub(crate) scale: f32, } #[typetag::serde] @@ -35,6 +36,7 @@ impl Component for Add { pos: (pos.0, pos.1), a_in: dummy_input.clone(), b_in: dummy_input.clone(), + scale: 1.0, })) } fn get_id_ports(&self) -> (Id, Ports) { @@ -114,12 +116,29 @@ impl Add { pos, a_in, b_in, + scale: 1.0, } } pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input) -> Rc { Rc::new(Add::new(id, pos, a_in, b_in)) } + + pub fn rc_new_with_scale( + id: &str, + pos: (f32, f32), + a_in: Input, + b_in: Input, + scale: f32, + ) -> Rc { + Rc::new(Add { + id: id.to_string(), + pos, + a_in, + b_in, + scale, + }) + } } #[cfg(test)] @@ -143,6 +162,7 @@ mod test { pos: (0.0, 0.0), a_in: Input::new("po1", "out"), b_in: Input::new("po2", "out"), + scale: 1.0, }), ], }; diff --git a/src/components/mux.rs b/src/components/mux.rs index f719e363..bc591f05 100644 --- a/src/components/mux.rs +++ b/src/components/mux.rs @@ -19,6 +19,7 @@ pub struct Mux { pub(crate) pos: (f32, f32), pub(crate) select: Input, pub(crate) m_in: Vec, + pub scale: f32, } #[typetag::serde] @@ -34,6 +35,7 @@ impl Component for Mux { pos: (pos.0, pos.1), select: dummy_input.clone(), m_in: vec![dummy_input.clone(), dummy_input.clone()], + scale: 1.0, })) } fn get_id_ports(&self) -> (Id, Ports) { @@ -113,10 +115,27 @@ impl Mux { pos, select, m_in, + scale: 1.0, } } pub fn rc_new(id: &str, pos: (f32, f32), select: Input, m_in: Vec) -> Rc { Rc::new(Mux::new(id, pos, select, m_in)) } + + pub fn rc_new_with_scale( + id: &str, + pos: (f32, f32), + select: Input, + m_in: Vec, + scale: f32, + ) -> Rc { + Rc::new(Mux { + id: id.to_string(), + pos, + select, + m_in, + scale, + }) + } } diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 756c6307..ec919d62 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -46,7 +46,7 @@ impl EguiComponent for Add { (-20f32, -20f32), ]; - let comp_scale = 0.6; + let comp_scale = self.scale; // The shape ui.painter().add(Shape::closed_line( @@ -75,8 +75,8 @@ impl EguiComponent for Add { }, )); let rect = Rect { - min: oh((-20f32, -40f32), s, o), - max: oh((20f32, 40f32), s, o), + min: oh((-20.0 * self.scale, -40.0 * self.scale), s, o), + max: oh((20.0 * self.scale, 40.0 * self.scale), s, o), }; let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { ui.label(format!("Id: {}", self.id.clone())); @@ -161,19 +161,19 @@ impl EguiComponent for Add { vec![ ( crate::components::ADD_A_IN_ID.to_string(), - Pos2::new(-20f32, -20f32) + own_pos, + Pos2::new(-20f32, -20f32) * self.scale + own_pos, ), ( crate::components::ADD_B_IN_ID.to_string(), - Pos2::new(-20f32, 20f32) + own_pos, + Pos2::new(-20f32, 20f32) * self.scale + own_pos, ), ( crate::components::ADD_OUT_ID.to_string(), - Pos2::new(20f32, 0f32) + own_pos, + Pos2::new(20f32, 0f32) * self.scale + own_pos, ), ( crate::components::ADD_OVERFLOW_ID.to_string(), - Pos2::new(0f32, -40f32) + own_pos, + Pos2::new(0f32, -40f32) * self.scale + own_pos, ), ] } diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index ec769683..7bd11220 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -46,8 +46,8 @@ impl EguiComponent for Mux { (-20f32, pa * (10f32) + 10f32), ]; for (x, y) in shape.iter_mut() { - *x *= 0.6; - *y *= 0.6; + *x *= self.scale; + *y *= self.scale; } // The shape @@ -64,13 +64,13 @@ impl EguiComponent for Mux { [ oh( ( - -20f32 * 0.6, - (((select as f32) * 20f32) - pa * 10f32 + 10f32) * 0.6, + -20f32 * self.scale, + (((select as f32) * 20f32) - pa * 10f32 + 10f32) * self.scale, ), s, o, ), - oh((10f32 * 0.6, 0f32 * 0.6), s, o), + oh((10f32 * self.scale, 0f32 * self.scale), s, o), ], Stroke { width: scale, @@ -79,8 +79,16 @@ impl EguiComponent for Mux { )); let rect = Rect { - min: oh((-20f32 * 0.6, (pa * (-10f32) - 10f32) * 0.6), s, o), - max: oh((10f32 * 0.6, (pa * 10f32 + 10f32) * 0.6), s, o), + min: oh( + (-20f32 * self.scale, (pa * (-10f32) - 10f32) * self.scale), + s, + o, + ), + max: oh( + (10f32 * self.scale, (pa * 10f32 + 10f32) * self.scale), + s, + o, + ), }; let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { ui.label(format!("Id: {}", self.id.clone())); @@ -185,12 +193,12 @@ impl EguiComponent for Mux { for i in 0..=self.m_in.len() - 1 { v.push(( format!("{}{}", crate::components::MUX_TEMPLATE_ID, i), - Pos2::new(-20f32, top + i as f32 * 20f32 + 20f32) + own_pos, + Pos2::new(-20f32, top + i as f32 * 20f32 + 20f32) * self.scale + own_pos, )); } v.push(( crate::components::MUX_OUT_ID.to_string(), - Pos2::new(10f32, 0f32) + own_pos, + Pos2::new(10f32, 0f32) * self.scale + own_pos, )); v } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 8cd62985..1363df8b 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -86,6 +86,7 @@ impl Default for Library { pos: (0.0, 0.0), a_in: dummy_input.clone(), b_in: dummy_input.clone(), + scale: 1.0, }), Rc::new(Constant { id: "c".to_string(), @@ -127,6 +128,7 @@ impl Default for Library { pos: (0.0, 0.0), select: dummy_input.clone(), m_in: vec![dummy_input.clone(), dummy_input.clone()], + scale: 1.0, }), Rc::new(Register { id: "reg".to_string(), From 1efa585425a4c86a667c77cfb2e0f5ca13bb8e47 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Mon, 9 Sep 2024 12:56:10 +0200 Subject: [PATCH 100/126] fixed overflow bug --- mips-lib/src/components/full_adder.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mips-lib/src/components/full_adder.rs b/mips-lib/src/components/full_adder.rs index fa699f3b..9b1cf239 100644 --- a/mips-lib/src/components/full_adder.rs +++ b/mips-lib/src/components/full_adder.rs @@ -153,16 +153,16 @@ impl Component for FullAdd { output = (a < b) as u32; } alu_op::SLL => { - output = a << b; + output = a.overflowing_shl(b).0; // https://doc.rust-lang.org/std/primitive.u32.html#method.overflowing_shl } alu_op::SRL => { - output = a >> b; + output = a.overflowing_shr(b).0; } alu_op::SRA => { - output = ((a as i32) >> b) as u32; + output = (a as i32).overflowing_shr(b).0 as u32; } alu_op::LUI => { - output = (a & 0x0000_ffff) | (b << 16); + output = (a & 0x0000_ffff) | b.overflowing_shl(16).0; } _ => { return Err(Condition::Error( From 19487323a116b3e505de1dca7963a5a52c0fc5a0 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Mon, 9 Sep 2024 13:40:21 +0200 Subject: [PATCH 101/126] worked on organizing wires --- examples/and.rs | 33 ++++++ .../src/gui_egui/components/full_adder.rs | 48 ++++++--- .../components/mips_instruction_splitter.rs | 102 ++++++++++++++++-- .../src/gui_egui/components/mips_reg_file.rs | 2 +- mips-lib/src/main.rs | 31 ++++++ src/common.rs | 2 +- src/gui_egui/components/add.rs | 22 ++++ src/gui_egui/components/and.rs | 34 +++++- src/gui_egui/components/equal.rs | 34 +++++- src/gui_egui/components/mux.rs | 21 +++- src/gui_egui/components/register.rs | 2 +- src/gui_egui/components/wire.rs | 42 ++++++-- src/mips_helper_functions.rs | 4 +- 13 files changed, 335 insertions(+), 42 deletions(-) create mode 100644 examples/and.rs create mode 100644 mips-lib/src/main.rs diff --git a/examples/and.rs b/examples/and.rs new file mode 100644 index 00000000..8877fe4c --- /dev/null +++ b/examples/and.rs @@ -0,0 +1,33 @@ +use std::path::PathBuf; +#[cfg(feature = "gui-egui")] +use syncrim::gui_egui::editor::Library; +use syncrim::{ + common::{ComponentStore, Input}, + components::*, + fern::fern_setup, +}; +fn main() { + fern_setup(); + let cs = ComponentStore { + store: vec![ + ProbeEdit::rc_new("A", (100.0, 100.0)), + ProbeEdit::rc_new("B", (100.0, 140.0)), + And::rc_new( + "and", + (150.0, 120.0), + Input::new("A", PROBE_EDIT_OUT_ID), + Input::new("B", PROBE_EDIT_OUT_ID), + ), + Probe::rc_new("probe", (250.0, 100.0), Input::new("and", AND_OUT_ID)), + ], + }; + + let path = PathBuf::from("and.json"); + cs.save_file(&path); + + #[cfg(feature = "gui-egui")] + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + + #[cfg(feature = "gui-vizia")] + syncrim::gui_vizia::gui(cs, &path); +} diff --git a/mips-lib/src/gui_egui/components/full_adder.rs b/mips-lib/src/gui_egui/components/full_adder.rs index 6a69e069..5a6fbcd8 100644 --- a/mips-lib/src/gui_egui/components/full_adder.rs +++ b/mips-lib/src/gui_egui/components/full_adder.rs @@ -1,6 +1,9 @@ -use crate::components::{alu_op, FullAdd, FULL_ADD_OUT_ID, FULL_ADD_OVERFLOW_OUT_ID}; +use crate::components::{ + alu_op, FullAdd, FULL_ADD_A_IN_ID, FULL_ADD_B_IN_ID, FULL_ADD_OP_IN_ID, FULL_ADD_OUT_ID, + FULL_ADD_OVERFLOW_OUT_ID, +}; use egui::{ - vec2, Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Stroke, + pos2, vec2, Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Shape, Stroke, TextWrapMode, Ui, Vec2, }; use syncrim::common::{EguiComponent, Input, Ports, Simulator}; @@ -11,6 +14,7 @@ use syncrim::gui_egui::component_ui::{ use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use syncrim::gui_egui::gui::EguiExtra; use syncrim::gui_egui::helper::offset_helper; +use syncrim::signal::Id; #[typetag::serde] impl EguiComponent for FullAdd { @@ -176,19 +180,7 @@ impl EguiComponent for FullAdd { } } - fn top_padding(&self) -> f32 { - 20f32 - } - - fn set_pos(&mut self, pos: (f32, f32)) { - self.pos = pos; - } - - fn get_pos(&self) -> (f32, f32) { - self.pos - } - - fn get_port_location(&self, id: Input) -> Option<(f32, f32)> { + fn get_input_location(&self, id: Input) -> Option<(f32, f32)> { if id == self.a_in { Some((Pos2::from(self.pos) + vec2(-20.0, -30.0)).into()) } else if id == self.b_in { @@ -203,4 +195,30 @@ impl EguiComponent for FullAdd { None } } + + fn ports_location(&self) -> Vec<(Id, egui::Pos2)> { + let own_pos: Vec2 = self.pos.into(); + vec![ + (FULL_ADD_A_IN_ID.to_string(), pos2(-20.0, -30.0) + own_pos), + (FULL_ADD_B_IN_ID.to_string(), pos2(-20.0, 30.0) + own_pos), + (FULL_ADD_OP_IN_ID.to_string(), pos2(-10.0, -40.0) + own_pos), + (FULL_ADD_OUT_ID.to_string(), pos2(20.0, 0.0) + own_pos), + ( + FULL_ADD_OVERFLOW_OUT_ID.to_string(), + pos2(-20.0, 5.0) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + 20f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } } diff --git a/mips-lib/src/gui_egui/components/mips_instruction_splitter.rs b/mips-lib/src/gui_egui/components/mips_instruction_splitter.rs index b2ec778d..bc7f1c63 100644 --- a/mips-lib/src/gui_egui/components/mips_instruction_splitter.rs +++ b/mips-lib/src/gui_egui/components/mips_instruction_splitter.rs @@ -1,10 +1,17 @@ -use crate::components::InstrSplit; -use egui::{Rect, Response, RichText, Ui, Vec2}; -use syncrim::common::{EguiComponent, Id, Ports, Simulator}; +use crate::components::{ + InstrSplit, INSTRUCTION_SPLITTER_FUNCT_ID, INSTRUCTION_SPLITTER_IMMEDIATE_ID, + INSTRUCTION_SPLITTER_OP_ID, INSTRUCTION_SPLITTER_RD_ID, INSTRUCTION_SPLITTER_RS_ID, + INSTRUCTION_SPLITTER_RT_ID, INSTRUCTION_SPLITTER_SHAMT_ID, INSTRUCTION_SPLITTER_TARGET_ID, +}; +use egui::{pos2, Pos2, Rect, Response, RichText, Ui, Vec2}; +use syncrim::common::{EguiComponent, Id, Input, Ports, Simulator}; use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use syncrim::gui_egui::gui::EguiExtra; use syncrim::gui_egui::helper::basic_component_gui; +const WIDTH: f32 = 50.0; +const HEIGHT: f32 = 200.0; + #[typetag::serde] impl EguiComponent for InstrSplit { fn render( @@ -18,11 +25,11 @@ impl EguiComponent for InstrSplit { _editor_mode: EditorMode, ) -> Option> { // size of the component - let width = 50f32 * scale; - let height: f32 = 200f32 * scale; + let w = WIDTH * scale; + let h: f32 = HEIGHT * scale; basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { - ui.set_height(height); - ui.set_width(width); + ui.set_height(h); + ui.set_width(w); ui.centered_and_justified(|ui| { ui.label(RichText::new("instruction\n splitter").size(12f32 * scale)); }); @@ -67,4 +74,85 @@ impl EguiComponent for InstrSplit { fn top_padding(&self) -> f32 { 20f32 } + + fn ports_location(&self) -> Vec<(syncrim::common::Id, Pos2)> { + // width 50 + // height 200 + let own_pos = Vec2::new(self.pos.0, self.pos.1); + const M: f32 = 6.0; + fn out_pos(i: u32) -> Pos2 { + pos2( + WIDTH / 2.0 + M, + -HEIGHT / 2.0 + (i as f32 + 1.0) * HEIGHT / 9.0, + ) + } + vec![ + ( + crate::components::INSTRUCTION_SPLITTER_IN_ID.to_string(), + Pos2::new(-WIDTH / 2.0 - M, 0.0) + own_pos, + ), + ( + crate::components::INSTRUCTION_SPLITTER_SHAMT_ID.to_string(), + out_pos(0) + own_pos, + ), + ( + crate::components::INSTRUCTION_SPLITTER_OP_ID.to_string(), + out_pos(1) + own_pos, + ), + ( + crate::components::INSTRUCTION_SPLITTER_FUNCT_ID.to_string(), + out_pos(2) + own_pos, + ), + ( + crate::components::INSTRUCTION_SPLITTER_RS_ID.to_string(), + out_pos(3) + own_pos, + ), + ( + crate::components::INSTRUCTION_SPLITTER_RT_ID.to_string(), + out_pos(4) + own_pos, + ), + ( + crate::components::INSTRUCTION_SPLITTER_IMMEDIATE_ID.to_string(), + out_pos(5) + own_pos, + ), + ( + crate::components::INSTRUCTION_SPLITTER_RD_ID.to_string(), + out_pos(6) + own_pos, + ), + ( + crate::components::INSTRUCTION_SPLITTER_TARGET_ID.to_string(), + out_pos(7) + own_pos, + ), + ] + } + + fn get_input_location(&self, id: Input) -> Option<(f32, f32)> { + let loc = self + .ports_location() + .iter() + .map(|(_, loc)| <(f32, f32)>::from(loc)) + .collect::>(); + + if id == self.instruction_in { + Some(loc[0]) + } else if id == Input::new(&self.id, INSTRUCTION_SPLITTER_SHAMT_ID) { + Some(loc[1]) + } else if id == Input::new(&self.id, INSTRUCTION_SPLITTER_OP_ID) { + Some(loc[2]) + } else if id == Input::new(&self.id, INSTRUCTION_SPLITTER_FUNCT_ID) { + Some(loc[3]) + } else if id == Input::new(&self.id, INSTRUCTION_SPLITTER_RS_ID) { + Some(loc[4]) + } else if id == Input::new(&self.id, INSTRUCTION_SPLITTER_RT_ID) { + Some(loc[5]) + } else if id == Input::new(&self.id, INSTRUCTION_SPLITTER_IMMEDIATE_ID) { + Some(loc[6]) + } else if id == Input::new(&self.id, INSTRUCTION_SPLITTER_RD_ID) { + Some(loc[7]) + } else if id == Input::new(&self.id, INSTRUCTION_SPLITTER_TARGET_ID) { + Some(loc[8]) + } else { + None + } + } } diff --git a/mips-lib/src/gui_egui/components/mips_reg_file.rs b/mips-lib/src/gui_egui/components/mips_reg_file.rs index 719d8b6f..276c5e25 100644 --- a/mips-lib/src/gui_egui/components/mips_reg_file.rs +++ b/mips-lib/src/gui_egui/components/mips_reg_file.rs @@ -91,7 +91,7 @@ impl EguiComponent for RegFile { }) } - fn get_port_location(&self, id: Input) -> Option<(f32, f32)> { + fn get_input_location(&self, id: Input) -> Option<(f32, f32)> { // components size = (120,250) let margin = egui::style::Spacing::default().window_margin; diff --git a/mips-lib/src/main.rs b/mips-lib/src/main.rs new file mode 100644 index 00000000..ba21d2e8 --- /dev/null +++ b/mips-lib/src/main.rs @@ -0,0 +1,31 @@ +use clap::Parser; +use mips_lib; +use std::path::PathBuf; +#[cfg(feature = "gui-egui")] +use syncrim::gui_egui::editor::Library; +use syncrim::{common::ComponentStore, fern::fern_setup}; +/// Simple program to greet a person +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// Path to the model to load on startup + #[arg(short, long, default_value = "empty.json")] + model: String, +} + +fn main() { + fern_setup(); + let args = Args::parse(); + let path = PathBuf::from(args.model); + + let cs = ComponentStore::load_file(&path); + + #[cfg(feature = "gui-egui")] + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + + #[cfg(feature = "gui-vizia")] + syncrim::gui_vizia::gui(cs, &path); + + #[cfg(not(any(feature = "gui-vizia", feature = "gui-egui")))] + syncrim::common::Simulator::new(cs).unwrap(); +} diff --git a/src/common.rs b/src/common.rs index e40f2975..d0f372c9 100644 --- a/src/common.rs +++ b/src/common.rs @@ -137,7 +137,7 @@ pub trait EguiComponent: Component { } } - fn get_port_location(&self, _id: Input) -> Option<(f32, f32)> { + fn get_input_location(&self, _id: Input) -> Option<(f32, f32)> { None } diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index ec919d62..a3e1f1e5 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -1,3 +1,5 @@ +use crate::common::Input; +use crate::components::{ADD_OUT_ID, ADD_OVERFLOW_ID}; use crate::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, visualize_ports, @@ -178,6 +180,26 @@ impl EguiComponent for Add { ] } + fn get_input_location(&self, id: Input) -> Option<(f32, f32)> { + let loc = self + .ports_location() + .iter() + .map(|(_, loc)| <(f32, f32)>::from(loc)) + .collect::>(); + + if id == self.a_in { + Some(loc[0]) + } else if id == self.b_in { + Some(loc[1]) + } else if id == Input::new(&self.id, ADD_OUT_ID) { + Some(loc[2]) + } else if id == Input::new(&self.id, ADD_OVERFLOW_ID) { + Some(loc[3]) + } else { + None + } + } + fn top_padding(&self) -> f32 { 40f32 } diff --git a/src/gui_egui/components/and.rs b/src/gui_egui/components/and.rs index 8407d1ca..9966ef1e 100644 --- a/src/gui_egui/components/and.rs +++ b/src/gui_egui/components/and.rs @@ -1,9 +1,9 @@ -use crate::common::{EguiComponent, Id, Ports, Simulator}; -use crate::components::And; +use crate::common::{EguiComponent, Id, Input, Ports, Simulator}; +use crate::components::{And, AND_A_IN_ID, AND_B_IN_ID, AND_OUT_ID}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::basic_component_gui; -use egui::{Rect, Response, Ui, Vec2}; +use egui::{pos2, Pos2, Rect, Response, Ui, Vec2}; #[typetag::serde] impl EguiComponent for And { @@ -60,4 +60,32 @@ impl EguiComponent for And { fn top_padding(&self) -> f32 { 20f32 } + + fn get_input_location(&self, id: Input) -> Option<(f32, f32)> { + let loc = self + .ports_location() + .iter() + .map(|(_, loc)| <(f32, f32)>::from(loc)) + .collect::>(); + if id == self.a_in { + Some(loc[0]) + } else if id == self.b_in { + Some(loc[1]) + } else if id == Input::new(&self.id, AND_OUT_ID) { + Some(loc[2]) + } else { + None + } + } + + fn ports_location(&self) -> Vec<(Id, egui::Pos2)> { + //size 22-14 + let m = 6f32; // margin + let pos: Vec2 = self.pos.into(); + vec![ + (AND_A_IN_ID.to_string(), pos2(-11.0 - m, -10.0) + pos), + (AND_B_IN_ID.to_string(), pos2(-11.0 - m, 10.0) + pos), + (AND_OUT_ID.to_string(), pos2(11.0 + m, 0.0) + pos), + ] + } } diff --git a/src/gui_egui/components/equal.rs b/src/gui_egui/components/equal.rs index 853f0bf8..58063c38 100644 --- a/src/gui_egui/components/equal.rs +++ b/src/gui_egui/components/equal.rs @@ -1,9 +1,9 @@ -use crate::common::{EguiComponent, Id, Ports, Simulator}; -use crate::components::Equal; +use crate::common::{EguiComponent, Id, Input, Ports, Simulator}; +use crate::components::{Equal, EQUAL_A_IN_ID, EQUAL_B_IN_ID, EQUAL_OUT_ID}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::basic_component_gui; -use egui::{Rect, Response, Ui, Vec2}; +use egui::{pos2, Rect, Response, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Equal { @@ -60,4 +60,32 @@ impl EguiComponent for Equal { fn top_padding(&self) -> f32 { 20f32 } + + fn get_input_location(&self, id: Input) -> Option<(f32, f32)> { + let loc = self + .ports_location() + .iter() + .map(|(_, loc)| <(f32, f32)>::from(loc)) + .collect::>(); + if id == self.a_in { + Some(loc[0]) + } else if id == self.b_in { + Some(loc[1]) + } else if id == Input::new(&self.id, EQUAL_OUT_ID) { + Some(loc[2]) + } else { + None + } + } + + fn ports_location(&self) -> Vec<(Id, egui::Pos2)> { + //size 22-14 + let m = 6f32; // margin + let pos: Vec2 = self.pos.into(); + vec![ + (EQUAL_A_IN_ID.to_string(), pos2(-11.0 - m, -10.0) + pos), + (EQUAL_B_IN_ID.to_string(), pos2(-11.0 - m, 10.0) + pos), + (EQUAL_OUT_ID.to_string(), pos2(11.0 + m, 0.0) + pos), + ] + } } diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index 7bd11220..8792ab14 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -1,5 +1,5 @@ use crate::common::{EguiComponent, Input, Ports, SignalUnsigned, Simulator}; -use crate::components::Mux; +use crate::components::{Mux, MUX_OUT_ID}; use crate::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, input_selector_removeable, pos_drag_value, properties_window, rect_with_hover, visualize_ports, @@ -182,13 +182,30 @@ impl EguiComponent for Mux { } } + fn get_input_location(&self, id: Input) -> Option<(f32, f32)> { + let loc = self + .ports_location() + .iter() + .map(|(_, loc)| <(f32, f32)>::from(loc)) + .collect::>(); + if let Some(i) = self.m_in.iter().position(|item| item == &id) { + Some(loc[i + 1]) + } else if id == self.select { + Some(loc[0]) + } else if id == Input::new(&self.id, MUX_OUT_ID) { + Some(*loc.last().unwrap()) + } else { + None + } + } + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { let own_pos = Vec2::new(self.pos.0, self.pos.1); let pa = self.m_in.len() as f32; let top = -pa * 10f32 - 10f32; let mut v = vec![( crate::components::MUX_SELECT_ID.to_string(), - Pos2::new(-10f32, top) + own_pos, + Pos2::new(-10f32, top) * self.scale + own_pos, )]; for i in 0..=self.m_in.len() - 1 { v.push(( diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index 42a85233..1b50a424 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -159,7 +159,7 @@ impl EguiComponent for Register { ] } - fn get_port_location(&self, input: Input) -> Option<(f32, f32)> { + fn get_input_location(&self, input: Input) -> Option<(f32, f32)> { let own_pos = self.get_pos(); let input_pos_change = (-10f32, 0f32); let output_pos_change = (10f32, 0f32); diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 508358ac..9648f4bf 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -5,8 +5,8 @@ use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions, SnapP use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::{basic_on_hover, offset_helper, shadow_small_dark}; use egui::{ - Color32, DragValue, Frame, Key, KeyboardShortcut, Margin, Modifiers, PointerButton, Pos2, Rect, - Response, Rounding, Shape, Stroke, Ui, Vec2, Window, + Color32, DragValue, Frame, Key, KeyboardShortcut, Margin, Modifiers, Order, PointerButton, + Pos2, Rect, Response, Rounding, Sense, Shape, Stroke, Ui, Vec2, Window, }; /// if the mouse cursor is less than this distance in points away from the wire display tooltip @@ -92,10 +92,39 @@ impl EguiComponent for Wire { for val in line_vec.windows(2) { let first_pos = val[0]; let last_pos = val[1]; - r.push( - ui.allocate_ui_at_rect(Rect::from_two_pos(first_pos, last_pos), |_| {}) - .response, - ); + let rect = Rect::from_two_pos(first_pos, last_pos); + + // why the fuck do i need this much code just to make sure its rendered at the correct layer + // let resp = ui + // .allocate_ui_at_rect(rect, |ui| { + // let mut layer = ui.layer_id(); + // layer.order = Order::Foreground; + // ui.with_layer_id(layer, |ui| { + // ui.allocate_exact_size( + // rect.size(), + // Sense { + // click: true, + // drag: true, + // focusable: true, + // }, + // ) + // }) + // }) + // .inner + // .inner + // .1; + // // log::debug!("{:?}", resp); + // if resp.contains_pointer() { + // ui.painter().rect_stroke( + // resp.interact_rect, + // Rounding::same(0.0), + // Stroke { + // width: scale, + // color: Color32::RED, + // }, + // ); + // } + // r.push(resp); if let Some(cursor) = ui.ctx().pointer_latest_pos() { if min_from_line(first_pos.to_vec2(), last_pos.to_vec2(), cursor.to_vec2()) < TOOLTIP_DISTANCE @@ -108,7 +137,6 @@ impl EguiComponent for Wire { (first_pos + last_pos.to_vec2()) / 2.0, |ui| basic_on_hover(ui, self, &simulator), ); - break; } }; } diff --git a/src/mips_helper_functions.rs b/src/mips_helper_functions.rs index 10a365bc..8221c478 100644 --- a/src/mips_helper_functions.rs +++ b/src/mips_helper_functions.rs @@ -33,10 +33,10 @@ pub fn autowire(mut cs: ComponentStore) -> ComponentStore { &format!("from {}:{} to {}:{}", s_id, s_field, d_id, d_field), vec![ source_component - .get_port_location(Input::new(s_id, s_field)) + .get_input_location(Input::new(s_id, s_field)) .unwrap_or(source_component.get_pos()), destination_component - .get_port_location(Input::new(s_id, s_field)) + .get_input_location(Input::new(s_id, s_field)) .unwrap_or(destination_component.get_pos()), ], source_port.clone(), From 5d7f01a814c7575c050b227ce13eb1df9fe75406 Mon Sep 17 00:00:00 2001 From: onsdagens Date: Mon, 9 Sep 2024 14:17:34 +0200 Subject: [PATCH 102/126] fix riscv model --- riscv/Cargo.toml | 4 +- riscv/autosave.json | 1 - riscv/riscv.json | 1981 +++++++++++++++++- riscv/src/gui_egui/components/instr_mem.rs | 173 +- riscv/src/gui_egui/components/probe_label.rs | 2 +- riscv/src/gui_egui/components/reg_file.rs | 3 +- riscv/src/gui_egui/components/rv_mem.rs | 7 +- 7 files changed, 2074 insertions(+), 97 deletions(-) delete mode 100644 riscv/autosave.json diff --git a/riscv/Cargo.toml b/riscv/Cargo.toml index 606d0d43..644c6d18 100644 --- a/riscv/Cargo.toml +++ b/riscv/Cargo.toml @@ -16,7 +16,7 @@ log = "0.4.19" num_enum = "0.7.2" fern = "0.6.2" xmas-elf = "0.9.0" -egui = "0.23.0" +egui = "0.28.0" asm_riscv = { git = 'https://github.com/onsdagens/wari' } gimli = "0.27.3" object = "0.31.1" @@ -24,7 +24,7 @@ memmap2 = "0.7.1" riscv_asm_strings = { git = 'https://github.com/perlindgren/riscv_asm_strings' } priority-queue = { version = "1.3.2", features = ["serde"] } riscv-rt = "0.11.0" -egui_extras = "0.23.0" +egui_extras = "0.28.0" [dependencies.syncrim] path = "../" diff --git a/riscv/autosave.json b/riscv/autosave.json deleted file mode 100644 index e8d59b48..00000000 --- a/riscv/autosave.json +++ /dev/null @@ -1 +0,0 @@ -{"store":[{"type":"Register","id":"regfile_rd_reg","pos":[1880.0,1070.0],"r_in":{"id":"decoder","field":"decoder_rd"}},{"type":"Register","id":"rf_ra_we_reg","pos":[1880.0,870.0],"r_in":{"id":"clic","field":"rf_ra_we"}},{"type":"Register","id":"regfile_we_reg","pos":[1880.0,1010.0],"r_in":{"id":"decoder","field":"decoder_wb_write_enable"}},{"type":"Register","id":"stack_depth_reg","pos":[1880.0,810.0],"r_in":{"id":"clic","field":"stack_depth_out"}},{"type":"Register","id":"wb_reg","pos":[1880.0,530.0],"r_in":{"id":"wb_mux","field":"out"}},{"type":"Register","id":"reg","pos":[490.0,700.0],"r_in":{"id":"interrupt_mux","field":"out"}},{"type":"Constant","id":"zero_c","pos":[1350.0,430.0],"value":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}},{"type":"Wire","id":"auipc_lui_imm_op_a","pos":[[815.0,370.0],[1380.0,370.0]],"input":{"id":"zero_c","field":"out"}},{"type":"Constant","id":"pc_adder_c","pos":[520.0,640.0],"value":{"data":{"Data":4},"fmt":{"Hex":["_32",false]}}},{"type":"Wire","id":"ra_we_to_rf","pos":[[1890.0,1010.0],[1940.0,1010.0],[1940.0,270.0],[1020.0,270.0],[1020.0,440.0]],"input":{"id":"regfile_we_reg","field":"out"}},{"type":"Wire","id":"blu_int_to_rf","pos":[[1890.0,870.0],[1930.0,870.0],[1930.0,280.0],[1100.0,280.0],[1100.0,440.0]],"input":{"id":"regfile_we_reg","field":"out"}},{"type":"Wire","id":"zero_c_data","pos":[[1360.0,430.0],[1380.0,430.0]],"input":{"id":"zero_c","field":"out"}},{"type":"Wire","id":"w11","pos":[[815.0,390.0],[1380.0,390.0]],"input":{"id":"zero_c","field":"out"}},{"type":"Wire","id":"pc_c","pos":[[520.0,640.0],[540.0,640.0]],"input":{"id":"pc_adder_c","field":"out"}},{"type":"Wire","id":"w11111","pos":[[815.0,410.0],[1380.0,410.0]],"input":{"id":"zero_c","field":"out"}},{"type":"Wire","id":"stack_depth_to_rf","pos":[[1890.0,810.0],[1920.0,810.0],[1920.0,290.0],[1140.0,290.0],[1140.0,440.0]],"input":{"id":"stack_depth_reg","field":"out"}},{"type":"Wire","id":"w1","pos":[[1890.0,530.0],[1910.0,530.0],[1910.0,300.0],[1180.0,300.0],[1180.0,440.0]],"input":{"id":"wb_reg","field":"out"}},{"type":"Wire","id":"curr_pc","pos":[[520.0,700.0],[520.0,1010.0],[1340.0,1010.0],[1340.0,880.0],[1380.0,880.0]],"input":{"id":"reg","field":"out"}},{"type":"InstrMem","width":100.0,"height":100.0,"id":"instr_mem","pos":[670.0,900.0],"pc":{"id":"reg","field":"out"},"range":{"start":0,"end":8192},"le":true},{"type":"Decoder","width":30.0,"height":600.0,"id":"decoder","pos":[800.0,620.0],"instruction":{"id":"instr_mem","field":"instruction"}},{"type":"Wire","id":"decoder_shamt","pos":[[815.0,840.0],[1380.0,840.0]],"input":{"id":"decoder","field":"decoder_shamt"}},{"type":"Wire","id":"decoder_store_offset_imm","pos":[[815.0,800.0],[1380.0,800.0]],"input":{"id":"decoder","field":"decoder_store_offset_imm"}},{"type":"Wire","id":"decoder_rs1","pos":[[815.0,545.0],[955.0,545.0]],"input":{"id":"decoder","field":"decoder_rs1"}},{"type":"Wire","id":"decoder_zimm","pos":[[815.0,880.0],[1300.0,880.0],[1300.0,710.0],[1470.0,710.0]],"input":{"id":"decoder","field":"decoder_zimm"}},{"type":"Wire","id":"decoder_rs2","pos":[[815.0,710.0],[815.0,685.0],[955.0,685.0]],"input":{"id":"decoder","field":"decoder_rs2"}},{"type":"Wire","id":"decoder_imm","pos":[[815.0,820.0],[1380.0,820.0]],"input":{"id":"decoder","field":"decoder_imm"}},{"type":"Wire","id":"we","pos":[[815.0,900.0],[900.0,900.0],[900.0,1060.0],[1850.0,1060.0],[1850.0,1010.0],[1870.0,1010.0]],"input":{"id":"decoder","field":"decoder_wb_write_enable"}},{"type":"Wire","id":"decoder_rd","pos":[[815.0,910.0],[890.0,910.0],[890.0,1070.0],[1870.0,1070.0]],"input":{"id":"decoder","field":"decoder_rd"}},{"type":"RegFile","id":"reg_file","pos":[1080.0,615.0],"width":250.0,"height":350.0,"stack_depth":{"id":"stack_depth_reg","field":"out"},"clic_ra_we":{"id":"rf_ra_we_reg","field":"out"},"read_addr1":{"id":"decoder","field":"decoder_rs1"},"read_addr2":{"id":"decoder","field":"decoder_rs2"},"write_data":{"id":"wb_reg","field":"out"},"write_addr":{"id":"regfile_rd_reg","field":"out"},"write_enable":{"id":"regfile_rd_reg","field":"out"},"history":[{"stack_depth":0,"read_addr1":0,"read_addr2":0,"write_addr2":null,"old_data":null,"old_ra":null}]},{"type":"Mux","id":"alu_operand_b_mux","pos":[1400.0,830.0],"select":{"id":"decoder","field":"decoder_alu_b_mux_sel"},"m_in":[{"id":"reg_file","field":"reg_b"},{"id":"decoder","field":"decoder_store_offset_imm"},{"id":"decoder","field":"decoder_imm"},{"id":"decoder","field":"decoder_shamt"},{"id":"decoder","field":"decoder_lui_auipc_imm"},{"id":"reg","field":"out"}]},{"type":"Wire","id":"alu_operand_b","pos":[[1410.0,830.0],[1440.0,830.0],[1440.0,530.0],[1460.0,530.0]],"input":{"id":"alu_operand_b_mux","field":"out"}},{"type":"Cross","id":"c0","pos":[1220.0,780.0],"input":{"id":"reg_file","field":"reg_b"}},{"type":"Mux","id":"alu_operand_a_mux","pos":[1400.0,410.0],"select":{"id":"decoder","field":"decoder_alu_a_mux_sel"},"m_in":[{"id":"decoder","field":"decoder_lui_auipc_imm"},{"id":"decoder","field":"decoder_jal_imm"},{"id":"decoder","field":"decoder_branch_imm"},{"id":"zero_c","field":"out"},{"id":"reg_file","field":"reg_a"}]},{"type":"Wire","id":"alu_operand_a","pos":[[1410.0,410.0],[1440.0,410.0],[1440.0,470.0],[1460.0,470.0]],"input":{"id":"alu_operand_a_mux","field":"out"}},{"type":"ALU","id":"alu","pos":[1480.0,500.0],"operator_i":{"id":"decoder","field":"decoder_alu_op"},"operand_a_i":{"id":"alu_operand_a_mux","field":"out"},"operand_b_i":{"id":"alu_operand_b_mux","field":"out"}},{"type":"Wire","id":"branch_jump_target","pos":[[1500.0,500.0],[1520.0,500.0],[1520.0,240.0],[1520.0,240.0],[320.0,240.0],[320.0,240.0],[320.0,700.0],[320.0,700.0],[360.0,700.0]],"input":{"id":"alu","field":"alu_result_o"}},{"type":"Wire","id":"w111111","pos":[[1500.0,500.0],[1500.0,500.0],[1520.0,500.0]],"input":{"id":"alu","field":"alu_result_o"}},{"type":"Wire","id":"data_mem_addr","pos":[[1520.0,500.0],[1520.0,820.0],[1540.0,820.0]],"input":{"id":"alu","field":"alu_result_o"}},{"type":"Wire","id":"alu_result","pos":[[1500.0,500.0],[1820.0,500.0]],"input":{"id":"alu","field":"alu_result_o"}},{"type":"Cross","id":"c5","pos":[1520.0,500.0],"input":{"id":"alu","field":"alu_result_o"}},{"type":"Wire","id":"reg_b","pos":[[1500.0,740.0],[1690.0,740.0],[1690.0,850.0]],"input":{"id":"reg_file","field":"reg_b"}},{"type":"Cross","id":"c1","pos":[1220.0,450.0],"input":{"id":"reg_file","field":"reg_a"}},{"type":"Cross","id":"p11","pos":[1510.0,740.0],"input":{"id":"reg_file","field":"reg_b"}},{"type":"BranchLogic","width":60.0,"height":60.0,"id":"branch_logic","pos":[1260.0,615.0],"rs1":{"id":"reg_file","field":"reg_a"},"rs2":{"id":"reg_file","field":"reg_b"},"ctrl":{"id":"decoder","field":"decoder_branch_op"},"enable":{"id":"decoder","field":"decoder_branch_instr"}},{"type":"Wire","id":"reg_a","pos":[[1220.0,450.0],[1220.0,600.0],[1230.0,600.0]],"input":{"id":"reg_file","field":"reg_a"}},{"type":"Wire","id":"rs2_data","pos":[[1205.0,780.0],[1380.0,780.0]],"input":{"id":"reg_file","field":"reg_b"}},{"type":"Mux","id":"csr_mux","pos":[1490.0,700.0],"select":{"id":"decoder","field":"csr_data_mux"},"m_in":[{"id":"reg_file","field":"reg_a"},{"id":"decoder","field":"decoder_zimm"}]},{"type":"Wire","id":"csr_data","pos":[[1500.0,700.0],[1700.0,700.0],[1700.0,850.0]],"input":{"id":"csr_mux","field":"out"}},{"type":"Wire","id":"reg_b_data","pos":[[1220.0,780.0],[1220.0,740.0],[1510.0,740.0],[1510.0,850.0]],"input":{"id":"reg_file","field":"reg_b"}},{"type":"Wire","id":"reg_a_data","pos":[[1300.0,450.0],[1300.0,690.0],[1470.0,690.0]],"input":{"id":"reg_file","field":"reg_a"}},{"type":"Wire","id":"reg_a_data_o","pos":[[1205.0,450.0],[1380.0,450.0]],"input":{"id":"reg_file","field":"reg_a"}},{"type":"Wire","id":"w1111111111","pos":[[1220.0,740.0],[1220.0,630.0],[1230.0,630.0]],"input":{"id":"reg_file","field":"reg_b"}},{"type":"Wire","id":"decoder_auipc_lui_imm_to_b","pos":[[815.0,860.0],[1380.0,860.0]],"input":{"id":"decoder","field":"decoder_lui_auipc_imm"}},{"type":"Wire","id":"insn","pos":[[700.0,850.0],[700.0,640.0],[785.0,640.0]],"input":{"id":"instr_mem","field":"instruction"}},{"type":"Wire","id":"instr_addr","pos":[[520.0,780.0],[640.0,780.0],[640.0,850.0]],"input":{"id":"reg","field":"out"}},{"type":"Wire","id":"pc","pos":[[500.0,700.0],[540.0,700.0]],"input":{"id":"reg","field":"out"}},{"type":"Cross","id":"c2","pos":[520.0,780.0],"input":{"id":"reg","field":"out"}},{"type":"Add","id":"pc_adder","pos":[560.0,670.0],"a_in":{"id":"pc_adder_c","field":"out"},"b_in":{"id":"reg","field":"out"}},{"type":"Wire","id":"pc_p4","pos":[[580.0,670.0],[580.0,670.0],[610.0,670.0],[610.0,670.0],[610.0,1000.0],[610.0,1000.0],[1810.0,1000.0],[1810.0,1000.0],[1810.0,560.0],[1810.0,560.0],[1820.0,560.0]],"input":{"id":"pc_adder","field":"out"}},{"type":"Wire","id":"pc_p_4","pos":[[580.0,670.0],[600.0,670.0],[600.0,620.0],[340.0,620.0],[340.0,680.0],[360.0,680.0]],"input":{"id":"pc_adder","field":"out"}},{"type":"Mux","id":"pc_adder_mux","pos":[380.0,690.0],"select":{"id":"branch_logic","field":"out"},"m_in":[{"id":"pc_adder","field":"out"},{"id":"alu","field":"alu_result_o"}]},{"type":"Wire","id":"new_pc","pos":[[390.0,690.0],[430.0,690.0]],"input":{"id":"pc_adder_mux","field":"out"}},{"type":"Wire","id":"w111","pos":[[410.0,690.0],[410.0,1040.0],[1710.0,1040.0],[1710.0,950.0]],"input":{"id":"pc_adder_mux","field":"out"}},{"type":"Cross","id":"p1","pos":[410.0,690.0],"input":{"id":"pc_adder_mux","field":"out"}},{"type":"Cross","id":"c_pc_out","pos":[600.0,670.0],"input":{"id":"pc_adder","field":"out"}},{"type":"CLIC","id":"clic","pos":[1710.0,900.0],"width":100.0,"height":100.0,"data":{"id":"reg_file","field":"reg_b"},"addr":{"id":"alu","field":"alu_result_o"},"data_we":{"id":"decoder","field":"data_mem_ctrl"},"data_size":{"id":"decoder","field":"data_mem_size"},"csr_data":{"id":"csr_mux","field":"out"},"csr_addr":{"id":"decoder","field":"csr_addr"},"csr_ctl":{"id":"decoder","field":"csr_ctl"},"mret":{"id":"decoder","field":"mret"},"pc":{"id":"pc_adder","field":"out"},"pc_next":{"id":"pc_adder_mux","field":"out"},"history":[{"mmio_op":[[0,0],4132],"csr_op":[[833,0]],"queue_op":[]}]},{"type":"Wire","id":"w_mem_int_addr","pos":[[1680.0,850.0],[1680.0,750.0],[1530.0,750.0],[1530.0,800.0],[1540.0,800.0]],"input":{"id":"clic","field":"mem_int_addr"}},{"type":"Mux","id":"dm_addr_mux","pos":[1560.0,810.0],"select":{"id":"clic","field":"interrupt_inv"},"m_in":[{"id":"clic","field":"mem_int_addr"},{"id":"alu","field":"alu_result_o"}]},{"type":"GPIO","height":50.0,"width":250.0,"id":"gpio","pos":[1740.0,380.0],"data_i":{"id":"reg_file","field":"reg_b"},"size_i":{"id":"decoder","field":"data_mem_size"},"we_i":{"id":"decoder","field":"data_mem_ctrl"},"addr_i":{"id":"dm_addr_mux","field":"out"},"se_i":{"id":"decoder","field":"data_se"},"csr_d":{"id":"csr_mux","field":"out"},"csr_a":{"id":"decoder","field":"csr_addr"},"csr_ctl":{"id":"decoder","field":"csr_ctl"}},{"type":"LED","height":20.0,"width":20.0,"id":"led","pos":[1820.0,320.0],"input":{"id":"gpio","field":"pin_o2"}},{"type":"Wire","id":"w1111","pos":[[1570.0,810.0],[1580.0,810.0],[1580.0,850.0]],"input":{"id":"dm_addr_mux","field":"out"}},{"type":"RVMem","id":"data_memory","pos":[1550.0,900.0],"width":100.0,"height":100.0,"big_endian":false,"data":{"id":"reg_file","field":"reg_b"},"addr":{"id":"dm_addr_mux","field":"out"},"ctrl":{"id":"decoder","field":"data_mem_ctrl"},"sext":{"id":"decoder","field":"data_se"},"size":{"id":"decoder","field":"data_mem_size"},"interrupt":{"id":"clic","field":"rf_ra_we"},"range":{"start":1342177280,"end":1342185472},"history":[{"data":null,"addr":0,"size":0}]},{"type":"Wire","id":"isr_addr","pos":[[1590.0,820.0],[1610.0,820.0]],"input":{"id":"data_memory","field":"data_o"}},{"type":"Cross","id":"p","pos":[1590.0,820.0],"input":{"id":"data_memory","field":"data_o"}},{"type":"Wire","id":"mem_data_o","pos":[[1590.0,850.0],[1590.0,550.0],[1730.0,550.0]],"input":{"id":"data_memory","field":"data_o"}},{"type":"Wire","id":"new","pos":[[1610.0,800.0],[1600.0,800.0],[1600.0,760.0],[1670.0,760.0],[1670.0,850.0]],"input":{"id":"clic","field":"mepc_out"}},{"type":"Wire","id":"clic_mmio_d_o","pos":[[1710.0,850.0],[1710.0,570.0],[1730.0,570.0]],"input":{"id":"clic","field":"mmio_data_o"}},{"type":"Mux","id":"mmio_data_mux","pos":[1750.0,560.0],"select":{"id":"data_memory","field":"mmio_mux_ctl"},"m_in":[{"id":"data_memory","field":"data_o"},{"id":"clic","field":"mmio_data_o"}]},{"type":"Mux","id":"mepc_isr_mux","pos":[1630.0,810.0],"select":{"id":"clic","field":"isr_mepc_sel"},"m_in":[{"id":"clic","field":"mepc_out"},{"id":"data_memory","field":"data_o"}]},{"type":"Wire","id":"mepc_isr_addr","pos":[[1640.0,810.0],[1650.0,810.0],[1650.0,1030.0],[420.0,1030.0],[420.0,710.0],[430.0,710.0]],"input":{"id":"mepc_isr_mux","field":"out"}},{"type":"Wire","id":"clic_csr_data_o","pos":[[1730.0,850.0],[1730.0,700.0],[1800.0,700.0],[1800.0,540.0],[1820.0,540.0]],"input":{"id":"clic","field":"csr_data_o"}},{"type":"Wire","id":"clic_interrupt","pos":[[1760.0,870.0],[1870.0,870.0]],"input":{"id":"clic","field":"rf_ra_we"}},{"type":"Mux","id":"interrupt_mux","pos":[450.0,700.0],"select":{"id":"clic","field":"interrupt"},"m_in":[{"id":"pc_adder_mux","field":"out"},{"id":"mepc_isr_mux","field":"out"}]},{"type":"Mux","id":"wb_mux","pos":[1840.0,530.0],"select":{"id":"decoder","field":"decoder_wb_mux_sel"},"m_in":[{"id":"alu","field":"alu_result_o"},{"id":"mmio_data_mux","field":"out"},{"id":"clic","field":"csr_data_o"},{"id":"pc_adder","field":"out"}]},{"type":"Wire","id":"w","pos":[[1870.0,530.0],[1850.0,530.0]],"input":{"id":"wb_mux","field":"out"}},{"type":"Wire","id":"mem_wb_data","pos":[[1760.0,560.0],[1780.0,560.0],[1780.0,520.0],[1820.0,520.0]],"input":{"id":"mmio_data_mux","field":"out"}},{"type":"Wire","id":"pc_int_mux","pos":[[460.0,700.0],[480.0,700.0]],"input":{"id":"interrupt_mux","field":"out"}},{"type":"Wire","id":"w_stack_depth","pos":[[1750.0,850.0],[1750.0,810.0],[1870.0,810.0]],"input":{"id":"clic","field":"stack_depth_out"}},{"type":"Wire","id":"w1111111","pos":[[1890.0,1070.0],[1890.0,1070.0],[1950.0,1070.0],[1950.0,1070.0],[1950.0,260.0],[1950.0,260.0],[1030.0,260.0],[1017.5,260.0],[1017.5,440.0]],"input":{"id":"regfile_rd_reg","field":"out"}}]} \ No newline at end of file diff --git a/riscv/riscv.json b/riscv/riscv.json index 8f0df927..dd00f0dd 100644 --- a/riscv/riscv.json +++ b/riscv/riscv.json @@ -1 +1,1980 @@ -{"store":[{"type":"Register","id":"rf_ra_we_reg","pos":[1880.0,870.0],"r_in":{"id":"clic","field":"rf_ra_we"}},{"type":"Register","id":"stack_depth_reg","pos":[1880.0,810.0],"r_in":{"id":"clic","field":"stack_depth_out"}},{"type":"Register","id":"reg","pos":[490.0,700.0],"r_in":{"id":"interrupt_mux","field":"out"}},{"type":"Register","id":"regfile_we_reg","pos":[1880.0,1010.0],"r_in":{"id":"decoder","field":"decoder_wb_write_enable"}},{"type":"Register","id":"wb_reg","pos":[1880.0,530.0],"r_in":{"id":"wb_mux","field":"out"}},{"type":"Register","id":"regfile_rd_reg","pos":[1880.0,1070.0],"r_in":{"id":"decoder","field":"decoder_rd"}},{"type":"Constant","id":"zero_c","pos":[1350.0,430.0],"value":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}},{"type":"Wire","id":"w11111","pos":[[815.0,410.0],[1380.0,410.0]],"input":{"id":"zero_c","field":"out"}},{"type":"Wire","id":"auipc_lui_imm_op_a","pos":[[815.0,370.0],[1380.0,370.0]],"input":{"id":"zero_c","field":"out"}},{"type":"Wire","id":"stack_depth_to_rf","pos":[[1890.0,810.0],[1920.0,810.0],[1920.0,290.0],[1140.0,290.0],[1140.0,440.0]],"input":{"id":"stack_depth_reg","field":"out"}},{"type":"InstrMem","width":100.0,"height":100.0,"id":"instr_mem","pos":[670.0,900.0],"pc":{"id":"reg","field":"out"},"range":{"start":0,"end":8192},"le":true},{"type":"Decoder","width":30.0,"height":600.0,"id":"decoder","pos":[800.0,620.0],"instruction":{"id":"instr_mem","field":"instruction"}},{"type":"Wire","id":"insn","pos":[[700.0,850.0],[700.0,640.0],[785.0,640.0]],"input":{"id":"instr_mem","field":"instruction"}},{"type":"Wire","id":"curr_pc","pos":[[520.0,700.0],[520.0,1010.0],[1340.0,1010.0],[1340.0,880.0],[1380.0,880.0]],"input":{"id":"reg","field":"out"}},{"type":"Wire","id":"w11","pos":[[815.0,390.0],[1380.0,390.0]],"input":{"id":"zero_c","field":"out"}},{"type":"Wire","id":"ra_we_to_rf","pos":[[1890.0,1010.0],[1940.0,1010.0],[1940.0,270.0],[1060.0,270.0],[1060.0,440.0]],"input":{"id":"regfile_we_reg","field":"out"}},{"type":"Wire","id":"w1","pos":[[1890.0,530.0],[1910.0,530.0],[1910.0,300.0],[1180.0,300.0],[1180.0,440.0]],"input":{"id":"wb_reg","field":"out"}},{"type":"Constant","id":"pc_adder_c","pos":[520.0,640.0],"value":{"data":{"Data":4},"fmt":{"Hex":["_32",false]}}},{"type":"Wire","id":"decoder_zimm","pos":[[815.0,880.0],[1300.0,880.0],[1300.0,710.0],[1470.0,710.0]],"input":{"id":"decoder","field":"decoder_zimm"}},{"type":"Wire","id":"pc","pos":[[500.0,700.0],[540.0,700.0]],"input":{"id":"reg","field":"out"}},{"type":"Wire","id":"decoder_rs2","pos":[[815.0,685.0],[955.0,685.0]],"input":{"id":"decoder","field":"decoder_rs2"}},{"type":"RegFile","id":"reg_file","pos":[1080.0,615.0],"width":250.0,"height":350.0,"stack_depth":{"id":"stack_depth_reg","field":"out"},"clic_ra_we":{"id":"rf_ra_we_reg","field":"out"},"read_addr1":{"id":"decoder","field":"decoder_rs1"},"read_addr2":{"id":"decoder","field":"decoder_rs2"},"write_data":{"id":"wb_reg","field":"out"},"write_addr":{"id":"regfile_rd_reg","field":"out"},"write_enable":{"id":"regfile_we_reg","field":"out"},"history":[{"stack_depth":0,"read_addr1":0,"read_addr2":0,"write_addr2":null,"old_data":null,"old_ra":null}]},{"type":"Wire","id":"reg_a","pos":[[1220.0,450.0],[1220.0,600.0],[1230.0,600.0]],"input":{"id":"reg_file","field":"reg_a"}},{"type":"Wire","id":"reg_a_data","pos":[[1300.0,450.0],[1300.0,690.0],[1470.0,690.0]],"input":{"id":"reg_file","field":"reg_a"}},{"type":"Wire","id":"reg_b_data","pos":[[1220.0,780.0],[1220.0,740.0],[1510.0,740.0],[1510.0,850.0]],"input":{"id":"reg_file","field":"reg_b"}},{"type":"Cross","id":"c1","pos":[1220.0,450.0],"input":{"id":"reg_file","field":"reg_a"}},{"type":"Wire","id":"reg_a_data_o","pos":[[1205.0,450.0],[1380.0,450.0]],"input":{"id":"reg_file","field":"reg_a"}},{"type":"Mux","id":"alu_operand_b_mux","pos":[1400.0,830.0],"select":{"id":"decoder","field":"decoder_alu_b_mux_sel"},"m_in":[{"id":"reg_file","field":"reg_b"},{"id":"decoder","field":"decoder_store_offset_imm"},{"id":"decoder","field":"decoder_imm"},{"id":"decoder","field":"decoder_shamt"},{"id":"decoder","field":"decoder_lui_auipc_imm"},{"id":"reg","field":"out"}]},{"type":"Mux","id":"alu_operand_a_mux","pos":[1400.0,410.0],"select":{"id":"decoder","field":"decoder_alu_a_mux_sel"},"m_in":[{"id":"decoder","field":"decoder_lui_auipc_imm"},{"id":"decoder","field":"decoder_jal_imm"},{"id":"decoder","field":"decoder_branch_imm"},{"id":"zero_c","field":"out"},{"id":"reg_file","field":"reg_a"}]},{"type":"Wire","id":"alu_operand_a","pos":[[1410.0,410.0],[1440.0,410.0],[1440.0,470.0],[1460.0,470.0]],"input":{"id":"alu_operand_a_mux","field":"out"}},{"type":"Wire","id":"reg_b","pos":[[1500.0,740.0],[1690.0,740.0],[1690.0,850.0]],"input":{"id":"reg_file","field":"reg_b"}},{"type":"Wire","id":"w1111111111","pos":[[1220.0,740.0],[1220.0,630.0],[1230.0,630.0]],"input":{"id":"reg_file","field":"reg_b"}},{"type":"Wire","id":"decoder_imm","pos":[[815.0,820.0],[1380.0,820.0]],"input":{"id":"decoder","field":"decoder_imm"}},{"type":"BranchLogic","width":60.0,"height":60.0,"id":"branch_logic","pos":[1260.0,615.0],"rs1":{"id":"reg_file","field":"reg_a"},"rs2":{"id":"reg_file","field":"reg_b"},"ctrl":{"id":"decoder","field":"decoder_branch_op"},"enable":{"id":"decoder","field":"decoder_branch_instr"}},{"type":"Wire","id":"decoder_shamt","pos":[[815.0,840.0],[1380.0,840.0]],"input":{"id":"decoder","field":"decoder_shamt"}},{"type":"Wire","id":"decoder_rs1","pos":[[815.0,545.0],[955.0,545.0]],"input":{"id":"decoder","field":"decoder_rs1"}},{"type":"Wire","id":"pc_c","pos":[[520.0,640.0],[540.0,640.0]],"input":{"id":"pc_adder_c","field":"out"}},{"type":"Wire","id":"blu_int_to_rf","pos":[[1890.0,870.0],[1930.0,870.0],[1930.0,280.0],[1100.0,280.0],[1100.0,440.0]],"input":{"id":"regfile_we_reg","field":"out"}},{"type":"Wire","id":"zero_c_data","pos":[[1360.0,430.0],[1380.0,430.0]],"input":{"id":"zero_c","field":"out"}},{"type":"Cross","id":"c2","pos":[520.0,780.0],"input":{"id":"reg","field":"out"}},{"type":"Cross","id":"p11","pos":[1510.0,740.0],"input":{"id":"reg_file","field":"reg_b"}},{"type":"Cross","id":"c0","pos":[1220.0,780.0],"input":{"id":"reg_file","field":"reg_b"}},{"type":"Wire","id":"alu_operand_b","pos":[[1410.0,830.0],[1440.0,830.0],[1440.0,530.0],[1460.0,530.0]],"input":{"id":"alu_operand_b_mux","field":"out"}},{"type":"Wire","id":"decoder_auipc_lui_imm_to_b","pos":[[815.0,860.0],[1380.0,860.0]],"input":{"id":"decoder","field":"decoder_lui_auipc_imm"}},{"type":"Wire","id":"rd_to_rf","pos":[[1890.0,1070.0],[1950.0,1070.0],[1950.0,260.0],[1020.0,260.0],[1020.0,440.0]],"input":{"id":"regfile_rd_reg","field":"out"}},{"type":"Wire","id":"decoder_rd","pos":[[815.0,910.0],[890.0,910.0],[890.0,1070.0],[1870.0,1070.0]],"input":{"id":"decoder","field":"decoder_rd"}},{"type":"Wire","id":"instr_addr","pos":[[520.0,780.0],[640.0,780.0],[640.0,850.0]],"input":{"id":"reg","field":"out"}},{"type":"Add","id":"pc_adder","pos":[560.0,670.0],"a_in":{"id":"pc_adder_c","field":"out"},"b_in":{"id":"reg","field":"out"}},{"type":"Wire","id":"pc_p4","pos":[[580.0,670.0],[600.0,670.0],[600.0,1000.0],[1810.0,1000.0],[1810.0,560.0],[1820.0,560.0]],"input":{"id":"pc_adder","field":"out"}},{"type":"Cross","id":"c_pc_out","pos":[600.0,670.0],"input":{"id":"pc_adder","field":"out"}},{"type":"Wire","id":"pc_p_4","pos":[[580.0,670.0],[600.0,670.0],[600.0,620.0],[340.0,620.0],[340.0,680.0],[360.0,680.0]],"input":{"id":"pc_adder","field":"out"}},{"type":"ALU","id":"alu","pos":[1480.0,500.0],"operator_i":{"id":"decoder","field":"decoder_alu_op"},"operand_a_i":{"id":"alu_operand_a_mux","field":"out"},"operand_b_i":{"id":"alu_operand_b_mux","field":"out"}},{"type":"Wire","id":"branch_jump_target","pos":[[1500.0,500.0],[1520.0,500.0],[1520.0,240.0],[1520.0,240.0],[320.0,240.0],[320.0,240.0],[320.0,700.0],[320.0,700.0],[360.0,700.0]],"input":{"id":"alu","field":"alu_result_o"}},{"type":"Mux","id":"pc_adder_mux","pos":[380.0,690.0],"select":{"id":"branch_logic","field":"out"},"m_in":[{"id":"pc_adder","field":"out"},{"id":"alu","field":"alu_result_o"}]},{"type":"Wire","id":"new_pc","pos":[[390.0,690.0],[430.0,690.0]],"input":{"id":"pc_adder_mux","field":"out"}},{"type":"Cross","id":"p1","pos":[410.0,690.0],"input":{"id":"pc_adder_mux","field":"out"}},{"type":"Wire","id":"alu_result","pos":[[1500.0,500.0],[1820.0,500.0]],"input":{"id":"alu","field":"alu_result_o"}},{"type":"Cross","id":"c5","pos":[1520.0,500.0],"input":{"id":"alu","field":"alu_result_o"}},{"type":"Wire","id":"data_mem_addr","pos":[[1520.0,500.0],[1520.0,820.0],[1540.0,820.0]],"input":{"id":"alu","field":"alu_result_o"}},{"type":"Wire","id":"rs2_data","pos":[[1205.0,780.0],[1380.0,780.0]],"input":{"id":"reg_file","field":"reg_b"}},{"type":"Wire","id":"we","pos":[[815.0,900.0],[900.0,900.0],[900.0,1060.0],[1850.0,1060.0],[1850.0,1010.0],[1870.0,1010.0]],"input":{"id":"decoder","field":"decoder_wb_write_enable"}},{"type":"Wire","id":"w111111","pos":[[1500.0,500.0],[1500.0,500.0],[1520.0,500.0]],"input":{"id":"alu","field":"alu_result_o"}},{"type":"Mux","id":"csr_mux","pos":[1490.0,700.0],"select":{"id":"decoder","field":"csr_data_mux"},"m_in":[{"id":"reg_file","field":"reg_a"},{"id":"decoder","field":"decoder_zimm"}]},{"type":"Wire","id":"csr_data","pos":[[1500.0,700.0],[1700.0,700.0],[1700.0,850.0]],"input":{"id":"csr_mux","field":"out"}},{"type":"CLIC","id":"clic","pos":[1710.0,900.0],"width":100.0,"height":100.0,"data":{"id":"reg_file","field":"reg_b"},"addr":{"id":"alu","field":"alu_result_o"},"data_we":{"id":"decoder","field":"data_mem_ctrl"},"data_size":{"id":"decoder","field":"data_mem_size"},"csr_data":{"id":"csr_mux","field":"out"},"csr_addr":{"id":"decoder","field":"csr_addr"},"csr_ctl":{"id":"decoder","field":"csr_ctl"},"mret":{"id":"decoder","field":"mret"},"pc":{"id":"pc_adder","field":"out"},"pc_next":{"id":"pc_adder_mux","field":"out"},"history":[{"mmio_op":[[0,0],4096],"csr_op":[[833,0]],"queue_op":[]}]},{"type":"Wire","id":"clic_interrupt","pos":[[1760.0,870.0],[1870.0,870.0]],"input":{"id":"clic","field":"rf_ra_we"}},{"type":"Mux","id":"dm_addr_mux","pos":[1560.0,810.0],"select":{"id":"clic","field":"interrupt_inv"},"m_in":[{"id":"clic","field":"mem_int_addr"},{"id":"alu","field":"alu_result_o"}]},{"type":"GPIO","height":50.0,"width":250.0,"id":"gpio","pos":[1740.0,380.0],"data_i":{"id":"reg_file","field":"reg_b"},"size_i":{"id":"decoder","field":"data_mem_size"},"we_i":{"id":"decoder","field":"data_mem_ctrl"},"addr_i":{"id":"dm_addr_mux","field":"out"},"se_i":{"id":"decoder","field":"data_se"},"csr_d":{"id":"csr_mux","field":"out"},"csr_a":{"id":"decoder","field":"csr_addr"},"csr_ctl":{"id":"decoder","field":"csr_ctl"}},{"type":"LED","height":20.0,"width":20.0,"id":"led","pos":[1820.0,320.0],"input":{"id":"gpio","field":"pin_o0"}},{"type":"Wire","id":"w1111","pos":[[1570.0,810.0],[1580.0,810.0],[1580.0,850.0]],"input":{"id":"dm_addr_mux","field":"out"}},{"type":"RVMem","id":"data_memory","pos":[1550.0,900.0],"width":100.0,"height":100.0,"big_endian":false,"data":{"id":"reg_file","field":"reg_b"},"addr":{"id":"dm_addr_mux","field":"out"},"ctrl":{"id":"decoder","field":"data_mem_ctrl"},"sext":{"id":"decoder","field":"data_se"},"size":{"id":"decoder","field":"data_mem_size"},"interrupt":{"id":"clic","field":"rf_ra_we"},"range":{"start":1342177280,"end":1342185472},"history":[{"data":null,"addr":0,"size":0}]},{"type":"Mux","id":"mmio_data_mux","pos":[1750.0,560.0],"select":{"id":"data_memory","field":"mmio_mux_ctl"},"m_in":[{"id":"data_memory","field":"data_o"},{"id":"clic","field":"mmio_data_o"}]},{"type":"Mux","id":"wb_mux","pos":[1840.0,530.0],"select":{"id":"decoder","field":"decoder_wb_mux_sel"},"m_in":[{"id":"alu","field":"alu_result_o"},{"id":"mmio_data_mux","field":"out"},{"id":"clic","field":"csr_data_o"},{"id":"pc_adder","field":"out"}]},{"type":"Wire","id":"w","pos":[[1870.0,530.0],[1850.0,530.0]],"input":{"id":"wb_mux","field":"out"}},{"type":"Wire","id":"mem_wb_data","pos":[[1760.0,560.0],[1780.0,560.0],[1780.0,520.0],[1820.0,520.0]],"input":{"id":"mmio_data_mux","field":"out"}},{"type":"Wire","id":"mem_data_o","pos":[[1590.0,850.0],[1590.0,550.0],[1730.0,550.0]],"input":{"id":"data_memory","field":"data_o"}},{"type":"Cross","id":"p","pos":[1590.0,820.0],"input":{"id":"data_memory","field":"data_o"}},{"type":"Wire","id":"clic_csr_data_o","pos":[[1730.0,850.0],[1730.0,700.0],[1800.0,700.0],[1800.0,540.0],[1820.0,540.0]],"input":{"id":"clic","field":"csr_data_o"}},{"type":"Wire","id":"w_mem_int_addr","pos":[[1680.0,850.0],[1680.0,750.0],[1530.0,750.0],[1530.0,800.0],[1540.0,800.0]],"input":{"id":"clic","field":"mem_int_addr"}},{"type":"Wire","id":"clic_mmio_d_o","pos":[[1710.0,850.0],[1710.0,570.0],[1730.0,570.0]],"input":{"id":"clic","field":"mmio_data_o"}},{"type":"Wire","id":"mepc_isr_addr","pos":[[1670.0,850.0],[1670.0,810.0],[1650.0,810.0],[1650.0,1030.0],[420.0,1030.0],[420.0,710.0],[430.0,710.0]],"input":{"id":"clic","field":"mepc_out"}},{"type":"Mux","id":"interrupt_mux","pos":[450.0,700.0],"select":{"id":"clic","field":"interrupt"},"m_in":[{"id":"pc_adder_mux","field":"out"},{"id":"clic","field":"mepc_out"}]},{"type":"Wire","id":"pc_int_mux","pos":[[460.0,700.0],[480.0,700.0]],"input":{"id":"interrupt_mux","field":"out"}},{"type":"Wire","id":"w111","pos":[[410.0,690.0],[410.0,1040.0],[1710.0,1040.0],[1710.0,950.0]],"input":{"id":"pc_adder_mux","field":"out"}},{"type":"Wire","id":"decoder_store_offset_imm","pos":[[815.0,800.0],[1380.0,800.0]],"input":{"id":"decoder","field":"decoder_store_offset_imm"}},{"type":"Wire","id":"w_stack_depth","pos":[[1750.0,850.0],[1750.0,810.0],[1870.0,810.0]],"input":{"id":"clic","field":"stack_depth_out"}}]} \ No newline at end of file +{ + "store": [ + { + "type": "Register", + "id": "rf_ra_we_reg", + "pos": [ + 1880.0, + 870.0 + ], + "r_in": { + "id": "clic", + "field": "rf_ra_we" + } + }, + { + "type": "Register", + "id": "stack_depth_reg", + "pos": [ + 1880.0, + 810.0 + ], + "r_in": { + "id": "clic", + "field": "stack_depth_out" + } + }, + { + "type": "Register", + "id": "reg", + "pos": [ + 490.0, + 700.0 + ], + "r_in": { + "id": "interrupt_mux", + "field": "mux_out" + } + }, + { + "type": "Register", + "id": "regfile_we_reg", + "pos": [ + 1880.0, + 1010.0 + ], + "r_in": { + "id": "decoder", + "field": "decoder_wb_write_enable" + } + }, + { + "type": "Register", + "id": "wb_reg", + "pos": [ + 1880.0, + 530.0 + ], + "r_in": { + "id": "wb_mux", + "field": "mux_out" + } + }, + { + "type": "Register", + "id": "regfile_rd_reg", + "pos": [ + 1880.0, + 1070.0 + ], + "r_in": { + "id": "decoder", + "field": "decoder_rd" + } + }, + { + "type": "Constant", + "id": "zero_c", + "pos": [ + 1350.0, + 430.0 + ], + "value": { + "data": { + "Data": 0 + }, + "fmt": { + "Hex": [ + "_32", + false + ] + } + } + }, + { + "type": "Wire", + "id": "w11111", + "pos": [ + [ + 815.0, + 410.0 + ], + [ + 1380.0, + 410.0 + ] + ], + "input": { + "id": "zero_c", + "field": "constant_out" + } + }, + { + "type": "Wire", + "id": "auipc_lui_imm_op_a", + "pos": [ + [ + 815.0, + 370.0 + ], + [ + 1380.0, + 370.0 + ] + ], + "input": { + "id": "zero_c", + "field": "constant_out" + } + }, + { + "type": "Wire", + "id": "stack_depth_to_rf", + "pos": [ + [ + 1890.0, + 810.0 + ], + [ + 1920.0, + 810.0 + ], + [ + 1920.0, + 290.0 + ], + [ + 1140.0, + 290.0 + ], + [ + 1140.0, + 440.0 + ] + ], + "input": { + "id": "stack_depth_reg", + "field": "register_out" + } + }, + { + "type": "InstrMem", + "width": 100.0, + "height": 100.0, + "id": "instr_mem", + "pos": [ + 670.0, + 900.0 + ], + "pc": { + "id": "reg", + "field": "register_out" + }, + "range": { + "start": 0, + "end": 8192 + }, + "le": true + }, + { + "type": "Decoder", + "width": 30.0, + "height": 600.0, + "id": "decoder", + "pos": [ + 800.0, + 620.0 + ], + "instruction": { + "id": "instr_mem", + "field": "instruction" + } + }, + { + "type": "Wire", + "id": "insn", + "pos": [ + [ + 700.0, + 850.0 + ], + [ + 700.0, + 640.0 + ], + [ + 785.0, + 640.0 + ] + ], + "input": { + "id": "instr_mem", + "field": "instruction" + } + }, + { + "type": "Wire", + "id": "curr_pc", + "pos": [ + [ + 520.0, + 700.0 + ], + [ + 520.0, + 1010.0 + ], + [ + 1340.0, + 1010.0 + ], + [ + 1340.0, + 880.0 + ], + [ + 1380.0, + 880.0 + ] + ], + "input": { + "id": "reg", + "field": "register_out" + } + }, + { + "type": "Wire", + "id": "w11", + "pos": [ + [ + 815.0, + 390.0 + ], + [ + 1380.0, + 390.0 + ] + ], + "input": { + "id": "zero_c", + "field": "constant_out" + } + }, + { + "type": "Wire", + "id": "ra_we_to_rf", + "pos": [ + [ + 1890.0, + 1010.0 + ], + [ + 1940.0, + 1010.0 + ], + [ + 1940.0, + 270.0 + ], + [ + 1060.0, + 270.0 + ], + [ + 1060.0, + 440.0 + ] + ], + "input": { + "id": "regfile_we_reg", + "field": "register_out" + } + }, + { + "type": "Wire", + "id": "w1", + "pos": [ + [ + 1890.0, + 530.0 + ], + [ + 1910.0, + 530.0 + ], + [ + 1910.0, + 300.0 + ], + [ + 1180.0, + 300.0 + ], + [ + 1180.0, + 440.0 + ] + ], + "input": { + "id": "wb_reg", + "field": "register_out" + } + }, + { + "type": "Constant", + "id": "pc_adder_c", + "pos": [ + 520.0, + 640.0 + ], + "value": { + "data": { + "Data": 4 + }, + "fmt": { + "Hex": [ + "_32", + false + ] + } + } + }, + { + "type": "Wire", + "id": "decoder_zimm", + "pos": [ + [ + 815.0, + 880.0 + ], + [ + 1300.0, + 880.0 + ], + [ + 1300.0, + 710.0 + ], + [ + 1470.0, + 710.0 + ] + ], + "input": { + "id": "decoder", + "field": "decoder_zimm" + } + }, + { + "type": "Wire", + "id": "pc", + "pos": [ + [ + 500.0, + 700.0 + ], + [ + 540.0, + 700.0 + ] + ], + "input": { + "id": "reg", + "field": "register_out" + } + }, + { + "type": "Wire", + "id": "decoder_rs2", + "pos": [ + [ + 815.0, + 685.0 + ], + [ + 955.0, + 685.0 + ] + ], + "input": { + "id": "decoder", + "field": "decoder_rs2" + } + }, + { + "type": "RegFile", + "id": "reg_file", + "pos": [ + 1080.0, + 615.0 + ], + "width": 250.0, + "height": 350.0, + "stack_depth": { + "id": "stack_depth_reg", + "field": "register_out" + }, + "clic_ra_we": { + "id": "rf_ra_we_reg", + "field": "register_out" + }, + "read_addr1": { + "id": "decoder", + "field": "decoder_rs1" + }, + "read_addr2": { + "id": "decoder", + "field": "decoder_rs2" + }, + "write_data": { + "id": "wb_reg", + "field": "register_out" + }, + "write_addr": { + "id": "regfile_rd_reg", + "field": "register_out" + }, + "write_enable": { + "id": "regfile_we_reg", + "field": "register_out" + }, + "history": [ + { + "stack_depth": 0, + "read_addr1": 0, + "read_addr2": 0, + "write_addr2": null, + "old_data": null, + "old_ra": null + } + ] + }, + { + "type": "Wire", + "id": "reg_a", + "pos": [ + [ + 1220.0, + 450.0 + ], + [ + 1220.0, + 600.0 + ], + [ + 1230.0, + 600.0 + ] + ], + "input": { + "id": "reg_file", + "field": "reg_a" + } + }, + { + "type": "Wire", + "id": "reg_a_data", + "pos": [ + [ + 1300.0, + 450.0 + ], + [ + 1300.0, + 690.0 + ], + [ + 1470.0, + 690.0 + ] + ], + "input": { + "id": "reg_file", + "field": "reg_a" + } + }, + { + "type": "Wire", + "id": "reg_b_data", + "pos": [ + [ + 1220.0, + 780.0 + ], + [ + 1220.0, + 740.0 + ], + [ + 1510.0, + 740.0 + ], + [ + 1510.0, + 850.0 + ] + ], + "input": { + "id": "reg_file", + "field": "reg_b" + } + }, + { + "type": "Cross", + "id": "c1", + "pos": [ + 1220.0, + 450.0 + ], + "input": { + "id": "reg_file", + "field": "reg_a" + } + }, + { + "type": "Wire", + "id": "reg_a_data_o", + "pos": [ + [ + 1205.0, + 450.0 + ], + [ + 1380.0, + 450.0 + ] + ], + "input": { + "id": "reg_file", + "field": "reg_a" + } + }, + { + "type": "Mux", + "id": "alu_operand_b_mux", + "pos": [ + 1400.0, + 830.0 + ], + "select": { + "id": "decoder", + "field": "decoder_alu_b_mux_sel" + }, + "scale": 1.0, + "m_in": [ + { + "id": "reg_file", + "field": "reg_b" + }, + { + "id": "decoder", + "field": "decoder_store_offset_imm" + }, + { + "id": "decoder", + "field": "decoder_imm" + }, + { + "id": "decoder", + "field": "decoder_shamt" + }, + { + "id": "decoder", + "field": "decoder_lui_auipc_imm" + }, + { + "id": "reg", + "field": "register_out" + } + ] + }, + { + "type": "Mux", + "id": "alu_operand_a_mux", + "pos": [ + 1400.0, + 410.0 + ], + "select": { + "id": "decoder", + "field": "decoder_alu_a_mux_sel" + }, + "scale": 1.0, + "m_in": [ + { + "id": "decoder", + "field": "decoder_lui_auipc_imm" + }, + { + "id": "decoder", + "field": "decoder_jal_imm" + }, + { + "id": "decoder", + "field": "decoder_branch_imm" + }, + { + "id": "zero_c", + "field": "constant_out" + }, + { + "id": "reg_file", + "field": "reg_a" + } + ] + }, + { + "type": "Wire", + "id": "alu_operand_a", + "pos": [ + [ + 1410.0, + 410.0 + ], + [ + 1440.0, + 410.0 + ], + [ + 1440.0, + 470.0 + ], + [ + 1460.0, + 470.0 + ] + ], + "input": { + "id": "alu_operand_a_mux", + "field": "mux_out" + } + }, + { + "type": "Wire", + "id": "reg_b", + "pos": [ + [ + 1500.0, + 740.0 + ], + [ + 1690.0, + 740.0 + ], + [ + 1690.0, + 850.0 + ] + ], + "input": { + "id": "reg_file", + "field": "reg_b" + } + }, + { + "type": "Wire", + "id": "w1111111111", + "pos": [ + [ + 1220.0, + 740.0 + ], + [ + 1220.0, + 630.0 + ], + [ + 1230.0, + 630.0 + ] + ], + "input": { + "id": "reg_file", + "field": "reg_b" + } + }, + { + "type": "Wire", + "id": "decoder_imm", + "pos": [ + [ + 815.0, + 820.0 + ], + [ + 1380.0, + 820.0 + ] + ], + "input": { + "id": "decoder", + "field": "decoder_imm" + } + }, + { + "type": "BranchLogic", + "width": 60.0, + "height": 60.0, + "id": "branch_logic", + "pos": [ + 1260.0, + 615.0 + ], + "rs1": { + "id": "reg_file", + "field": "reg_a" + }, + "rs2": { + "id": "reg_file", + "field": "reg_b" + }, + "ctrl": { + "id": "decoder", + "field": "decoder_branch_op" + }, + "enable": { + "id": "decoder", + "field": "decoder_branch_instr" + } + }, + { + "type": "Wire", + "id": "decoder_shamt", + "pos": [ + [ + 815.0, + 840.0 + ], + [ + 1380.0, + 840.0 + ] + ], + "input": { + "id": "decoder", + "field": "decoder_shamt" + } + }, + { + "type": "Wire", + "id": "decoder_rs1", + "pos": [ + [ + 815.0, + 545.0 + ], + [ + 955.0, + 545.0 + ] + ], + "input": { + "id": "decoder", + "field": "decoder_rs1" + } + }, + { + "type": "Wire", + "id": "pc_c", + "pos": [ + [ + 520.0, + 640.0 + ], + [ + 540.0, + 640.0 + ] + ], + "input": { + "id": "pc_adder_c", + "field": "constant_out" + } + }, + { + "type": "Wire", + "id": "blu_int_to_rf", + "pos": [ + [ + 1890.0, + 870.0 + ], + [ + 1930.0, + 870.0 + ], + [ + 1930.0, + 280.0 + ], + [ + 1100.0, + 280.0 + ], + [ + 1100.0, + 440.0 + ] + ], + "input": { + "id": "regfile_we_reg", + "field": "register_out" + } + }, + { + "type": "Wire", + "id": "zero_c_data", + "pos": [ + [ + 1360.0, + 430.0 + ], + [ + 1380.0, + 430.0 + ] + ], + "input": { + "id": "zero_c", + "field": "constant_out" + } + }, + { + "type": "Cross", + "id": "c2", + "pos": [ + 520.0, + 780.0 + ], + "input": { + "id": "reg", + "field": "register_out" + } + }, + { + "type": "Cross", + "id": "p11", + "pos": [ + 1510.0, + 740.0 + ], + "input": { + "id": "reg_file", + "field": "reg_b" + } + }, + { + "type": "Cross", + "id": "c0", + "pos": [ + 1220.0, + 780.0 + ], + "input": { + "id": "reg_file", + "field": "reg_b" + } + }, + { + "type": "Wire", + "id": "alu_operand_b", + "pos": [ + [ + 1410.0, + 830.0 + ], + [ + 1440.0, + 830.0 + ], + [ + 1440.0, + 530.0 + ], + [ + 1460.0, + 530.0 + ] + ], + "input": { + "id": "alu_operand_b_mux", + "field": "mux_out" + } + }, + { + "type": "Wire", + "id": "decoder_auipc_lui_imm_to_b", + "pos": [ + [ + 815.0, + 860.0 + ], + [ + 1380.0, + 860.0 + ] + ], + "input": { + "id": "decoder", + "field": "decoder_lui_auipc_imm" + } + }, + { + "type": "Wire", + "id": "rd_to_rf", + "pos": [ + [ + 1890.0, + 1070.0 + ], + [ + 1950.0, + 1070.0 + ], + [ + 1950.0, + 260.0 + ], + [ + 1020.0, + 260.0 + ], + [ + 1020.0, + 440.0 + ] + ], + "input": { + "id": "regfile_rd_reg", + "field": "register_out" + } + }, + { + "type": "Wire", + "id": "decoder_rd", + "pos": [ + [ + 815.0, + 910.0 + ], + [ + 890.0, + 910.0 + ], + [ + 890.0, + 1070.0 + ], + [ + 1870.0, + 1070.0 + ] + ], + "input": { + "id": "decoder", + "field": "decoder_rd" + } + }, + { + "type": "Wire", + "id": "instr_addr", + "pos": [ + [ + 520.0, + 780.0 + ], + [ + 640.0, + 780.0 + ], + [ + 640.0, + 850.0 + ] + ], + "input": { + "id": "reg", + "field": "register_out" + } + }, + { + "type": "Add", + "id": "pc_adder", + "pos": [ + 560.0, + 670.0 + ], + "scale": 1.0, + "a_in": { + "id": "pc_adder_c", + "field": "constant_out" + }, + "b_in": { + "id": "reg", + "field": "register_out" + } + }, + { + "type": "Wire", + "id": "pc_p4", + "pos": [ + [ + 580.0, + 670.0 + ], + [ + 600.0, + 670.0 + ], + [ + 600.0, + 1000.0 + ], + [ + 1810.0, + 1000.0 + ], + [ + 1810.0, + 560.0 + ], + [ + 1820.0, + 560.0 + ] + ], + "input": { + "id": "pc_adder", + "field": "add_out" + } + }, + { + "type": "Cross", + "id": "c_pc_out", + "pos": [ + 600.0, + 670.0 + ], + "input": { + "id": "pc_adder", + "field": "add_out" + } + }, + { + "type": "Wire", + "id": "pc_p_4", + "pos": [ + [ + 580.0, + 670.0 + ], + [ + 600.0, + 670.0 + ], + [ + 600.0, + 620.0 + ], + [ + 340.0, + 620.0 + ], + [ + 340.0, + 680.0 + ], + [ + 360.0, + 680.0 + ] + ], + "input": { + "id": "pc_adder", + "field": "add_out" + } + }, + { + "type": "ALU", + "id": "alu", + "pos": [ + 1480.0, + 500.0 + ], + "operator_i": { + "id": "decoder", + "field": "decoder_alu_op" + }, + "operand_a_i": { + "id": "alu_operand_a_mux", + "field": "mux_out" + }, + "operand_b_i": { + "id": "alu_operand_b_mux", + "field": "mux_out" + } + }, + { + "type": "Wire", + "id": "branch_jump_target", + "pos": [ + [ + 1500.0, + 500.0 + ], + [ + 1520.0, + 500.0 + ], + [ + 1520.0, + 240.0 + ], + [ + 1520.0, + 240.0 + ], + [ + 320.0, + 240.0 + ], + [ + 320.0, + 240.0 + ], + [ + 320.0, + 700.0 + ], + [ + 320.0, + 700.0 + ], + [ + 360.0, + 700.0 + ] + ], + "input": { + "id": "alu", + "field": "alu_result_o" + } + }, + { + "type": "Mux", + "id": "pc_adder_mux", + "pos": [ + 380.0, + 690.0 + ], + "select": { + "id": "branch_logic", + "field": "out" + }, + "scale": 1.0, + "m_in": [ + { + "id": "pc_adder", + "field": "add_out" + }, + { + "id": "alu", + "field": "alu_result_o" + } + ] + }, + { + "type": "Wire", + "id": "new_pc", + "pos": [ + [ + 390.0, + 690.0 + ], + [ + 430.0, + 690.0 + ] + ], + "input": { + "id": "pc_adder_mux", + "field": "mux_out" + } + }, + { + "type": "Cross", + "id": "p1", + "pos": [ + 410.0, + 690.0 + ], + "input": { + "id": "pc_adder_mux", + "field": "mux_out" + } + }, + { + "type": "Wire", + "id": "alu_result", + "pos": [ + [ + 1500.0, + 500.0 + ], + [ + 1820.0, + 500.0 + ] + ], + "input": { + "id": "alu", + "field": "alu_result_o" + } + }, + { + "type": "Cross", + "id": "c5", + "pos": [ + 1520.0, + 500.0 + ], + "input": { + "id": "alu", + "field": "alu_result_o" + } + }, + { + "type": "Wire", + "id": "data_mem_addr", + "pos": [ + [ + 1520.0, + 500.0 + ], + [ + 1520.0, + 820.0 + ], + [ + 1540.0, + 820.0 + ] + ], + "input": { + "id": "alu", + "field": "alu_result_o" + } + }, + { + "type": "Wire", + "id": "rs2_data", + "pos": [ + [ + 1205.0, + 780.0 + ], + [ + 1380.0, + 780.0 + ] + ], + "input": { + "id": "reg_file", + "field": "reg_b" + } + }, + { + "type": "Wire", + "id": "we", + "pos": [ + [ + 815.0, + 900.0 + ], + [ + 900.0, + 900.0 + ], + [ + 900.0, + 1060.0 + ], + [ + 1850.0, + 1060.0 + ], + [ + 1850.0, + 1010.0 + ], + [ + 1870.0, + 1010.0 + ] + ], + "input": { + "id": "decoder", + "field": "decoder_wb_write_enable" + } + }, + { + "type": "Wire", + "id": "w111111", + "pos": [ + [ + 1500.0, + 500.0 + ], + [ + 1500.0, + 500.0 + ], + [ + 1520.0, + 500.0 + ] + ], + "input": { + "id": "alu", + "field": "alu_result_o" + } + }, + { + "type": "Mux", + "id": "csr_mux", + "pos": [ + 1490.0, + 700.0 + ], + "select": { + "id": "decoder", + "field": "csr_data_mux" + }, + "scale": 1.0, + "m_in": [ + { + "id": "reg_file", + "field": "reg_a" + }, + { + "id": "decoder", + "field": "decoder_zimm" + } + ] + }, + { + "type": "Wire", + "id": "csr_data", + "pos": [ + [ + 1500.0, + 700.0 + ], + [ + 1700.0, + 700.0 + ], + [ + 1700.0, + 850.0 + ] + ], + "input": { + "id": "csr_mux", + "field": "mux_out" + } + }, + { + "type": "CLIC", + "id": "clic", + "pos": [ + 1710.0, + 900.0 + ], + "width": 100.0, + "height": 100.0, + "data": { + "id": "reg_file", + "field": "reg_b" + }, + "addr": { + "id": "alu", + "field": "alu_result_o" + }, + "data_we": { + "id": "decoder", + "field": "data_mem_ctrl" + }, + "data_size": { + "id": "decoder", + "field": "data_mem_size" + }, + "csr_data": { + "id": "csr_mux", + "field": "mux_out" + }, + "csr_addr": { + "id": "decoder", + "field": "csr_addr" + }, + "csr_ctl": { + "id": "decoder", + "field": "csr_ctl" + }, + "mret": { + "id": "decoder", + "field": "mret" + }, + "pc": { + "id": "pc_adder", + "field": "add_out" + }, + "pc_next": { + "id": "pc_adder_mux", + "field": "mux_out" + }, + "history": [ + { + "mmio_op": [ + [ + 0, + 0 + ], + 4096 + ], + "csr_op": [ + [ + 833, + 0 + ] + ], + "queue_op": [] + } + ] + }, + { + "type": "Wire", + "id": "clic_interrupt", + "pos": [ + [ + 1760.0, + 870.0 + ], + [ + 1870.0, + 870.0 + ] + ], + "input": { + "id": "clic", + "field": "rf_ra_we" + } + }, + { + "type": "Mux", + "id": "dm_addr_mux", + "pos": [ + 1560.0, + 810.0 + ], + "select": { + "id": "clic", + "field": "interrupt_inv" + }, + "scale": 1.0, + "m_in": [ + { + "id": "clic", + "field": "mem_int_addr" + }, + { + "id": "alu", + "field": "alu_result_o" + } + ] + }, + { + "type": "GPIO", + "height": 50.0, + "width": 250.0, + "id": "gpio", + "pos": [ + 1740.0, + 380.0 + ], + "data_i": { + "id": "reg_file", + "field": "reg_b" + }, + "size_i": { + "id": "decoder", + "field": "data_mem_size" + }, + "we_i": { + "id": "decoder", + "field": "data_mem_ctrl" + }, + "addr_i": { + "id": "dm_addr_mux", + "field": "mux_out" + }, + "se_i": { + "id": "decoder", + "field": "data_se" + }, + "csr_d": { + "id": "csr_mux", + "field": "mux_out" + }, + "csr_a": { + "id": "decoder", + "field": "csr_addr" + }, + "csr_ctl": { + "id": "decoder", + "field": "csr_ctl" + } + }, + { + "type": "LED", + "height": 20.0, + "width": 20.0, + "id": "led", + "pos": [ + 1820.0, + 320.0 + ], + "input": { + "id": "gpio", + "field": "pin_o0" + } + }, + { + "type": "Wire", + "id": "w1111", + "pos": [ + [ + 1570.0, + 810.0 + ], + [ + 1580.0, + 810.0 + ], + [ + 1580.0, + 850.0 + ] + ], + "input": { + "id": "dm_addr_mux", + "field": "mux_out" + } + }, + { + "type": "RVMem", + "id": "data_memory", + "pos": [ + 1550.0, + 900.0 + ], + "width": 100.0, + "height": 100.0, + "big_endian": false, + "data": { + "id": "reg_file", + "field": "reg_b" + }, + "addr": { + "id": "dm_addr_mux", + "field": "mux_out" + }, + "ctrl": { + "id": "decoder", + "field": "data_mem_ctrl" + }, + "sext": { + "id": "decoder", + "field": "data_se" + }, + "size": { + "id": "decoder", + "field": "data_mem_size" + }, + "interrupt": { + "id": "clic", + "field": "rf_ra_we" + }, + "range": { + "start": 1342177280, + "end": 1342185472 + }, + "history": [ + { + "data": null, + "addr": 0, + "size": 0 + } + ] + }, + { + "type": "Mux", + "id": "mmio_data_mux", + "pos": [ + 1750.0, + 560.0 + ], + "select": { + "id": "data_memory", + "field": "mmio_mux_ctl" + }, + "scale": 1.0, + "m_in": [ + { + "id": "data_memory", + "field": "data_o" + }, + { + "id": "clic", + "field": "mmio_data_o" + } + ] + }, + { + "type": "Mux", + "id": "wb_mux", + "pos": [ + 1840.0, + 530.0 + ], + "select": { + "id": "decoder", + "field": "decoder_wb_mux_sel" + }, + "scale": 1.0, + "m_in": [ + { + "id": "alu", + "field": "alu_result_o" + }, + { + "id": "mmio_data_mux", + "field": "mux_out" + }, + { + "id": "clic", + "field": "csr_data_o" + }, + { + "id": "pc_adder", + "field": "add_out" + } + ] + }, + { + "type": "Wire", + "id": "w", + "pos": [ + [ + 1870.0, + 530.0 + ], + [ + 1850.0, + 530.0 + ] + ], + "input": { + "id": "wb_mux", + "field": "out" + } + }, + { + "type": "Wire", + "id": "mem_wb_data", + "pos": [ + [ + 1760.0, + 560.0 + ], + [ + 1780.0, + 560.0 + ], + [ + 1780.0, + 520.0 + ], + [ + 1820.0, + 520.0 + ] + ], + "input": { + "id": "mmio_data_mux", + "field": "mux_out" + } + }, + { + "type": "Wire", + "id": "mem_data_o", + "pos": [ + [ + 1590.0, + 850.0 + ], + [ + 1590.0, + 550.0 + ], + [ + 1730.0, + 550.0 + ] + ], + "input": { + "id": "data_memory", + "field": "data_o" + } + }, + { + "type": "Cross", + "id": "p", + "pos": [ + 1590.0, + 820.0 + ], + "input": { + "id": "data_memory", + "field": "data_o" + } + }, + { + "type": "Wire", + "id": "clic_csr_data_o", + "pos": [ + [ + 1730.0, + 850.0 + ], + [ + 1730.0, + 700.0 + ], + [ + 1800.0, + 700.0 + ], + [ + 1800.0, + 540.0 + ], + [ + 1820.0, + 540.0 + ] + ], + "input": { + "id": "clic", + "field": "csr_data_o" + } + }, + { + "type": "Wire", + "id": "w_mem_int_addr", + "pos": [ + [ + 1680.0, + 850.0 + ], + [ + 1680.0, + 750.0 + ], + [ + 1530.0, + 750.0 + ], + [ + 1530.0, + 800.0 + ], + [ + 1540.0, + 800.0 + ] + ], + "input": { + "id": "clic", + "field": "mem_int_addr" + } + }, + { + "type": "Wire", + "id": "clic_mmio_d_o", + "pos": [ + [ + 1710.0, + 850.0 + ], + [ + 1710.0, + 570.0 + ], + [ + 1730.0, + 570.0 + ] + ], + "input": { + "id": "clic", + "field": "mmio_data_o" + } + }, + { + "type": "Wire", + "id": "mepc_isr_addr", + "pos": [ + [ + 1670.0, + 850.0 + ], + [ + 1670.0, + 810.0 + ], + [ + 1650.0, + 810.0 + ], + [ + 1650.0, + 1030.0 + ], + [ + 420.0, + 1030.0 + ], + [ + 420.0, + 710.0 + ], + [ + 430.0, + 710.0 + ] + ], + "input": { + "id": "clic", + "field": "mepc_out" + } + }, + { + "type": "Mux", + "id": "interrupt_mux", + "pos": [ + 450.0, + 700.0 + ], + "select": { + "id": "clic", + "field": "interrupt" + }, + "scale": 1.0, + "m_in": [ + { + "id": "pc_adder_mux", + "field": "mux_out" + }, + { + "id": "clic", + "field": "mepc_out" + } + ] + }, + { + "type": "Wire", + "id": "pc_int_mux", + "pos": [ + [ + 460.0, + 700.0 + ], + [ + 480.0, + 700.0 + ] + ], + "input": { + "id": "interrupt_mux", + "field": "mux_out" + } + }, + { + "type": "Wire", + "id": "w111", + "pos": [ + [ + 410.0, + 690.0 + ], + [ + 410.0, + 1040.0 + ], + [ + 1710.0, + 1040.0 + ], + [ + 1710.0, + 950.0 + ] + ], + "input": { + "id": "pc_adder_mux", + "field": "mux_out" + } + }, + { + "type": "Wire", + "id": "decoder_store_offset_imm", + "pos": [ + [ + 815.0, + 800.0 + ], + [ + 1380.0, + 800.0 + ] + ], + "input": { + "id": "decoder", + "field": "decoder_store_offset_imm" + } + }, + { + "type": "Wire", + "id": "w_stack_depth", + "pos": [ + [ + 1750.0, + 850.0 + ], + [ + 1750.0, + 810.0 + ], + [ + 1870.0, + 810.0 + ] + ], + "input": { + "id": "clic", + "field": "stack_depth_out" + } + } + ] +} diff --git a/riscv/src/gui_egui/components/instr_mem.rs b/riscv/src/gui_egui/components/instr_mem.rs index 14989232..4dfccfb5 100644 --- a/riscv/src/gui_egui/components/instr_mem.rs +++ b/riscv/src/gui_egui/components/instr_mem.rs @@ -44,98 +44,95 @@ impl InstrMem { }); }) .body(|body| { - body.rows( - 15.0, - (self.range.end - self.range.start) / 4, - |index, mut row| { - let address = index * 4 + self.range.start; - let pc: u32 = { - if simulator.as_ref().is_some() { - simulator - .as_ref() - .unwrap() - .get_input_value(&self.pc) - .try_into() - .unwrap_or(0) - } else { - 0 - } - }; - let (bg_color, fg_color) = { - if pc as usize == address { - (Color32::DARK_GRAY, Color32::WHITE) - } else { - (Color32::TRANSPARENT, Color32::LIGHT_GRAY) - } - }; - let breakpoint_color = { - if self.breakpoints.borrow_mut().contains(&address) { - Color32::RED - } else { - Color32::TRANSPARENT - } - }; - row.col(|ui| match &self.symbols.get(&address) { - Some(s) => { - ui.add(Label::new(format!("{}:", s)).truncate(true)); - } - None => {} - }); - //breakpoint - row.col(|ui| { - ui.label(RichText::new("•").color(breakpoint_color)); - }); - //address - row.col(|ui| { - ui.add(Label::new(format!("0x{:08x}", address)).truncate(true)); - }); - let mut bytes = [0u8; 4]; - if !self.le { - bytes[3] = *self.bytes.get(&address).unwrap(); - bytes[2] = *self.bytes.get(&(address + 1)).unwrap(); - bytes[1] = *self.bytes.get(&(address + 2)).unwrap(); - bytes[0] = *self.bytes.get(&(address + 3)).unwrap(); + body.rows(15.0, (self.range.end - self.range.start) / 4, |mut row| { + let index = row.index(); + let address = index * 4 + self.range.start; + let pc: u32 = { + if simulator.as_ref().is_some() { + simulator + .as_ref() + .unwrap() + .get_input_value(&self.pc) + .try_into() + .unwrap_or(0) + } else { + 0 + } + }; + let (bg_color, fg_color) = { + if pc as usize == address { + (Color32::DARK_GRAY, Color32::WHITE) + } else { + (Color32::TRANSPARENT, Color32::LIGHT_GRAY) + } + }; + let breakpoint_color = { + if self.breakpoints.borrow_mut().contains(&address) { + Color32::RED } else { - bytes[0] = *self.bytes.get(&address).unwrap(); - bytes[1] = *self.bytes.get(&(address + 1)).unwrap(); - bytes[2] = *self.bytes.get(&(address + 2)).unwrap(); - bytes[3] = *self.bytes.get(&(address + 3)).unwrap(); + Color32::TRANSPARENT + } + }; + row.col(|ui| match &self.symbols.get(&address) { + Some(s) => { + ui.add(Label::new(format!("{}:", s)).truncate()); } - let instr = ((bytes[3] as u32) << 24) - | ((bytes[2] as u32) << 16) - | ((bytes[1] as u32) << 8) - | (bytes[0] as u32); + None => {} + }); + //breakpoint + row.col(|ui| { + ui.label(RichText::new("•").color(breakpoint_color)); + }); + //address + row.col(|ui| { + ui.add(Label::new(format!("0x{:08x}", address)).truncate()); + }); + let mut bytes = [0u8; 4]; + if !self.le { + bytes[3] = *self.bytes.get(&address).unwrap(); + bytes[2] = *self.bytes.get(&(address + 1)).unwrap(); + bytes[1] = *self.bytes.get(&(address + 2)).unwrap(); + bytes[0] = *self.bytes.get(&(address + 3)).unwrap(); + } else { + bytes[0] = *self.bytes.get(&address).unwrap(); + bytes[1] = *self.bytes.get(&(address + 1)).unwrap(); + bytes[2] = *self.bytes.get(&(address + 2)).unwrap(); + bytes[3] = *self.bytes.get(&(address + 3)).unwrap(); + } + let instr = ((bytes[3] as u32) << 24) + | ((bytes[2] as u32) << 16) + | ((bytes[1] as u32) << 8) + | (bytes[0] as u32); - let instr_fmt = match asm_riscv::I::try_from(instr) { - Ok(i) => riscv_asm_strings::StringifyUpperHex::to_string(&i), - Err(_) => "Unknown instruction".to_string(), - }; - //hex instr - row.col(|ui| { - ui.add(Label::new(format!("0x{:08X}", instr)).truncate(true)); - }); - row.col(|ui| { - if ui - .add( - Label::new( - RichText::new(instr_fmt) - .color(fg_color) - .background_color(bg_color), - ) - .truncate(true) - .sense(Sense::click()), + let instr_fmt = match asm_riscv::I::try_from(instr) { + Ok(i) => riscv_asm_strings::StringifyUpperHex::to_string(&i), + Err(_) => "Unknown instruction".to_string(), + }; + //hex instr + row.col(|ui| { + ui.add(Label::new(format!("0x{:08X}", instr)).truncate()); + }); + row.col(|ui| { + if ui + .add( + Label::new( + RichText::new(instr_fmt) + .color(fg_color) + .background_color(bg_color), ) - .clicked() - { - trace!("clicked"); - if !self.breakpoints.borrow_mut().remove(&address) { - self.breakpoints.borrow_mut().insert(address); - } - }; - }); - row.col(|_| {}); - }, - ); + .truncate() + .sense(Sense::click()), + ) + .clicked() + { + trace!("clicked"); + if !self.breakpoints.borrow_mut().remove(&address) { + self.breakpoints.borrow_mut().insert(address); + } + }; + }); + row.col(|_| {}); + }); }); }); } diff --git a/riscv/src/gui_egui/components/probe_label.rs b/riscv/src/gui_egui/components/probe_label.rs index 57ce4a63..d2611edf 100644 --- a/riscv/src/gui_egui/components/probe_label.rs +++ b/riscv/src/gui_egui/components/probe_label.rs @@ -29,7 +29,7 @@ impl EguiComponent for ProbeLabel { Some(s) => s.get_input_value(&input), None => SignalValue::Uninitialized, }; - let area = Area::new(self.id.to_string()) + let area = Area::new(self.id.clone().into()) .order(Order::Middle) .current_pos(offset.to_pos2()) .movable(false) diff --git a/riscv/src/gui_egui/components/reg_file.rs b/riscv/src/gui_egui/components/reg_file.rs index 208eb3e1..81657c28 100644 --- a/riscv/src/gui_egui/components/reg_file.rs +++ b/riscv/src/gui_egui/components/reg_file.rs @@ -124,7 +124,8 @@ impl EguiComponent for RegFile { 15.0 * scale, RegStore::lo_range().end as usize - RegStore::lo_range().start as usize, - |index, mut row| { + |mut row| { + let index = row.index(); row.col(|ui| { ui.add(Label::new( RichText::new(format!( diff --git a/riscv/src/gui_egui/components/rv_mem.rs b/riscv/src/gui_egui/components/rv_mem.rs index e70e1226..a04eabf9 100644 --- a/riscv/src/gui_egui/components/rv_mem.rs +++ b/riscv/src/gui_egui/components/rv_mem.rs @@ -36,7 +36,8 @@ impl RVMem { body.rows( 15.0, ((self.range.end - self.range.start) / 4) as usize, - |index, mut row| { + |mut row| { + let index = row.index(); //println!("{}", index); let address = self.range.start as usize + index * 4; let memory = self.memory.0.borrow().clone(); @@ -68,10 +69,10 @@ impl RVMem { } } row.col(|ui| { - ui.add(Label::new(word).truncate(true)); + ui.add(Label::new(word).truncate()); }); row.col(|ui| { - ui.add(Label::new(ascii).truncate(true)); + ui.add(Label::new(ascii).truncate()); }); }, ); From 62c3164c5519c552ecb5bb121cfea7a0581f4938 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Mon, 9 Sep 2024 15:52:23 +0200 Subject: [PATCH 103/126] contued work on aligning wires --- mips-lib/src/components/mips_dm.rs | 1 - .../gui_egui/components/mips_control_unit.rs | 122 +++++++++++++++++- mips-lib/src/gui_egui/components/mips_dm.rs | 69 +++++++++- mips-lib/src/gui_egui/components/mips_im.rs | 42 ++++++ .../src/gui_egui/components/mips_reg_file.rs | 31 ++++- mips-lib/src/gui_egui/components/sz_extend.rs | 48 ++++++- src/fern.rs | 4 +- src/gui_egui/components/shift_left_const.rs | 42 +++++- src/gui_egui/components/wire.rs | 62 ++++----- src/gui_egui/components/zero_extend.rs | 42 +++++- 10 files changed, 407 insertions(+), 56 deletions(-) diff --git a/mips-lib/src/components/mips_dm.rs b/mips-lib/src/components/mips_dm.rs index 5181c45d..eafe1eec 100644 --- a/mips-lib/src/components/mips_dm.rs +++ b/mips-lib/src/components/mips_dm.rs @@ -9,7 +9,6 @@ use syncrim::common::EguiComponent; use syncrim::common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}; use crate::components::physical_mem::{MemOpSize, MemWriteReturn, MipsMem}; -use crate::components::RegFile; use super::PhysicalMem; diff --git a/mips-lib/src/gui_egui/components/mips_control_unit.rs b/mips-lib/src/gui_egui/components/mips_control_unit.rs index 1e128792..7f0183aa 100644 --- a/mips-lib/src/gui_egui/components/mips_control_unit.rs +++ b/mips-lib/src/gui_egui/components/mips_control_unit.rs @@ -1,10 +1,13 @@ -use crate::components::ControlUnit; -use egui::{Rect, Response, Ui, Vec2}; -use syncrim::common::{EguiComponent, Id, Ports, Simulator}; +use crate::components::{cntr_field, ControlUnit}; +use egui::{pos2, Pos2, Rect, Response, Ui, Vec2}; +use syncrim::common::{EguiComponent, Id, Input, Ports, Simulator}; use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use syncrim::gui_egui::gui::EguiExtra; use syncrim::gui_egui::helper::basic_component_gui; +const WIDTH: f32 = 400.0; +const HEIGHT: f32 = 15.0; + #[typetag::serde] impl EguiComponent for ControlUnit { fn render( @@ -18,11 +21,11 @@ impl EguiComponent for ControlUnit { _editor_mode: EditorMode, ) -> Option> { // size of the component - let width = 100f32 * scale; - let height: f32 = 12f32 * scale; + let w = WIDTH * scale; + let h: f32 = HEIGHT * scale; basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { - ui.set_height(height); - ui.set_width(width); + ui.set_height(h); + ui.set_width(w); ui.centered_and_justified(|ui| { ui.label("Control Unit"); }); @@ -67,4 +70,109 @@ impl EguiComponent for ControlUnit { fn top_padding(&self) -> f32 { 20f32 } + + fn ports_location(&self) -> Vec<(syncrim::common::Id, Pos2)> { + // width 50 + // height 200 + let own_pos = Vec2::new(self.pos.0, self.pos.1); + const M: f32 = 6.0; + fn out_pos(i: u32) -> Pos2 { + pos2( + -WIDTH / 2.0 + (i as f32 + 1.0) * WIDTH / 12.0, + HEIGHT / 2.0 + M, + ) + } + vec![ + ( + crate::components::cntr_field::INSTR_IN.to_string(), + Pos2::new(-WIDTH / 2.0 - M, 0.0) + own_pos, + ), + ( + crate::components::cntr_field::EXTEND_SELECT_OUT.to_string(), + out_pos(0) + own_pos, + ), + ( + crate::components::cntr_field::BRANCH_INTERRUPT_OUT.to_string(), + out_pos(1) + own_pos, + ), + ( + crate::components::cntr_field::REG_DEST_OUT.to_string(), + out_pos(2) + own_pos, + ), + ( + crate::components::cntr_field::ALU_SRC_A_OUT.to_string(), + out_pos(3) + own_pos, + ), + ( + crate::components::cntr_field::ALU_SRC_B_OUT.to_string(), + out_pos(4) + own_pos, + ), + ( + crate::components::cntr_field::MEM_WRITE_ENABLE_OUT.to_string(), + out_pos(5) + own_pos, + ), + ( + crate::components::cntr_field::MEM_MODE_OUT.to_string(), + out_pos(6) + own_pos, + ), + ( + crate::components::cntr_field::MMU_OUT.to_string(), + out_pos(7) + own_pos, + ), + ( + crate::components::cntr_field::ALU_OP_OUT.to_string(), + out_pos(8) + own_pos, + ), + ( + crate::components::cntr_field::REG_WRITE_SRC_OUT.to_string(), + out_pos(9) + own_pos, + ), + ( + crate::components::cntr_field::REG_WRITE_ENABLE_OUT.to_string(), + out_pos(10) + own_pos, + ), + ( + crate::components::cntr_field::CP0_OUT.to_string(), + out_pos(11) + own_pos, + ), + ] + } + + fn get_input_location(&self, id: Input) -> Option<(f32, f32)> { + let loc = self + .ports_location() + .iter() + .map(|(_, loc)| <(f32, f32)>::from(loc)) + .collect::>(); + + if id == self.a_in { + Some(loc[0]) + } else if id == Input::new(&self.id, cntr_field::EXTEND_SELECT_OUT) { + Some(loc[1]) + } else if id == Input::new(&self.id, cntr_field::BRANCH_INTERRUPT_OUT) { + Some(loc[2]) + } else if id == Input::new(&self.id, cntr_field::REG_DEST_OUT) { + Some(loc[3]) + } else if id == Input::new(&self.id, cntr_field::ALU_SRC_A_OUT) { + Some(loc[4]) + } else if id == Input::new(&self.id, cntr_field::ALU_SRC_B_OUT) { + Some(loc[5]) + } else if id == Input::new(&self.id, cntr_field::MEM_WRITE_ENABLE_OUT) { + Some(loc[6]) + } else if id == Input::new(&self.id, cntr_field::MEM_MODE_OUT) { + Some(loc[7]) + } else if id == Input::new(&self.id, cntr_field::MMU_OUT) { + Some(loc[8]) + } else if id == Input::new(&self.id, cntr_field::ALU_OP_OUT) { + Some(loc[9]) + } else if id == Input::new(&self.id, cntr_field::REG_WRITE_SRC_OUT) { + Some(loc[10]) + } else if id == Input::new(&self.id, cntr_field::REG_WRITE_ENABLE_OUT) { + Some(loc[11]) + } else if id == Input::new(&self.id, cntr_field::CP0_OUT) { + Some(loc[12]) + } else { + None + } + } } diff --git a/mips-lib/src/gui_egui/components/mips_dm.rs b/mips-lib/src/gui_egui/components/mips_dm.rs index 6939c19e..fb5f61ef 100644 --- a/mips-lib/src/gui_egui/components/mips_dm.rs +++ b/mips-lib/src/gui_egui/components/mips_dm.rs @@ -1,10 +1,13 @@ -use crate::components::{DataMem, PhysicalMem, RegFile}; -use egui::{Rect, Response, RichText, Ui, Vec2}; -use syncrim::common::{EguiComponent, Id, Ports, Simulator}; +use crate::components::{DataMem, PhysicalMem, RegFile, DATA_MEM_READ_DATA_OUT_ID}; +use egui::{pos2, Pos2, Rect, Response, RichText, Ui, Vec2}; +use syncrim::common::{EguiComponent, Id, Input, Ports, Simulator}; use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use syncrim::gui_egui::gui::EguiExtra; use syncrim::gui_egui::helper::basic_component_gui; +const WIDTH: f32 = 120.0; +const HEIGHT: f32 = 55.0; + #[typetag::serde] impl EguiComponent for DataMem { fn render( @@ -30,6 +33,8 @@ impl EguiComponent for DataMem { let mut mem_view_vis: bool = self.mem_view.borrow().visible; let r = basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.set_height(HEIGHT * scale); + ui.set_width(WIDTH * scale); // ui.centered_and_justified(|ui| { ui.label(RichText::new("Data memory").size(12f32 * scale)); ui.button( @@ -38,7 +43,6 @@ impl EguiComponent for DataMem { .strikethrough(), ) .on_hover_text("Use instruction memory to load a file"); - match mem_view_vis { false => { if ui.button("Show mem window").clicked() { @@ -128,4 +132,61 @@ impl EguiComponent for DataMem { fn top_padding(&self) -> f32 { 20f32 } + + fn ports_location(&self) -> Vec<(syncrim::common::Id, Pos2)> { + // width 50 + // height 200 + let own_pos = Vec2::new(self.pos.0, self.pos.1); + const M: f32 = 6.0; + fn out_pos(i: u32) -> Pos2 { + pos2( + -WIDTH / 2.0 + (i as f32 + 1.0) * WIDTH / 4.0, + -HEIGHT / 2.0 - M, + ) + } + vec![ + ( + crate::components::DATA_MEM_WD_IN_ID.to_string(), + pos2(-WIDTH / 2.0 - M, 0.0) + own_pos, + ), + ( + crate::components::DATA_MEM_A_IN_ID.to_string(), + out_pos(0) + own_pos, + ), + ( + crate::components::DATA_MEM_WRITE_ENABLE_ID.to_string(), + out_pos(1) + own_pos, + ), + ( + crate::components::DATA_MEM_OP_IN_ID.to_string(), + out_pos(2) + own_pos, + ), + ( + crate::components::DATA_MEM_READ_DATA_OUT_ID.to_string(), + pos2(WIDTH / 2.0 + M, 0.0) + own_pos, + ), + ] + } + + fn get_input_location(&self, id: Input) -> Option<(f32, f32)> { + let loc = self + .ports_location() + .iter() + .map(|(_, loc)| <(f32, f32)>::from(loc)) + .collect::>(); + + if id == self.data_input { + Some(loc[0]) + } else if id == self.address_input { + Some(loc[1]) + } else if id == self.write_enable_input { + Some(loc[2]) + } else if id == self.op_input { + Some(loc[3]) + } else if id == Input::new(&self.id, DATA_MEM_READ_DATA_OUT_ID) { + Some(loc[4]) + } else { + None + } + } } diff --git a/mips-lib/src/gui_egui/components/mips_im.rs b/mips-lib/src/gui_egui/components/mips_im.rs index d68b1604..12dd9313 100644 --- a/mips-lib/src/gui_egui/components/mips_im.rs +++ b/mips-lib/src/gui_egui/components/mips_im.rs @@ -7,13 +7,20 @@ use crate::components::InstrMem; use crate::components::MipsMem; use crate::components::PhysicalMem; use crate::components::RegFile; +use crate::components::INSTR_MEM_INSTRUCTION_ID; +use egui::pos2; +use egui::Pos2; // use crate::gui_egui::mips_mem_view_window::MemViewWindow; use egui::{Rect, Response, RichText, Ui, Vec2}; +use syncrim::common::Input; use syncrim::common::{EguiComponent, Id, Ports, Simulator}; use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use syncrim::gui_egui::gui::EguiExtra; use syncrim::gui_egui::helper::basic_component_gui; +const WIDTH: f32 = 120.0; +const HEIGHT: f32 = 55.0; + #[typetag::serde] impl EguiComponent for InstrMem { fn render( @@ -41,6 +48,8 @@ impl EguiComponent for InstrMem { let r = basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { // ui.centered_and_justified(|ui| { + ui.set_height(HEIGHT * scale); + ui.set_width(WIDTH * scale); ui.label(RichText::new("Instruction memory").size(12f32 * scale)); if ui.button("load file").clicked() { path_option = rfd::FileDialog::new().pick_file(); @@ -142,4 +151,37 @@ impl EguiComponent for InstrMem { fn top_padding(&self) -> f32 { 20f32 } + + fn ports_location(&self) -> Vec<(syncrim::common::Id, Pos2)> { + // width 50 + // height 200 + let own_pos = Vec2::new(self.pos.0, self.pos.1); + const M: f32 = 6.0; + vec![ + ( + crate::components::INSTR_MEM_PC_ID.to_string(), + pos2(-WIDTH / 3.0, -HEIGHT / 2.0 - M) + own_pos, + ), + ( + crate::components::DATA_MEM_A_IN_ID.to_string(), + pos2(WIDTH / 3.0, -HEIGHT / 2.0 - M) + own_pos, + ), + ] + } + + fn get_input_location(&self, id: Input) -> Option<(f32, f32)> { + let loc = self + .ports_location() + .iter() + .map(|(_, loc)| <(f32, f32)>::from(loc)) + .collect::>(); + + if id == self.pc { + Some(loc[0]) + } else if id == Input::new(&self.id, INSTR_MEM_INSTRUCTION_ID) { + Some(loc[1]) + } else { + None + } + } } diff --git a/mips-lib/src/gui_egui/components/mips_reg_file.rs b/mips-lib/src/gui_egui/components/mips_reg_file.rs index 276c5e25..2313561e 100644 --- a/mips-lib/src/gui_egui/components/mips_reg_file.rs +++ b/mips-lib/src/gui_egui/components/mips_reg_file.rs @@ -1,9 +1,10 @@ use crate::components::{reg_file_fields, RegFile, RegFormat}; use egui::{vec2, ComboBox, Pos2, Rect, Response, RichText, ScrollArea, Ui, Vec2}; -use syncrim::common::{EguiComponent, Input, Simulator}; -use syncrim::gui_egui::editor::EditorMode; +use syncrim::common::{EguiComponent, Input, Ports, Simulator}; +use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use syncrim::gui_egui::gui::EguiExtra; use syncrim::gui_egui::helper::basic_component_gui; +use syncrim::signal::Id; const REG_NAMES: [&str; 32] = [ "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", @@ -90,6 +91,32 @@ impl EguiComponent for RegFile { }); }) } + fn render_editor( + &mut self, + ui: &mut egui::Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: egui::Vec2, + scale: f32, + clip_rect: egui::Rect, + _id_ports: &[(Id, Ports)], + _grid: &GridOptions, + editor_mode: EditorMode, + ) -> EditorRenderReturn { + self.render( + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ); + EditorRenderReturn { + delete: false, + resp: None, + } + } fn get_input_location(&self, id: Input) -> Option<(f32, f32)> { // components size = (120,250) diff --git a/mips-lib/src/gui_egui/components/sz_extend.rs b/mips-lib/src/gui_egui/components/sz_extend.rs index fcb178ff..e404482d 100644 --- a/mips-lib/src/gui_egui/components/sz_extend.rs +++ b/mips-lib/src/gui_egui/components/sz_extend.rs @@ -1,10 +1,13 @@ -use crate::components::SignZeroExtend; -use egui::{Rect, Response, RichText, Ui, Vec2}; -use syncrim::common::{EguiComponent, Id, Ports, SignalValue, Simulator}; +use crate::components::{SignZeroExtend, SIGNZEROEXTEND_OUT_ID}; +use egui::{pos2, Pos2, Rect, Response, RichText, Ui, Vec2}; +use syncrim::common::{EguiComponent, Id, Input, Ports, SignalValue, Simulator}; use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use syncrim::gui_egui::gui::EguiExtra; use syncrim::gui_egui::helper::basic_component_gui; +const WIDTH: f32 = 105.0; +const HEIGHT: f32 = 30.0; + #[typetag::serde] impl EguiComponent for SignZeroExtend { fn render( @@ -18,6 +21,8 @@ impl EguiComponent for SignZeroExtend { _editor_mode: EditorMode, ) -> Option> { basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.set_height(HEIGHT * scale); + ui.set_width(WIDTH * scale); match &simulator { Some(sim) => { ui.label(match sim.get_input_value(&self.signzero_ctrl_in) { @@ -80,4 +85,41 @@ impl EguiComponent for SignZeroExtend { fn top_padding(&self) -> f32 { 20f32 } + + fn ports_location(&self) -> Vec<(syncrim::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + const M: f32 = 6.0; + vec![ + ( + crate::components::SIGNZEROEXTEND_SIGNAL_IN_ID.to_string(), + pos2(-WIDTH / 2.0 - M, 0.0) + own_pos, + ), + ( + crate::components::SIGNZEROEXTEND_CTRL_IN_ID.to_string(), + pos2(0.0, -HEIGHT / 2.0 - M) + own_pos, + ), + ( + crate::components::SIGNZEROEXTEND_OUT_ID.to_string(), + pos2(WIDTH / 2.0 + M, 0.0) + own_pos, + ), + ] + } + + fn get_input_location(&self, id: Input) -> Option<(f32, f32)> { + let loc = self + .ports_location() + .iter() + .map(|(_, loc)| <(f32, f32)>::from(loc)) + .collect::>(); + + if id == self.signzero_signal_in { + Some(loc[0]) + } else if id == self.signzero_ctrl_in { + Some(loc[1]) + } else if id == Input::new(&self.id, SIGNZEROEXTEND_OUT_ID) { + Some(loc[2]) + } else { + None + } + } } diff --git a/src/fern.rs b/src/fern.rs index 8b80fb23..4e837a02 100644 --- a/src/fern.rs +++ b/src/fern.rs @@ -15,8 +15,8 @@ pub fn fern_setup() { )) }) // Add blanket level filter - - // .level(log::LevelFilter::Debug); - .level(log::LevelFilter::Trace); + .level(log::LevelFilter::Debug); + // .level(log::LevelFilter::Trace); // .level(log::LevelFilter::Off); // - and per-module overrides diff --git a/src/gui_egui/components/shift_left_const.rs b/src/gui_egui/components/shift_left_const.rs index bd1c3a65..4acbdb4f 100644 --- a/src/gui_egui/components/shift_left_const.rs +++ b/src/gui_egui/components/shift_left_const.rs @@ -1,9 +1,12 @@ -use crate::common::{EguiComponent, Id, Ports, Simulator}; -use crate::components::ShiftConst; +use crate::common::{EguiComponent, Id, Input, Ports, Simulator}; +use crate::components::{ShiftConst, SHIFT_OUT_ID}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::basic_component_gui; -use egui::{Rect, Response, Ui, Vec2}; +use egui::{pos2, Pos2, Rect, Response, Ui, Vec2}; + +const HEIGHT: f32 = 14.0; +const WIDTH: f32 = 55.0; #[typetag::serde] impl EguiComponent for ShiftConst { @@ -18,6 +21,8 @@ impl EguiComponent for ShiftConst { _editor_mode: EditorMode, ) -> Option> { basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.set_height(HEIGHT * scale); + ui.set_width(WIDTH * scale); ui.label(format!("Shift << {}", self.shift_by)); }) } @@ -60,4 +65,35 @@ impl EguiComponent for ShiftConst { fn top_padding(&self) -> f32 { 20f32 } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + const M: f32 = 6.0; + vec![ + ( + crate::components::SHIFT_SIGNAL_IN_ID.to_string(), + pos2(-WIDTH / 2.0 - M, 0.0) + own_pos, + ), + ( + crate::components::SHIFT_OUT_ID.to_string(), + pos2(WIDTH / 2.0 + M, 0.0) + own_pos, + ), + ] + } + + fn get_input_location(&self, id: Input) -> Option<(f32, f32)> { + let loc = self + .ports_location() + .iter() + .map(|(_, loc)| <(f32, f32)>::from(loc)) + .collect::>(); + + if id == self.signal_in { + Some(loc[0]) + } else if id == Input::new(&self.id, SHIFT_OUT_ID) { + Some(loc[1]) + } else { + None + } + } } diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 9648f4bf..36f8e384 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -92,39 +92,39 @@ impl EguiComponent for Wire { for val in line_vec.windows(2) { let first_pos = val[0]; let last_pos = val[1]; - let rect = Rect::from_two_pos(first_pos, last_pos); + let rect = Rect::from_two_pos(first_pos, last_pos).expand(2.5); // why the fuck do i need this much code just to make sure its rendered at the correct layer - // let resp = ui - // .allocate_ui_at_rect(rect, |ui| { - // let mut layer = ui.layer_id(); - // layer.order = Order::Foreground; - // ui.with_layer_id(layer, |ui| { - // ui.allocate_exact_size( - // rect.size(), - // Sense { - // click: true, - // drag: true, - // focusable: true, - // }, - // ) - // }) - // }) - // .inner - // .inner - // .1; - // // log::debug!("{:?}", resp); - // if resp.contains_pointer() { - // ui.painter().rect_stroke( - // resp.interact_rect, - // Rounding::same(0.0), - // Stroke { - // width: scale, - // color: Color32::RED, - // }, - // ); - // } - // r.push(resp); + let resp = ui + .allocate_ui_at_rect(rect, |ui| { + let mut layer = ui.layer_id(); + layer.order = Order::Middle; + ui.with_layer_id(layer, |ui| { + ui.allocate_exact_size( + rect.size(), + Sense { + click: true, + drag: true, + focusable: true, + }, + ) + }) + }) + .inner + .inner + .1; + // log::debug!("{:?}", resp); + if resp.contains_pointer() { + ui.painter().rect_stroke( + resp.interact_rect, + Rounding::same(0.0), + Stroke { + width: scale, + color: Color32::RED, + }, + ); + } + r.push(resp); if let Some(cursor) = ui.ctx().pointer_latest_pos() { if min_from_line(first_pos.to_vec2(), last_pos.to_vec2(), cursor.to_vec2()) < TOOLTIP_DISTANCE diff --git a/src/gui_egui/components/zero_extend.rs b/src/gui_egui/components/zero_extend.rs index ff46b192..3d82f06f 100644 --- a/src/gui_egui/components/zero_extend.rs +++ b/src/gui_egui/components/zero_extend.rs @@ -1,9 +1,12 @@ -use crate::common::{EguiComponent, Id, Ports, Simulator}; -use crate::components::ZeroExtend; +use crate::common::{EguiComponent, Id, Input, Ports, Simulator}; +use crate::components::{ZeroExtend, ZEROEXTEND_OUT_ID}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::basic_component_gui; -use egui::{Rect, Response, Ui, Vec2}; +use egui::{pos2, Pos2, Rect, Response, Ui, Vec2}; + +const HEIGHT: f32 = 14.0; +const WIDTH: f32 = 70.0; #[typetag::serde] impl EguiComponent for ZeroExtend { @@ -18,6 +21,8 @@ impl EguiComponent for ZeroExtend { _editor_mode: EditorMode, ) -> Option> { basic_component_gui(self, &simulator, ui.ctx(), offset, scale, clip_rect, |ui| { + ui.set_height(HEIGHT * scale); + ui.set_width(WIDTH * scale); ui.label("Zero Extend"); }) } @@ -60,4 +65,35 @@ impl EguiComponent for ZeroExtend { fn top_padding(&self) -> f32 { 20f32 } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + const M: f32 = 6.0; + vec![ + ( + crate::components::ZEROEXTEND_SIGNAL_IN_ID.to_string(), + pos2(-WIDTH / 2.0 - M, 0.0) + own_pos, + ), + ( + crate::components::ZEROEXTEND_OUT_ID.to_string(), + pos2(WIDTH / 2.0 + M, 0.0) + own_pos, + ), + ] + } + + fn get_input_location(&self, id: Input) -> Option<(f32, f32)> { + let loc = self + .ports_location() + .iter() + .map(|(_, loc)| <(f32, f32)>::from(loc)) + .collect::>(); + + if id == self.signal_in { + Some(loc[0]) + } else if id == Input::new(&self.id, ZEROEXTEND_OUT_ID) { + Some(loc[1]) + } else { + None + } + } } From 1e5b1dc128213cf7f3dcf14e0125f0f9e5337591 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Mon, 9 Sep 2024 16:54:13 +0200 Subject: [PATCH 104/126] Wires stuff --- mips-lib/mips_simple.json | 1 + src/gui_egui/components/wire.rs | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 mips-lib/mips_simple.json diff --git a/mips-lib/mips_simple.json b/mips-lib/mips_simple.json new file mode 100644 index 00000000..b46ac187 --- /dev/null +++ b/mips-lib/mips_simple.json @@ -0,0 +1 @@ +{"store":[{"type":"PhysicalMem","id":"phys_mem","pos":[0.0,0.0],"mem":{"symbols":{},"sections":{},"data":{}}},{"type":"ProbeEdit","id":"rs_addr","pos":[60.0,100.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"ProbeEdit","id":"rt_addr","pos":[60.0,140.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"ProbeEdit","id":"write_addr","pos":[60.0,180.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"ProbeEdit","id":"write_data","pos":[60.0,220.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"ProbeEdit","id":"write_enable","pos":[60.0,260.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"Probe","id":"rs","pos":[300.0,120.0],"input":{"id":"reg_file","field":"rs_value_out"}},{"type":"Probe","id":"rt","pos":[60.0,400.0],"input":{"id":"reg_file","field":"rt_value_out"}},{"type":"ProbeEdit","id":"pc","pos":[60.0,500.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"InstrMem","id":"instr_mem","pos":[200.0,500.0],"pc":{"id":"pc","field":"out"},"phys_mem_id":"phys_mem","mem_view":{"visible":false,"title":"instruction memory view","id":"instr_mem","row_offset":0,"max_rows":1024,"big_endian":true,"format":"HexAndMips","show_settings":{"symbols":true,"sections":false,"program_counter":false,"registers":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true]},"reg_ref":{"id":"reg_file","pos":[200.0,200.0],"rs_address_in":{"id":"rs_addr","field":"out"},"rt_address_in":{"id":"rt_addr","field":"out"},"write_address_in":{"id":"write_addr","field":"out"},"write_data_in":{"id":"write_data","field":"out"},"write_enable_in":{"id":"write_enable","field":"out"}},"dynamic_symbols":{"PC_IM":[0,true]},"break_points":[]}},{"type":"ProbeEdit","id":"data_adrs","pos":[60.0,660.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"ProbeEdit","id":"data_write_enable","pos":[60.0,700.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"ProbeEdit","id":"data_mem_op","pos":[60.0,740.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"ProbeEdit","id":"data_write_data","pos":[60.0,780.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"DataMem","id":"data_mem","pos":[200.0,700.0],"address_input":{"id":"data_adrs","field":"out"},"data_input":{"id":"data_write_data","field":"out"},"op_input":{"id":"data_mem_op","field":"out"},"write_enable_input":{"id":"data_write_enable","field":"out"},"mem_view":{"visible":false,"title":"Data memory view","id":"data_mem","row_offset":0,"max_rows":1024,"big_endian":true,"format":"ByteAndUtf8","show_settings":{"symbols":true,"sections":false,"program_counter":false,"registers":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false]},"reg_ref":{"id":"reg_file","pos":[200.0,200.0],"rs_address_in":{"id":"rs_addr","field":"out"},"rt_address_in":{"id":"rt_addr","field":"out"},"write_address_in":{"id":"write_addr","field":"out"},"write_data_in":{"id":"write_data","field":"out"},"write_enable_in":{"id":"write_enable","field":"out"}},"dynamic_symbols":{},"break_points":[]}},{"type":"RegFile","id":"reg_file","pos":[200.0,200.0],"rs_address_in":{"id":"rs_addr","field":"out"},"rt_address_in":{"id":"rt_addr","field":"out"},"write_address_in":{"id":"write_addr","field":"out"},"write_data_in":{"id":"write_data","field":"out"},"write_enable_in":{"id":"write_enable","field":"out"}}]} \ No newline at end of file diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 36f8e384..e1141683 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -239,25 +239,32 @@ impl EguiComponent for Wire { ); let mut i = 0; + let mut to_insert: Option<(usize, (f32, f32))> = None; let mut first_item = true; self.pos.retain_mut(|seg_pos| { let mut delete = false; ui.horizontal(|ui| { ui.label(format!("Segment {}:", i)); ui.label("pos x"); - ui.add(DragValue::new(&mut seg_pos.0)); + ui.add(DragValue::new(&mut seg_pos.0).speed(0.5)); ui.label("pos y"); - ui.add(DragValue::new(&mut seg_pos.1)); + ui.add(DragValue::new(&mut seg_pos.1).speed(0.5)); if first_item { first_item = false; } else if ui.button("🗙").clicked() { delete = true; } + if ui.button("NEW").clicked() { + to_insert = Some((i, seg_pos.clone())); + } }); i += 1; !delete }); + if let Some((i, pos)) = to_insert { + self.pos.insert(i, pos) + }; if ui.button("+ Add new segment").clicked() { self.pos.push(*self.pos.last().unwrap()); From dd13b9d3de212c57dd8a48fc9afdfa0096665951 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Tue, 10 Sep 2024 19:49:27 +0200 Subject: [PATCH 105/126] added color to wire, pretty json --- mips-lib/mips_simple.json | 1 - mips-lib/mips_singel_cycle.json | 1 + src/component_store.rs | 2 +- src/components/wire.rs | 18 +++++++ src/gui_egui/components/wire.rs | 82 +++++++++++++++++++------------- src/gui_egui/editor_wire_mode.rs | 6 +-- src/gui_egui/helper.rs | 1 + 7 files changed, 72 insertions(+), 39 deletions(-) delete mode 100644 mips-lib/mips_simple.json create mode 100644 mips-lib/mips_singel_cycle.json diff --git a/mips-lib/mips_simple.json b/mips-lib/mips_simple.json deleted file mode 100644 index b46ac187..00000000 --- a/mips-lib/mips_simple.json +++ /dev/null @@ -1 +0,0 @@ -{"store":[{"type":"PhysicalMem","id":"phys_mem","pos":[0.0,0.0],"mem":{"symbols":{},"sections":{},"data":{}}},{"type":"ProbeEdit","id":"rs_addr","pos":[60.0,100.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"ProbeEdit","id":"rt_addr","pos":[60.0,140.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"ProbeEdit","id":"write_addr","pos":[60.0,180.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"ProbeEdit","id":"write_data","pos":[60.0,220.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"ProbeEdit","id":"write_enable","pos":[60.0,260.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"Probe","id":"rs","pos":[300.0,120.0],"input":{"id":"reg_file","field":"rs_value_out"}},{"type":"Probe","id":"rt","pos":[60.0,400.0],"input":{"id":"reg_file","field":"rt_value_out"}},{"type":"ProbeEdit","id":"pc","pos":[60.0,500.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"InstrMem","id":"instr_mem","pos":[200.0,500.0],"pc":{"id":"pc","field":"out"},"phys_mem_id":"phys_mem","mem_view":{"visible":false,"title":"instruction memory view","id":"instr_mem","row_offset":0,"max_rows":1024,"big_endian":true,"format":"HexAndMips","show_settings":{"symbols":true,"sections":false,"program_counter":false,"registers":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true]},"reg_ref":{"id":"reg_file","pos":[200.0,200.0],"rs_address_in":{"id":"rs_addr","field":"out"},"rt_address_in":{"id":"rt_addr","field":"out"},"write_address_in":{"id":"write_addr","field":"out"},"write_data_in":{"id":"write_data","field":"out"},"write_enable_in":{"id":"write_enable","field":"out"}},"dynamic_symbols":{"PC_IM":[0,true]},"break_points":[]}},{"type":"ProbeEdit","id":"data_adrs","pos":[60.0,660.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"ProbeEdit","id":"data_write_enable","pos":[60.0,700.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"ProbeEdit","id":"data_mem_op","pos":[60.0,740.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"ProbeEdit","id":"data_write_data","pos":[60.0,780.0],"edit_history":[{"text":"0","signal":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}}]},{"type":"DataMem","id":"data_mem","pos":[200.0,700.0],"address_input":{"id":"data_adrs","field":"out"},"data_input":{"id":"data_write_data","field":"out"},"op_input":{"id":"data_mem_op","field":"out"},"write_enable_input":{"id":"data_write_enable","field":"out"},"mem_view":{"visible":false,"title":"Data memory view","id":"data_mem","row_offset":0,"max_rows":1024,"big_endian":true,"format":"ByteAndUtf8","show_settings":{"symbols":true,"sections":false,"program_counter":false,"registers":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false]},"reg_ref":{"id":"reg_file","pos":[200.0,200.0],"rs_address_in":{"id":"rs_addr","field":"out"},"rt_address_in":{"id":"rt_addr","field":"out"},"write_address_in":{"id":"write_addr","field":"out"},"write_data_in":{"id":"write_data","field":"out"},"write_enable_in":{"id":"write_enable","field":"out"}},"dynamic_symbols":{},"break_points":[]}},{"type":"RegFile","id":"reg_file","pos":[200.0,200.0],"rs_address_in":{"id":"rs_addr","field":"out"},"rt_address_in":{"id":"rt_addr","field":"out"},"write_address_in":{"id":"write_addr","field":"out"},"write_data_in":{"id":"write_data","field":"out"},"write_enable_in":{"id":"write_enable","field":"out"}}]} \ No newline at end of file diff --git a/mips-lib/mips_singel_cycle.json b/mips-lib/mips_singel_cycle.json new file mode 100644 index 00000000..8f439013 --- /dev/null +++ b/mips-lib/mips_singel_cycle.json @@ -0,0 +1 @@ +{"store":[{"type":"Register","id":"pc","pos":[150.0,390.0],"r_in":{"id":"mux_jump_merge","field":"mux_out"}},{"type":"Register","id":"result_reg","pos":[850.0,225.0],"r_in":{"id":"mux_write_back","field":"mux_out"}},{"type":"Register","id":"reg_write_addr","pos":[850.0,525.0],"r_in":{"id":"mux_write_addr","field":"mux_out"}},{"type":"Register","id":"reg_we","pos":[850.0,50.0],"r_in":{"id":"control_unit","field":"reg_write_enable"}},{"type":"Constant","id":"0x_1F","pos":[350.0,550.0],"value":{"data":{"Data":31},"fmt":{"Hex":["_32",false]}}},{"type":"Wire","id":"from 0x_1F:constant_out to mux_write_addr:in2","pos":[[350.0,550.0],[388.0,537.0]],"input":{"id":"0x_1F","field":"constant_out"}},{"type":"Constant","id":"+4","pos":[150.0,440.0],"value":{"data":{"Data":4},"fmt":{"Hex":["_32",false]}}},{"type":"Wire","id":"from +4:constant_out to pc+4:a_in","pos":[[150.0,440.0],[188.0,412.0]],"input":{"id":"+4","field":"constant_out"}},{"type":"Add","id":"pc+4","pos":[200.0,400.0],"a_in":{"id":"+4","field":"constant_out"},"b_in":{"id":"pc","field":"register_out"},"scale":0.6},{"type":"Wire","id":"from pc+4:add_out to pc_add_branch:a_in","pos":[[225.0,436.5],[225.0,463.0],[388.0,463.0]],"input":{"id":"pc+4","field":"add_out"}},{"type":"PhysicalMem","id":"phys_mem","pos":[0.0,0.0]},{"type":"Wire","id":"from pc:register_out to pc+4:b_in","pos":[[176.0,390.0],[188.0,387.5]],"input":{"id":"pc","field":"register_out"}},{"type":"InstrMem","id":"instr_mem","pos":[250.0,575.0],"pc":{"id":"pc","field":"register_out"},"phys_mem_id":"phys_mem","regfile_id":"reg_file","mem_view":{"visible":false,"title":"instruction memory view","id":"instr_mem","row_offset":0,"max_rows":1024,"big_endian":true,"format":"HexAndMips","show_settings":{"symbols":true,"sections":false,"program_counter":false,"registers":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true]},"register_values":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2147483648,0,0],"dynamic_symbols":{"PC_IM":[0,true]},"break_points":[]}},{"type":"Wire","id":"from instr_mem:instruction to control_unit:control_unit_instr_in","pos":[[245.0,483.0],[245.0,50.0],[294.0,50.0]],"input":{"id":"instr_mem","field":"instruction"},"color_rgba":[0,0,0,20]},{"type":"JumpMerge","id":"jump_merge","pos":[125.0,475.0],"instr_addr_in":{"id":"pc","field":"register_out"},"jump_addr_in":{"id":"instr_mem","field":"instruction"}},{"type":"Wire","id":"from jump_merge:merge_out to mux_jump_merge:in2","pos":[[85.0,475.0],[67.0,475.0],[67.0,396.0],[88.0,396.0]],"input":{"id":"jump_merge","field":"merge_out"}},{"type":"Wire","id":"from pc+4:add_out to mux_jump_merge:in3","pos":[[212.0,400.0],[225.0,400.0],[225.0,437.0],[77.0,437.0],[77.0,408.0],[88.0,408.0]],"input":{"id":"pc+4","field":"add_out"}},{"type":"Wire","id":"from instr_mem:instruction to jump_merge:merge_jump_addr_in","pos":[[245.0,541.5],[245.0,483.0],[165.0,483.0]],"input":{"id":"instr_mem","field":"instruction"}},{"type":"ControlUnit","id":"control_unit","pos":[500.0,50.0],"a_in":{"id":"instr_mem","field":"instruction"}},{"type":"Wire","id":"from control_unit:reg_write_src to mux_write_back:select","pos":[[690.0,63.5],[690.0,115.0],[794.0,115.0],[794.0,207.0]],"input":{"id":"control_unit","field":"reg_write_src"},"color_rgba":[0,0,0,20]},{"type":"Wire","id":"from control_unit:reg_write_enable to reg_we:r_in","pos":[[706.0,50.0],[840.0,50.0]],"input":{"id":"control_unit","field":"reg_write_enable"},"color_rgba":[0,0,0,20]},{"type":"Wire","id":"from control_unit:mem_mode to data_mem:data_mem_op_in","pos":[[630.0,63.5],[630.0,541.5]],"input":{"id":"control_unit","field":"mem_mode"},"color_rgba":[0,0,0,20]},{"type":"Wire","id":"from control_unit:reg_dest to mux_write_addr:select","pos":[[400.0,63.5],[394.0,501.0]],"input":{"id":"control_unit","field":"reg_dest"}},{"type":"Wire","id":"from control_unit:mem_write_enable to data_mem:data_mem_write_enable","pos":[[600.0,63.5],[600.0,541.5]],"input":{"id":"control_unit","field":"mem_write_enable"},"color_rgba":[0,0,0,20]},{"type":"Wire","id":"from control_unit:alu_src_a to mux_source_a:select","pos":[[644.0,63.5],[644.0,171.0]],"input":{"id":"control_unit","field":"alu_src_a"},"color_rgba":[0,0,0,20]},{"type":"Wire","id":"from result_reg:register_out to reg_file:write_data_in","pos":[[860.0,225.0],[870.0,225.0],[870.0,373.0],[278.0,373.0],[278.0,335.0],[284.0,335.0]],"input":{"id":"result_reg","field":"register_out"}},{"type":"Wire","id":"from control_unit:extend_select to signzero_extend:signzero_ctrl_in","pos":[[333.3333,63.5],[325.0,404.0]],"input":{"id":"control_unit","field":"extend_select"},"color_rgba":[0,0,0,20]},{"type":"Wire","id":"from control_unit:alu_src_b to mux_source_b:select","pos":[[678.0,63.5],[678.0,212.0],[644.0,231.0]],"input":{"id":"control_unit","field":"alu_src_b"},"color_rgba":[0,0,0,20]},{"type":"InstrSplit","id":"instruction_split","pos":[200.0,225.0],"instruction_in":{"id":"instr_mem","field":"instruction"}},{"type":"Wire","id":"from instruction_split:rs_out to reg_file:rs_address_in","pos":[[231.0,213.88889],[261.0,213.88889],[261.0,85.0],[350.0,85.0],[350.0,94.0]],"input":{"id":"instruction_split","field":"rs_out"}},{"type":"ZeroExtend","id":"zero_extend_for_chamt","pos":[550.0,150.0],"signal_in":{"id":"instruction_split","field":"shamt_out"}},{"type":"Wire","id":"from zero_extend_for_chamt:zero_extend_out to mux_source_a:in0","pos":[[591.0,150.0],[638.0,183.0]],"input":{"id":"zero_extend_for_chamt","field":"zero_extend_out"}},{"type":"Mux","id":"mux_write_addr","pos":[400.0,525.0],"select":{"id":"control_unit","field":"reg_dest"},"m_in":[{"id":"instruction_split","field":"rt_out"},{"id":"instruction_split","field":"rd_out"},{"id":"0x_1F","field":"constant_out"}],"scale":0.6},{"type":"Wire","id":"from mux_write_addr:mux_out to reg_write_addr:r_in","pos":[[406.0,525.0],[840.0,525.0]],"input":{"id":"mux_write_addr","field":"mux_out"}},{"type":"Wire","id":"from instruction_split:rt_out to branch:branch_rt_in","pos":[[231.0,236.11111],[475.0,225.0]],"input":{"id":"instruction_split","field":"rt_out"}},{"type":"Wire","id":"from instruction_split:funct_out to branch:branch_funct_in","pos":[[231.0,191.66666],[475.0,225.0]],"input":{"id":"instruction_split","field":"funct_out"}},{"type":"Wire","id":"from instruction_split:rd_out to mux_write_addr:in1","pos":[[231.0,280.55554],[251.0,280.55554],[251.0,525.0],[388.0,525.0]],"input":{"id":"instruction_split","field":"rd_out"}},{"type":"Wire","id":"from instruction_split:rt_out to reg_file:rt_address_in","pos":[[231.0,236.11111],[350.0,356.0]],"input":{"id":"instruction_split","field":"rt_out"}},{"type":"Wire","id":"from instruction_split:rt_out to mux_write_addr:in0","pos":[[231.0,236.11111],[255.0,236.11111],[255.0,512.5],[388.0,513.0]],"input":{"id":"instruction_split","field":"rt_out"}},{"type":"Wire","id":"from instruction_split:op_out to branch:branch_op_in","pos":[[231.0,169.44444],[475.0,225.0]],"input":{"id":"instruction_split","field":"op_out"}},{"type":"Constant","id":"0_a_inp","pos":[610.0,220.0],"value":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}},{"type":"Wire","id":"from 0_a_inp:constant_out to mux_source_a:in2","pos":[[610.0,220.0],[638.0,207.0]],"input":{"id":"0_a_inp","field":"constant_out"}},{"type":"Wire","id":"from pc:register_out to jump_merge:merge_instr_addr_in","pos":[[175.5,471.0],[165.0,471.0]],"input":{"id":"pc","field":"register_out"}},{"type":"Wire","id":"from pc:register_out to instr_mem:pc","pos":[[160.0,390.0],[175.79999,390.0],[175.79999,520.0],[210.0,520.0],[210.0,541.5]],"input":{"id":"pc","field":"register_out"}},{"type":"Wire","id":"from control_unit:alu_op to alu:full_add_op_in","pos":[[660.0,63.5],[660.0,123.0],[710.0,123.0],[710.0,185.0]],"input":{"id":"control_unit","field":"alu_op"},"color_rgba":[0,0,0,20]},{"type":"SignZeroExtend","id":"signzero_extend","pos":[325.0,425.0],"signzero_signal_in":{"id":"instruction_split","field":"immediate_out"},"signzero_ctrl_in":{"id":"control_unit","field":"extend_select"}},{"type":"ShiftConst","id":"branch_shift","pos":[325.0,480.0],"signal_in":{"id":"signzero_extend","field":"sz_out"},"shift_by":2},{"type":"Add","id":"pc_add_branch","pos":[400.0,475.0],"a_in":{"id":"pc+4","field":"add_out"},"b_in":{"id":"branch_shift","field":"shift_left_const_out"},"scale":0.6},{"type":"Wire","id":"from signzero_extend:sz_out to mux_source_b:in2","pos":[[390.0,425.0],[541.0,425.0],[541.0,268.0],[638.0,267.0]],"input":{"id":"signzero_extend","field":"sz_out"}},{"type":"Wire","id":"from signzero_extend:sz_out to branch_shift:shift_in","pos":[[384.0,425.0],[390.0,425.0],[390.0,448.0],[280.5,448.0],[280.5,480.0],[291.5,480.0]],"input":{"id":"signzero_extend","field":"sz_out"}},{"type":"Wire","id":"from branch_shift:shift_left_const_out to pc_add_branch:b_in","pos":[[358.5,480.0],[388.0,487.0]],"input":{"id":"branch_shift","field":"shift_left_const_out"}},{"type":"Wire","id":"from instruction_split:immediate_out to signzero_extend:signzero_signal_in","pos":[[231.0,258.3333],[266.5,425.0]],"input":{"id":"instruction_split","field":"immediate_out"}},{"type":"Wire","id":"from reg_write_addr:register_out to reg_file:write_address_in","pos":[[860.0,525.0],[870.0,525.0],[870.0,390.0],[273.0,390.0],[273.0,315.0],[285.0,315.0]],"input":{"id":"reg_write_addr","field":"register_out"}},{"type":"Wire","id":"from pc+4:add_out to mux_source_b:in1","pos":[[225.0,400.0],[477.0,400.0],[477.0,256.0],[638.0,255.0]],"input":{"id":"pc+4","field":"add_out"}},{"type":"RegFile","id":"reg_file","pos":[350.0,225.0],"rs_address_in":{"id":"instruction_split","field":"rs_out"},"rt_address_in":{"id":"instruction_split","field":"rt_out"},"write_address_in":{"id":"reg_write_addr","field":"register_out"},"write_data_in":{"id":"result_reg","field":"register_out"},"write_enable_in":{"id":"reg_we","field":"register_out"}},{"type":"Wire","id":"from reg_file:rs_value_out to mux_jump_merge:in1","pos":[[416.0,265.0],[436.0,265.0],[436.0,362.0],[219.0,362.0],[219.0,347.0],[67.0,347.0],[67.0,384.0],[88.0,384.0]],"input":{"id":"reg_file","field":"rs_value_out"}},{"type":"Mux","id":"mux_source_a","pos":[650.0,195.0],"select":{"id":"control_unit","field":"alu_src_a"},"m_in":[{"id":"zero_extend_for_chamt","field":"zero_extend_out"},{"id":"reg_file","field":"rs_value_out"},{"id":"0_a_inp","field":"constant_out"}],"scale":0.6},{"type":"Wire","id":"from mux_source_a:mux_out to alu:full_add_a_in","pos":[[656.0,195.0],[700.0,195.0]],"input":{"id":"mux_source_a","field":"mux_out"}},{"type":"Mux","id":"mux_source_b","pos":[650.0,255.0],"select":{"id":"control_unit","field":"alu_src_b"},"m_in":[{"id":"reg_file","field":"rt_value_out"},{"id":"pc+4","field":"add_out"},{"id":"signzero_extend","field":"sz_out"}],"scale":0.6},{"type":"Wire","id":"from mux_source_b:mux_out to alu:full_add_b_in","pos":[[656.0,255.0],[700.0,255.0]],"input":{"id":"mux_source_b","field":"mux_out"}},{"type":"FullAdd","id":"alu","pos":[720.0,225.0],"a_in":{"id":"mux_source_a","field":"mux_out"},"b_in":{"id":"mux_source_b","field":"mux_out"},"op_in":{"id":"control_unit","field":"alu_op"}},{"type":"Wire","id":"from alu:alu_out to mux_write_back:in0","pos":[[750.0,225.0],[764.0,225.0],[764.0,219.0],[788.0,219.0]],"input":{"id":"alu","field":"alu_out"}},{"type":"Wire","id":"from alu:alu_out to data_mem:data_mem_address_in","pos":[[740.0,225.0],[750.0,225.0],[750.0,450.0],[570.0,450.0],[570.0,541.5]],"input":{"id":"alu","field":"alu_out"}},{"type":"Wire","id":"from reg_file:rt_value_out to data_mem:data_mem_write_data_in","pos":[[520.0,185.0],[520.0,575.0],[534.0,575.0]],"input":{"id":"reg_file","field":"rt_value_out"}},{"type":"Wire","id":"from reg_file:rs_value_out to mux_source_a:in1","pos":[[416.0,265.0],[638.0,195.0]],"input":{"id":"reg_file","field":"rs_value_out"}},{"type":"Wire","id":"from reg_file:rt_value_out to mux_source_b:in0","pos":[[416.0,185.0],[638.0,243.0]],"input":{"id":"reg_file","field":"rt_value_out"}},{"type":"BranchLogic","id":"branch","pos":[475.0,225.0],"op_in":{"id":"instruction_split","field":"op_out"},"rt_in":{"id":"instruction_split","field":"rt_out"},"funct_in":{"id":"instruction_split","field":"funct_out"},"rs_value":{"id":"reg_file","field":"rs_value_out"},"rt_value":{"id":"reg_file","field":"rt_value_out"}},{"type":"Mux","id":"mux_jump_merge","pos":[100.0,390.0],"select":{"id":"branch","field":"branch_out"},"m_in":[{"id":"pc_add_branch","field":"add_out"},{"id":"reg_file","field":"rs_value_out"},{"id":"jump_merge","field":"merge_out"},{"id":"pc+4","field":"add_out"}],"scale":0.6},{"type":"Wire","id":"from mux_jump_merge:mux_out to pc:r_in","pos":[[106.0,390.0],[140.0,390.0]],"input":{"id":"mux_jump_merge","field":"mux_out"}},{"type":"Wire","id":"from branch:branch_out to mux_jump_merge:select","pos":[[475.0,211.0],[475.0,90.0],[94.0,90.0],[94.0,360.0]],"input":{"id":"branch","field":"branch_out"},"color_rgba":[0,0,0,20]},{"type":"DataMem","id":"data_mem","pos":[600.0,575.0],"address_input":{"id":"alu","field":"alu_out"},"data_input":{"id":"reg_file","field":"rt_value_out"},"op_input":{"id":"control_unit","field":"mem_mode"},"write_enable_input":{"id":"control_unit","field":"mem_write_enable"},"phys_mem_id":"phys_mem","regfile_id":"reg_file","mem_view":{"visible":false,"title":"Data memory view","id":"data_mem","row_offset":0,"max_rows":1024,"big_endian":true,"format":"ByteAndUtf8","show_settings":{"symbols":true,"sections":false,"program_counter":false,"registers":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false]},"register_values":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2147483648,0,0],"dynamic_symbols":{"DM_ADRS":[0,false]},"break_points":[]}},{"type":"Wire","id":"from data_mem:data_out to mux_write_back:in1","pos":[[666.0,575.0],[775.0,575.0],[775.0,231.0],[788.0,231.0]],"input":{"id":"data_mem","field":"data_out"}},{"type":"Mux","id":"mux_write_back","pos":[800.0,225.0],"select":{"id":"control_unit","field":"reg_write_src"},"m_in":[{"id":"alu","field":"alu_out"},{"id":"data_mem","field":"data_out"}],"scale":0.6},{"type":"Wire","id":"from mux_write_back:mux_out to result_reg:r_in","pos":[[806.0,225.0],[840.0,225.0]],"input":{"id":"mux_write_back","field":"mux_out"}},{"type":"Wire","id":"from reg_file:rs_value_out to branch:branch_rs_value_id","pos":[[416.0,265.0],[475.0,225.0]],"input":{"id":"reg_file","field":"rs_value_out"}},{"type":"Wire","id":"from reg_file:rt_value_out to branch:branch_rt_value_id","pos":[[416.0,185.0],[475.0,225.0]],"input":{"id":"reg_file","field":"rt_value_out"}},{"type":"Wire","id":"from reg_we:register_out to reg_file:write_enable_in","pos":[[860.0,50.0],[870.0,50.0],[870.0,85.0],[370.0,85.0],[370.0,94.0]],"input":{"id":"reg_we","field":"register_out"},"color_rgba":[0,0,0,20]},{"type":"Wire","id":"from instr_mem:instruction to instruction_split:instruction_in","pos":[[245.0,343.5],[200.0,343.5],[200.0,330.5]],"input":{"id":"instr_mem","field":"instruction"}},{"type":"Wire","id":"from pc_add_branch:add_out to mux_jump_merge:in0","pos":[[412.0,475.0],[422.5,475.0],[422.5,365.0],[213.0,365.0],[213.0,356.0],[75.0,356.0],[75.0,372.0],[88.0,372.0]],"input":{"id":"pc_add_branch","field":"add_out"}},{"type":"Wire","id":"from instruction_split:shamt_out to zero_extend_for_chamt:signal_in","pos":[[231.0,147.22223],[509.0,150.0]],"input":{"id":"instruction_split","field":"shamt_out"}}]} \ No newline at end of file diff --git a/src/component_store.rs b/src/component_store.rs index 31aa1518..a34a9291 100644 --- a/src/component_store.rs +++ b/src/component_store.rs @@ -18,7 +18,7 @@ impl ComponentStore { } pub fn save_file(&self, path: &PathBuf) { - let json = serde_json::to_string(self).unwrap(); + let json = serde_json::to_string_pretty(self).unwrap(); trace!("json: {}", json); trace!("path {:?}", path); let mut file = File::create(path).unwrap(); diff --git a/src/components/wire.rs b/src/components/wire.rs index e0057807..b4a048a9 100644 --- a/src/components/wire.rs +++ b/src/components/wire.rs @@ -11,6 +11,15 @@ pub struct Wire { pub(crate) id: Id, pub(crate) pos: Vec<(f32, f32)>, pub(crate) input: Input, + // this is colour32, using [u8;4] instead of color + // because we are not sure if egui feature is present + // if this field does not exist in wire call basic color to generate it + // skip serializing color if color matches basic color + #[serde( + default = "Wire::basic_color", + skip_serializing_if = "Wire::is_color_basic" + )] + pub(crate) color_rgba: [u8; 4], } #[typetag::serde] @@ -46,10 +55,19 @@ impl Wire { id: id.to_string(), pos, input, + color_rgba: Wire::basic_color(), } } pub fn rc_new(id: &str, pos: Vec<(f32, f32)>, input: Input) -> Rc { Rc::new(Wire::new(id, pos, input)) } + + pub const fn basic_color() -> [u8; 4] { + [0x00, 0x00, 0x00, 0xff] + } + + pub fn is_color_basic(x: &[u8; 4]) -> bool { + &Wire::basic_color() == x + } } diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index e1141683..abc354b2 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -84,7 +84,12 @@ impl EguiComponent for Wire { line_vec.clone(), Stroke { width: scale, - color: Color32::BLACK, + color: Color32::from_rgba_unmultiplied( + self.color_rgba[0], + self.color_rgba[1], + self.color_rgba[2], + self.color_rgba[3], + ), }, )); let mut r: Vec = vec![]; @@ -93,38 +98,43 @@ impl EguiComponent for Wire { let first_pos = val[0]; let last_pos = val[1]; let rect = Rect::from_two_pos(first_pos, last_pos).expand(2.5); - - // why the fuck do i need this much code just to make sure its rendered at the correct layer - let resp = ui - .allocate_ui_at_rect(rect, |ui| { - let mut layer = ui.layer_id(); - layer.order = Order::Middle; - ui.with_layer_id(layer, |ui| { - ui.allocate_exact_size( - rect.size(), - Sense { - click: true, - drag: true, - focusable: true, + match editor_mode { + EditorMode::Default => { + // why the fuck do i need this much code just to make sure its rendered at the correct layer + let resp = ui + .allocate_ui_at_rect(rect, |ui| { + let mut layer = ui.layer_id(); + layer.order = Order::Middle; + ui.with_layer_id(layer, |ui| { + ui.allocate_exact_size( + rect.size(), + Sense { + click: true, + drag: true, + focusable: true, + }, + ) + }) + }) + .inner + .inner + .1; + // log::debug!("{:?}", resp); + if resp.contains_pointer() { + ui.painter().rect_stroke( + resp.interact_rect, + Rounding::same(0.0), + Stroke { + width: scale, + color: Color32::RED, }, - ) - }) - }) - .inner - .inner - .1; - // log::debug!("{:?}", resp); - if resp.contains_pointer() { - ui.painter().rect_stroke( - resp.interact_rect, - Rounding::same(0.0), - Stroke { - width: scale, - color: Color32::RED, - }, - ); - } - r.push(resp); + ); + } + r.push(resp); + } + _ => {} + }; + if let Some(cursor) = ui.ctx().pointer_latest_pos() { if min_from_line(first_pos.to_vec2(), last_pos.to_vec2(), cursor.to_vec2()) < TOOLTIP_DISTANCE @@ -237,6 +247,14 @@ impl EguiComponent for Wire { id_ports, self.id.clone(), ); + let mut c: Color32 = Color32::from_rgba_unmultiplied( + self.color_rgba[0], + self.color_rgba[1], + self.color_rgba[2], + self.color_rgba[3], + ); + ui.color_edit_button_srgba(&mut c); + self.color_rgba = c.to_array(); let mut i = 0; let mut to_insert: Option<(usize, (f32, f32))> = None; diff --git a/src/gui_egui/editor_wire_mode.rs b/src/gui_egui/editor_wire_mode.rs index 70b79559..6cb58810 100644 --- a/src/gui_egui/editor_wire_mode.rs +++ b/src/gui_egui/editor_wire_mode.rs @@ -101,11 +101,7 @@ pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { #[allow(ambiguous_wide_pointer_comparisons)] if !Rc::ptr_eq(&in_c.comp, &out_c.comp) { let comp = if is_input_in_comp_start { out_c } else { in_c }; - e.components.push(Rc::new(Wire { - id: id.to_string(), - pos: pos_v, - input: i.clone(), - })); + e.components.push(Rc::new(Wire::new(id, pos_v, i.clone()))); e.contexts.insert( id.to_string(), EguiExtra { diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index 8b82dcdf..d4fba37b 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -268,6 +268,7 @@ pub fn basic_on_hover( component: &dyn EguiComponent, simulator: &Option<&mut Simulator>, ) { + ui.set_max_width(200.0); ui.label(format!("id: {}", component.get_id_ports().0)); if let Some(sim) = simulator { ui.separator(); From 622e72b951fc518226dcbedeacd64fb356169bdf Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 11 Sep 2024 16:01:02 +0200 Subject: [PATCH 106/126] nice wires --- mips-lib/mips_singel_cycle.json | 1956 ++++++++++++++++++++++++++++++- 1 file changed, 1955 insertions(+), 1 deletion(-) diff --git a/mips-lib/mips_singel_cycle.json b/mips-lib/mips_singel_cycle.json index 8f439013..e36af0e7 100644 --- a/mips-lib/mips_singel_cycle.json +++ b/mips-lib/mips_singel_cycle.json @@ -1 +1,1955 @@ -{"store":[{"type":"Register","id":"pc","pos":[150.0,390.0],"r_in":{"id":"mux_jump_merge","field":"mux_out"}},{"type":"Register","id":"result_reg","pos":[850.0,225.0],"r_in":{"id":"mux_write_back","field":"mux_out"}},{"type":"Register","id":"reg_write_addr","pos":[850.0,525.0],"r_in":{"id":"mux_write_addr","field":"mux_out"}},{"type":"Register","id":"reg_we","pos":[850.0,50.0],"r_in":{"id":"control_unit","field":"reg_write_enable"}},{"type":"Constant","id":"0x_1F","pos":[350.0,550.0],"value":{"data":{"Data":31},"fmt":{"Hex":["_32",false]}}},{"type":"Wire","id":"from 0x_1F:constant_out to mux_write_addr:in2","pos":[[350.0,550.0],[388.0,537.0]],"input":{"id":"0x_1F","field":"constant_out"}},{"type":"Constant","id":"+4","pos":[150.0,440.0],"value":{"data":{"Data":4},"fmt":{"Hex":["_32",false]}}},{"type":"Wire","id":"from +4:constant_out to pc+4:a_in","pos":[[150.0,440.0],[188.0,412.0]],"input":{"id":"+4","field":"constant_out"}},{"type":"Add","id":"pc+4","pos":[200.0,400.0],"a_in":{"id":"+4","field":"constant_out"},"b_in":{"id":"pc","field":"register_out"},"scale":0.6},{"type":"Wire","id":"from pc+4:add_out to pc_add_branch:a_in","pos":[[225.0,436.5],[225.0,463.0],[388.0,463.0]],"input":{"id":"pc+4","field":"add_out"}},{"type":"PhysicalMem","id":"phys_mem","pos":[0.0,0.0]},{"type":"Wire","id":"from pc:register_out to pc+4:b_in","pos":[[176.0,390.0],[188.0,387.5]],"input":{"id":"pc","field":"register_out"}},{"type":"InstrMem","id":"instr_mem","pos":[250.0,575.0],"pc":{"id":"pc","field":"register_out"},"phys_mem_id":"phys_mem","regfile_id":"reg_file","mem_view":{"visible":false,"title":"instruction memory view","id":"instr_mem","row_offset":0,"max_rows":1024,"big_endian":true,"format":"HexAndMips","show_settings":{"symbols":true,"sections":false,"program_counter":false,"registers":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true]},"register_values":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2147483648,0,0],"dynamic_symbols":{"PC_IM":[0,true]},"break_points":[]}},{"type":"Wire","id":"from instr_mem:instruction to control_unit:control_unit_instr_in","pos":[[245.0,483.0],[245.0,50.0],[294.0,50.0]],"input":{"id":"instr_mem","field":"instruction"},"color_rgba":[0,0,0,20]},{"type":"JumpMerge","id":"jump_merge","pos":[125.0,475.0],"instr_addr_in":{"id":"pc","field":"register_out"},"jump_addr_in":{"id":"instr_mem","field":"instruction"}},{"type":"Wire","id":"from jump_merge:merge_out to mux_jump_merge:in2","pos":[[85.0,475.0],[67.0,475.0],[67.0,396.0],[88.0,396.0]],"input":{"id":"jump_merge","field":"merge_out"}},{"type":"Wire","id":"from pc+4:add_out to mux_jump_merge:in3","pos":[[212.0,400.0],[225.0,400.0],[225.0,437.0],[77.0,437.0],[77.0,408.0],[88.0,408.0]],"input":{"id":"pc+4","field":"add_out"}},{"type":"Wire","id":"from instr_mem:instruction to jump_merge:merge_jump_addr_in","pos":[[245.0,541.5],[245.0,483.0],[165.0,483.0]],"input":{"id":"instr_mem","field":"instruction"}},{"type":"ControlUnit","id":"control_unit","pos":[500.0,50.0],"a_in":{"id":"instr_mem","field":"instruction"}},{"type":"Wire","id":"from control_unit:reg_write_src to mux_write_back:select","pos":[[690.0,63.5],[690.0,115.0],[794.0,115.0],[794.0,207.0]],"input":{"id":"control_unit","field":"reg_write_src"},"color_rgba":[0,0,0,20]},{"type":"Wire","id":"from control_unit:reg_write_enable to reg_we:r_in","pos":[[706.0,50.0],[840.0,50.0]],"input":{"id":"control_unit","field":"reg_write_enable"},"color_rgba":[0,0,0,20]},{"type":"Wire","id":"from control_unit:mem_mode to data_mem:data_mem_op_in","pos":[[630.0,63.5],[630.0,541.5]],"input":{"id":"control_unit","field":"mem_mode"},"color_rgba":[0,0,0,20]},{"type":"Wire","id":"from control_unit:reg_dest to mux_write_addr:select","pos":[[400.0,63.5],[394.0,501.0]],"input":{"id":"control_unit","field":"reg_dest"}},{"type":"Wire","id":"from control_unit:mem_write_enable to data_mem:data_mem_write_enable","pos":[[600.0,63.5],[600.0,541.5]],"input":{"id":"control_unit","field":"mem_write_enable"},"color_rgba":[0,0,0,20]},{"type":"Wire","id":"from control_unit:alu_src_a to mux_source_a:select","pos":[[644.0,63.5],[644.0,171.0]],"input":{"id":"control_unit","field":"alu_src_a"},"color_rgba":[0,0,0,20]},{"type":"Wire","id":"from result_reg:register_out to reg_file:write_data_in","pos":[[860.0,225.0],[870.0,225.0],[870.0,373.0],[278.0,373.0],[278.0,335.0],[284.0,335.0]],"input":{"id":"result_reg","field":"register_out"}},{"type":"Wire","id":"from control_unit:extend_select to signzero_extend:signzero_ctrl_in","pos":[[333.3333,63.5],[325.0,404.0]],"input":{"id":"control_unit","field":"extend_select"},"color_rgba":[0,0,0,20]},{"type":"Wire","id":"from control_unit:alu_src_b to mux_source_b:select","pos":[[678.0,63.5],[678.0,212.0],[644.0,231.0]],"input":{"id":"control_unit","field":"alu_src_b"},"color_rgba":[0,0,0,20]},{"type":"InstrSplit","id":"instruction_split","pos":[200.0,225.0],"instruction_in":{"id":"instr_mem","field":"instruction"}},{"type":"Wire","id":"from instruction_split:rs_out to reg_file:rs_address_in","pos":[[231.0,213.88889],[261.0,213.88889],[261.0,85.0],[350.0,85.0],[350.0,94.0]],"input":{"id":"instruction_split","field":"rs_out"}},{"type":"ZeroExtend","id":"zero_extend_for_chamt","pos":[550.0,150.0],"signal_in":{"id":"instruction_split","field":"shamt_out"}},{"type":"Wire","id":"from zero_extend_for_chamt:zero_extend_out to mux_source_a:in0","pos":[[591.0,150.0],[638.0,183.0]],"input":{"id":"zero_extend_for_chamt","field":"zero_extend_out"}},{"type":"Mux","id":"mux_write_addr","pos":[400.0,525.0],"select":{"id":"control_unit","field":"reg_dest"},"m_in":[{"id":"instruction_split","field":"rt_out"},{"id":"instruction_split","field":"rd_out"},{"id":"0x_1F","field":"constant_out"}],"scale":0.6},{"type":"Wire","id":"from mux_write_addr:mux_out to reg_write_addr:r_in","pos":[[406.0,525.0],[840.0,525.0]],"input":{"id":"mux_write_addr","field":"mux_out"}},{"type":"Wire","id":"from instruction_split:rt_out to branch:branch_rt_in","pos":[[231.0,236.11111],[475.0,225.0]],"input":{"id":"instruction_split","field":"rt_out"}},{"type":"Wire","id":"from instruction_split:funct_out to branch:branch_funct_in","pos":[[231.0,191.66666],[475.0,225.0]],"input":{"id":"instruction_split","field":"funct_out"}},{"type":"Wire","id":"from instruction_split:rd_out to mux_write_addr:in1","pos":[[231.0,280.55554],[251.0,280.55554],[251.0,525.0],[388.0,525.0]],"input":{"id":"instruction_split","field":"rd_out"}},{"type":"Wire","id":"from instruction_split:rt_out to reg_file:rt_address_in","pos":[[231.0,236.11111],[350.0,356.0]],"input":{"id":"instruction_split","field":"rt_out"}},{"type":"Wire","id":"from instruction_split:rt_out to mux_write_addr:in0","pos":[[231.0,236.11111],[255.0,236.11111],[255.0,512.5],[388.0,513.0]],"input":{"id":"instruction_split","field":"rt_out"}},{"type":"Wire","id":"from instruction_split:op_out to branch:branch_op_in","pos":[[231.0,169.44444],[475.0,225.0]],"input":{"id":"instruction_split","field":"op_out"}},{"type":"Constant","id":"0_a_inp","pos":[610.0,220.0],"value":{"data":{"Data":0},"fmt":{"Hex":["_32",false]}}},{"type":"Wire","id":"from 0_a_inp:constant_out to mux_source_a:in2","pos":[[610.0,220.0],[638.0,207.0]],"input":{"id":"0_a_inp","field":"constant_out"}},{"type":"Wire","id":"from pc:register_out to jump_merge:merge_instr_addr_in","pos":[[175.5,471.0],[165.0,471.0]],"input":{"id":"pc","field":"register_out"}},{"type":"Wire","id":"from pc:register_out to instr_mem:pc","pos":[[160.0,390.0],[175.79999,390.0],[175.79999,520.0],[210.0,520.0],[210.0,541.5]],"input":{"id":"pc","field":"register_out"}},{"type":"Wire","id":"from control_unit:alu_op to alu:full_add_op_in","pos":[[660.0,63.5],[660.0,123.0],[710.0,123.0],[710.0,185.0]],"input":{"id":"control_unit","field":"alu_op"},"color_rgba":[0,0,0,20]},{"type":"SignZeroExtend","id":"signzero_extend","pos":[325.0,425.0],"signzero_signal_in":{"id":"instruction_split","field":"immediate_out"},"signzero_ctrl_in":{"id":"control_unit","field":"extend_select"}},{"type":"ShiftConst","id":"branch_shift","pos":[325.0,480.0],"signal_in":{"id":"signzero_extend","field":"sz_out"},"shift_by":2},{"type":"Add","id":"pc_add_branch","pos":[400.0,475.0],"a_in":{"id":"pc+4","field":"add_out"},"b_in":{"id":"branch_shift","field":"shift_left_const_out"},"scale":0.6},{"type":"Wire","id":"from signzero_extend:sz_out to mux_source_b:in2","pos":[[390.0,425.0],[541.0,425.0],[541.0,268.0],[638.0,267.0]],"input":{"id":"signzero_extend","field":"sz_out"}},{"type":"Wire","id":"from signzero_extend:sz_out to branch_shift:shift_in","pos":[[384.0,425.0],[390.0,425.0],[390.0,448.0],[280.5,448.0],[280.5,480.0],[291.5,480.0]],"input":{"id":"signzero_extend","field":"sz_out"}},{"type":"Wire","id":"from branch_shift:shift_left_const_out to pc_add_branch:b_in","pos":[[358.5,480.0],[388.0,487.0]],"input":{"id":"branch_shift","field":"shift_left_const_out"}},{"type":"Wire","id":"from instruction_split:immediate_out to signzero_extend:signzero_signal_in","pos":[[231.0,258.3333],[266.5,425.0]],"input":{"id":"instruction_split","field":"immediate_out"}},{"type":"Wire","id":"from reg_write_addr:register_out to reg_file:write_address_in","pos":[[860.0,525.0],[870.0,525.0],[870.0,390.0],[273.0,390.0],[273.0,315.0],[285.0,315.0]],"input":{"id":"reg_write_addr","field":"register_out"}},{"type":"Wire","id":"from pc+4:add_out to mux_source_b:in1","pos":[[225.0,400.0],[477.0,400.0],[477.0,256.0],[638.0,255.0]],"input":{"id":"pc+4","field":"add_out"}},{"type":"RegFile","id":"reg_file","pos":[350.0,225.0],"rs_address_in":{"id":"instruction_split","field":"rs_out"},"rt_address_in":{"id":"instruction_split","field":"rt_out"},"write_address_in":{"id":"reg_write_addr","field":"register_out"},"write_data_in":{"id":"result_reg","field":"register_out"},"write_enable_in":{"id":"reg_we","field":"register_out"}},{"type":"Wire","id":"from reg_file:rs_value_out to mux_jump_merge:in1","pos":[[416.0,265.0],[436.0,265.0],[436.0,362.0],[219.0,362.0],[219.0,347.0],[67.0,347.0],[67.0,384.0],[88.0,384.0]],"input":{"id":"reg_file","field":"rs_value_out"}},{"type":"Mux","id":"mux_source_a","pos":[650.0,195.0],"select":{"id":"control_unit","field":"alu_src_a"},"m_in":[{"id":"zero_extend_for_chamt","field":"zero_extend_out"},{"id":"reg_file","field":"rs_value_out"},{"id":"0_a_inp","field":"constant_out"}],"scale":0.6},{"type":"Wire","id":"from mux_source_a:mux_out to alu:full_add_a_in","pos":[[656.0,195.0],[700.0,195.0]],"input":{"id":"mux_source_a","field":"mux_out"}},{"type":"Mux","id":"mux_source_b","pos":[650.0,255.0],"select":{"id":"control_unit","field":"alu_src_b"},"m_in":[{"id":"reg_file","field":"rt_value_out"},{"id":"pc+4","field":"add_out"},{"id":"signzero_extend","field":"sz_out"}],"scale":0.6},{"type":"Wire","id":"from mux_source_b:mux_out to alu:full_add_b_in","pos":[[656.0,255.0],[700.0,255.0]],"input":{"id":"mux_source_b","field":"mux_out"}},{"type":"FullAdd","id":"alu","pos":[720.0,225.0],"a_in":{"id":"mux_source_a","field":"mux_out"},"b_in":{"id":"mux_source_b","field":"mux_out"},"op_in":{"id":"control_unit","field":"alu_op"}},{"type":"Wire","id":"from alu:alu_out to mux_write_back:in0","pos":[[750.0,225.0],[764.0,225.0],[764.0,219.0],[788.0,219.0]],"input":{"id":"alu","field":"alu_out"}},{"type":"Wire","id":"from alu:alu_out to data_mem:data_mem_address_in","pos":[[740.0,225.0],[750.0,225.0],[750.0,450.0],[570.0,450.0],[570.0,541.5]],"input":{"id":"alu","field":"alu_out"}},{"type":"Wire","id":"from reg_file:rt_value_out to data_mem:data_mem_write_data_in","pos":[[520.0,185.0],[520.0,575.0],[534.0,575.0]],"input":{"id":"reg_file","field":"rt_value_out"}},{"type":"Wire","id":"from reg_file:rs_value_out to mux_source_a:in1","pos":[[416.0,265.0],[638.0,195.0]],"input":{"id":"reg_file","field":"rs_value_out"}},{"type":"Wire","id":"from reg_file:rt_value_out to mux_source_b:in0","pos":[[416.0,185.0],[638.0,243.0]],"input":{"id":"reg_file","field":"rt_value_out"}},{"type":"BranchLogic","id":"branch","pos":[475.0,225.0],"op_in":{"id":"instruction_split","field":"op_out"},"rt_in":{"id":"instruction_split","field":"rt_out"},"funct_in":{"id":"instruction_split","field":"funct_out"},"rs_value":{"id":"reg_file","field":"rs_value_out"},"rt_value":{"id":"reg_file","field":"rt_value_out"}},{"type":"Mux","id":"mux_jump_merge","pos":[100.0,390.0],"select":{"id":"branch","field":"branch_out"},"m_in":[{"id":"pc_add_branch","field":"add_out"},{"id":"reg_file","field":"rs_value_out"},{"id":"jump_merge","field":"merge_out"},{"id":"pc+4","field":"add_out"}],"scale":0.6},{"type":"Wire","id":"from mux_jump_merge:mux_out to pc:r_in","pos":[[106.0,390.0],[140.0,390.0]],"input":{"id":"mux_jump_merge","field":"mux_out"}},{"type":"Wire","id":"from branch:branch_out to mux_jump_merge:select","pos":[[475.0,211.0],[475.0,90.0],[94.0,90.0],[94.0,360.0]],"input":{"id":"branch","field":"branch_out"},"color_rgba":[0,0,0,20]},{"type":"DataMem","id":"data_mem","pos":[600.0,575.0],"address_input":{"id":"alu","field":"alu_out"},"data_input":{"id":"reg_file","field":"rt_value_out"},"op_input":{"id":"control_unit","field":"mem_mode"},"write_enable_input":{"id":"control_unit","field":"mem_write_enable"},"phys_mem_id":"phys_mem","regfile_id":"reg_file","mem_view":{"visible":false,"title":"Data memory view","id":"data_mem","row_offset":0,"max_rows":1024,"big_endian":true,"format":"ByteAndUtf8","show_settings":{"symbols":true,"sections":false,"program_counter":false,"registers":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false]},"register_values":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2147483648,0,0],"dynamic_symbols":{"DM_ADRS":[0,false]},"break_points":[]}},{"type":"Wire","id":"from data_mem:data_out to mux_write_back:in1","pos":[[666.0,575.0],[775.0,575.0],[775.0,231.0],[788.0,231.0]],"input":{"id":"data_mem","field":"data_out"}},{"type":"Mux","id":"mux_write_back","pos":[800.0,225.0],"select":{"id":"control_unit","field":"reg_write_src"},"m_in":[{"id":"alu","field":"alu_out"},{"id":"data_mem","field":"data_out"}],"scale":0.6},{"type":"Wire","id":"from mux_write_back:mux_out to result_reg:r_in","pos":[[806.0,225.0],[840.0,225.0]],"input":{"id":"mux_write_back","field":"mux_out"}},{"type":"Wire","id":"from reg_file:rs_value_out to branch:branch_rs_value_id","pos":[[416.0,265.0],[475.0,225.0]],"input":{"id":"reg_file","field":"rs_value_out"}},{"type":"Wire","id":"from reg_file:rt_value_out to branch:branch_rt_value_id","pos":[[416.0,185.0],[475.0,225.0]],"input":{"id":"reg_file","field":"rt_value_out"}},{"type":"Wire","id":"from reg_we:register_out to reg_file:write_enable_in","pos":[[860.0,50.0],[870.0,50.0],[870.0,85.0],[370.0,85.0],[370.0,94.0]],"input":{"id":"reg_we","field":"register_out"},"color_rgba":[0,0,0,20]},{"type":"Wire","id":"from instr_mem:instruction to instruction_split:instruction_in","pos":[[245.0,343.5],[200.0,343.5],[200.0,330.5]],"input":{"id":"instr_mem","field":"instruction"}},{"type":"Wire","id":"from pc_add_branch:add_out to mux_jump_merge:in0","pos":[[412.0,475.0],[422.5,475.0],[422.5,365.0],[213.0,365.0],[213.0,356.0],[75.0,356.0],[75.0,372.0],[88.0,372.0]],"input":{"id":"pc_add_branch","field":"add_out"}},{"type":"Wire","id":"from instruction_split:shamt_out to zero_extend_for_chamt:signal_in","pos":[[231.0,147.22223],[509.0,150.0]],"input":{"id":"instruction_split","field":"shamt_out"}}]} \ No newline at end of file +{ + "store": [ + { + "type": "Register", + "id": "reg_we", + "pos": [ + 850.0, + 50.0 + ], + "r_in": { + "id": "control_unit", + "field": "reg_write_enable" + } + }, + { + "type": "Register", + "id": "result_reg", + "pos": [ + 850.0, + 225.0 + ], + "r_in": { + "id": "mux_write_back", + "field": "mux_out" + } + }, + { + "type": "Register", + "id": "pc", + "pos": [ + 150.0, + 390.0 + ], + "r_in": { + "id": "mux_jump_merge", + "field": "mux_out" + } + }, + { + "type": "Register", + "id": "reg_write_addr", + "pos": [ + 850.0, + 525.0 + ], + "r_in": { + "id": "mux_write_addr", + "field": "mux_out" + } + }, + { + "type": "Wire", + "id": "from result_reg:register_out to reg_file:write_data_in", + "pos": [ + [ + 860.0, + 225.0 + ], + [ + 870.0, + 225.0 + ], + [ + 870.0, + 373.0 + ], + [ + 278.0, + 373.0 + ], + [ + 278.0, + 335.0 + ], + [ + 284.0, + 335.0 + ] + ], + "input": { + "id": "result_reg", + "field": "register_out" + } + }, + { + "type": "Constant", + "id": "0x_1F", + "pos": [ + 350.0, + 550.0 + ], + "value": { + "data": { + "Data": 31 + }, + "fmt": { + "Hex": [ + "_32", + false + ] + } + } + }, + { + "type": "Wire", + "id": "from 0x_1F:constant_out to mux_write_addr:in2", + "pos": [ + [ + 350.0, + 550.0 + ], + [ + 388.0, + 537.0 + ] + ], + "input": { + "id": "0x_1F", + "field": "constant_out" + } + }, + { + "type": "Constant", + "id": "0_a_inp", + "pos": [ + 610.0, + 220.0 + ], + "value": { + "data": { + "Data": 0 + }, + "fmt": { + "Hex": [ + "_32", + false + ] + } + } + }, + { + "type": "Wire", + "id": "from 0_a_inp:constant_out to mux_source_a:in2", + "pos": [ + [ + 610.0, + 220.0 + ], + [ + 638.0, + 207.0 + ] + ], + "input": { + "id": "0_a_inp", + "field": "constant_out" + } + }, + { + "type": "Wire", + "id": "from reg_we:register_out to reg_file:write_enable_in", + "pos": [ + [ + 860.0, + 50.0 + ], + [ + 870.0, + 50.0 + ], + [ + 870.0, + 85.0 + ], + [ + 370.0, + 85.0 + ], + [ + 370.0, + 94.0 + ] + ], + "input": { + "id": "reg_we", + "field": "register_out" + }, + "color_rgba": [ + 0, + 0, + 0, + 20 + ] + }, + { + "type": "PhysicalMem", + "id": "phys_mem", + "pos": [ + 0.0, + 0.0 + ] + }, + { + "type": "InstrMem", + "id": "instr_mem", + "pos": [ + 250.0, + 575.0 + ], + "pc": { + "id": "pc", + "field": "register_out" + }, + "phys_mem_id": "phys_mem", + "regfile_id": "reg_file", + "mem_view": { + "visible": false, + "title": "instruction memory view", + "id": "instr_mem", + "row_offset": 0, + "max_rows": 1024, + "big_endian": true, + "format": "HexAndMips", + "show_settings": { + "symbols": true, + "sections": false, + "program_counter": false, + "registers": [ + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + true + ] + }, + "register_values": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2147483648, + 0, + 0 + ], + "dynamic_symbols": { + "PC_IM": [ + 0, + true + ] + }, + "break_points": [] + } + }, + { + "type": "JumpMerge", + "id": "jump_merge", + "pos": [ + 125.0, + 475.0 + ], + "instr_addr_in": { + "id": "pc", + "field": "register_out" + }, + "jump_addr_in": { + "id": "instr_mem", + "field": "instruction" + } + }, + { + "type": "Wire", + "id": "from jump_merge:merge_out to mux_jump_merge:in2", + "pos": [ + [ + 85.0, + 475.0 + ], + [ + 67.0, + 475.0 + ], + [ + 67.0, + 396.0 + ], + [ + 88.0, + 396.0 + ] + ], + "input": { + "id": "jump_merge", + "field": "merge_out" + } + }, + { + "type": "Wire", + "id": "from instr_mem:instruction to control_unit:control_unit_instr_in", + "pos": [ + [ + 245.0, + 344.0 + ], + [ + 245.0, + 50.0 + ], + [ + 294.0, + 50.0 + ] + ], + "input": { + "id": "instr_mem", + "field": "instruction" + }, + "color_rgba": [ + 0, + 0, + 0, + 20 + ] + }, + { + "type": "InstrSplit", + "id": "instruction_split", + "pos": [ + 200.0, + 225.0 + ], + "instruction_in": { + "id": "instr_mem", + "field": "instruction" + } + }, + { + "type": "Wire", + "id": "from instruction_split:rt_out to mux_write_addr:in0", + "pos": [ + [ + 231.0, + 236.11111 + ], + [ + 255.0, + 236.11111 + ], + [ + 255.0, + 512.5 + ], + [ + 388.0, + 513.0 + ] + ], + "input": { + "id": "instruction_split", + "field": "rt_out" + } + }, + { + "type": "Wire", + "id": "from instruction_split:shamt_out to zero_extend_for_chamt:signal_in", + "pos": [ + [ + 231.0, + 147.0 + ], + [ + 250.0, + 147.0 + ], + [ + 250.0, + 77.0 + ], + [ + 483.0, + 77.0 + ], + [ + 483.0, + 150.0 + ], + [ + 509.0, + 150.0 + ] + ], + "input": { + "id": "instruction_split", + "field": "shamt_out" + } + }, + { + "type": "Wire", + "id": "from instruction_split:immediate_out to signzero_extend:signzero_signal_in", + "pos": [ + [ + 231.0, + 258.3333 + ], + [ + 236.0, + 258.3333 + ], + [ + 236.0, + 425.0 + ], + [ + 266.5, + 425.0 + ] + ], + "input": { + "id": "instruction_split", + "field": "immediate_out" + } + }, + { + "type": "Wire", + "id": "from instruction_split:rs_out to reg_file:rs_address_in", + "pos": [ + [ + 231.0, + 213.88889 + ], + [ + 261.0, + 213.88889 + ], + [ + 261.0, + 85.0 + ], + [ + 350.0, + 85.0 + ], + [ + 350.0, + 94.0 + ] + ], + "input": { + "id": "instruction_split", + "field": "rs_out" + } + }, + { + "type": "Wire", + "id": "from instruction_split:rd_out to mux_write_addr:in1", + "pos": [ + [ + 231.0, + 280.55554 + ], + [ + 251.0, + 280.55554 + ], + [ + 251.0, + 525.0 + ], + [ + 388.0, + 525.0 + ] + ], + "input": { + "id": "instruction_split", + "field": "rd_out" + } + }, + { + "type": "ZeroExtend", + "id": "zero_extend_for_chamt", + "pos": [ + 550.0, + 150.0 + ], + "signal_in": { + "id": "instruction_split", + "field": "shamt_out" + } + }, + { + "type": "Wire", + "id": "from zero_extend_for_chamt:zero_extend_out to mux_source_a:in0", + "pos": [ + [ + 591.0, + 150.0 + ], + [ + 607.0, + 150.0 + ], + [ + 607.0, + 183.0 + ], + [ + 638.0, + 183.0 + ] + ], + "input": { + "id": "zero_extend_for_chamt", + "field": "zero_extend_out" + } + }, + { + "type": "Wire", + "id": "from instruction_split:rt_out to reg_file:rt_address_in", + "pos": [ + [ + 255.0, + 261.0 + ], + [ + 284.0, + 261.0 + ] + ], + "input": { + "id": "instruction_split", + "field": "rt_out" + } + }, + { + "type": "ControlUnit", + "id": "control_unit", + "pos": [ + 500.0, + 50.0 + ], + "a_in": { + "id": "instr_mem", + "field": "instruction" + } + }, + { + "type": "Wire", + "id": "from control_unit:alu_src_a to mux_source_a:select", + "pos": [ + [ + 644.0, + 63.5 + ], + [ + 644.0, + 171.0 + ] + ], + "input": { + "id": "control_unit", + "field": "alu_src_a" + }, + "color_rgba": [ + 0, + 0, + 0, + 20 + ] + }, + { + "type": "Wire", + "id": "from control_unit:reg_write_src to mux_write_back:select", + "pos": [ + [ + 690.0, + 63.5 + ], + [ + 690.0, + 115.0 + ], + [ + 794.0, + 115.0 + ], + [ + 794.0, + 207.0 + ] + ], + "input": { + "id": "control_unit", + "field": "reg_write_src" + }, + "color_rgba": [ + 0, + 0, + 0, + 20 + ] + }, + { + "type": "Wire", + "id": "from control_unit:extend_select to signzero_extend:signzero_ctrl_in", + "pos": [ + [ + 333.3333, + 63.5 + ], + [ + 325.0, + 404.0 + ] + ], + "input": { + "id": "control_unit", + "field": "extend_select" + }, + "color_rgba": [ + 0, + 0, + 0, + 20 + ] + }, + { + "type": "SignZeroExtend", + "id": "signzero_extend", + "pos": [ + 325.0, + 425.0 + ], + "signzero_signal_in": { + "id": "instruction_split", + "field": "immediate_out" + }, + "signzero_ctrl_in": { + "id": "control_unit", + "field": "extend_select" + } + }, + { + "type": "Wire", + "id": "from signzero_extend:sz_out to branch_shift:shift_in", + "pos": [ + [ + 384.0, + 425.0 + ], + [ + 390.0, + 425.0 + ], + [ + 390.0, + 448.0 + ], + [ + 280.5, + 448.0 + ], + [ + 280.5, + 480.0 + ], + [ + 291.5, + 480.0 + ] + ], + "input": { + "id": "signzero_extend", + "field": "sz_out" + } + }, + { + "type": "ShiftConst", + "id": "branch_shift", + "pos": [ + 325.0, + 480.0 + ], + "signal_in": { + "id": "signzero_extend", + "field": "sz_out" + }, + "shift_by": 2 + }, + { + "type": "Mux", + "id": "mux_write_addr", + "pos": [ + 400.0, + 525.0 + ], + "select": { + "id": "control_unit", + "field": "reg_dest" + }, + "m_in": [ + { + "id": "instruction_split", + "field": "rt_out" + }, + { + "id": "instruction_split", + "field": "rd_out" + }, + { + "id": "0x_1F", + "field": "constant_out" + } + ], + "scale": 0.6 + }, + { + "type": "Wire", + "id": "from mux_write_addr:mux_out to reg_write_addr:r_in", + "pos": [ + [ + 406.0, + 525.0 + ], + [ + 840.0, + 525.0 + ] + ], + "input": { + "id": "mux_write_addr", + "field": "mux_out" + } + }, + { + "type": "Wire", + "id": "from control_unit:reg_dest to mux_write_addr:select", + "pos": [ + [ + 420.0, + 63.5 + ], + [ + 420.0, + 501.0 + ], + [ + 394.5, + 501.0 + ] + ], + "input": { + "id": "control_unit", + "field": "reg_dest" + }, + "color_rgba": [ + 0, + 0, + 0, + 20 + ] + }, + { + "type": "Wire", + "id": "from control_unit:alu_op to alu:full_add_op_in", + "pos": [ + [ + 660.0, + 63.5 + ], + [ + 660.0, + 123.0 + ], + [ + 710.0, + 123.0 + ], + [ + 710.0, + 185.0 + ] + ], + "input": { + "id": "control_unit", + "field": "alu_op" + }, + "color_rgba": [ + 0, + 0, + 0, + 20 + ] + }, + { + "type": "Wire", + "id": "from pc:register_out to pc+4:b_in", + "pos": [ + [ + 176.0, + 390.0 + ], + [ + 188.0, + 387.5 + ] + ], + "input": { + "id": "pc", + "field": "register_out" + } + }, + { + "type": "Wire", + "id": "from pc:register_out to instr_mem:pc", + "pos": [ + [ + 160.0, + 390.0 + ], + [ + 175.79999, + 390.0 + ], + [ + 175.79999, + 520.0 + ], + [ + 210.0, + 520.0 + ], + [ + 210.0, + 541.5 + ] + ], + "input": { + "id": "pc", + "field": "register_out" + } + }, + { + "type": "Wire", + "id": "from branch_shift:shift_left_const_out to pc_add_branch:b_in", + "pos": [ + [ + 358.5, + 480.0 + ], + [ + 388.0, + 487.0 + ] + ], + "input": { + "id": "branch_shift", + "field": "shift_left_const_out" + } + }, + { + "type": "Wire", + "id": "from pc:register_out to jump_merge:merge_instr_addr_in", + "pos": [ + [ + 175.5, + 471.0 + ], + [ + 165.0, + 471.0 + ] + ], + "input": { + "id": "pc", + "field": "register_out" + } + }, + { + "type": "Wire", + "id": "from instr_mem:instruction to jump_merge:merge_jump_addr_in", + "pos": [ + [ + 245.0, + 541.5 + ], + [ + 245.0, + 483.0 + ], + [ + 165.0, + 483.0 + ] + ], + "input": { + "id": "instr_mem", + "field": "instruction" + } + }, + { + "type": "Wire", + "id": "from control_unit:mem_mode to data_mem:data_mem_op_in", + "pos": [ + [ + 630.0, + 63.5 + ], + [ + 630.0, + 541.5 + ] + ], + "input": { + "id": "control_unit", + "field": "mem_mode" + }, + "color_rgba": [ + 0, + 0, + 0, + 20 + ] + }, + { + "type": "Wire", + "id": "from control_unit:reg_write_enable to reg_we:r_in", + "pos": [ + [ + 706.0, + 50.0 + ], + [ + 840.0, + 50.0 + ] + ], + "input": { + "id": "control_unit", + "field": "reg_write_enable" + }, + "color_rgba": [ + 0, + 0, + 0, + 20 + ] + }, + { + "type": "Wire", + "id": "from control_unit:alu_src_b to mux_source_b:select", + "pos": [ + [ + 678.0, + 63.5 + ], + [ + 678.0, + 212.0 + ], + [ + 644.0, + 231.0 + ] + ], + "input": { + "id": "control_unit", + "field": "alu_src_b" + }, + "color_rgba": [ + 0, + 0, + 0, + 20 + ] + }, + { + "type": "Wire", + "id": "from reg_write_addr:register_out to reg_file:write_address_in", + "pos": [ + [ + 860.0, + 525.0 + ], + [ + 870.0, + 525.0 + ], + [ + 870.0, + 390.0 + ], + [ + 273.0, + 390.0 + ], + [ + 273.0, + 315.0 + ], + [ + 285.0, + 315.0 + ] + ], + "input": { + "id": "reg_write_addr", + "field": "register_out" + } + }, + { + "type": "RegFile", + "id": "reg_file", + "pos": [ + 350.0, + 225.0 + ], + "rs_address_in": { + "id": "instruction_split", + "field": "rs_out" + }, + "rt_address_in": { + "id": "instruction_split", + "field": "rt_out" + }, + "write_address_in": { + "id": "reg_write_addr", + "field": "register_out" + }, + "write_data_in": { + "id": "result_reg", + "field": "register_out" + }, + "write_enable_in": { + "id": "reg_we", + "field": "register_out" + } + }, + { + "type": "Wire", + "id": "from reg_file:rs_value_out to mux_source_a:in1", + "pos": [ + [ + 436.0, + 195.0 + ], + [ + 638.0, + 195.0 + ] + ], + "input": { + "id": "reg_file", + "field": "rs_value_out" + } + }, + { + "type": "Wire", + "id": "from reg_file:rt_value_out to branch:branch_rt_value_id", + "pos": [ + [ + 448.5, + 195.0 + ], + [ + 448.5, + 211.0 + ] + ], + "input": { + "id": "reg_file", + "field": "rt_value_out" + } + }, + { + "type": "Wire", + "id": "from reg_file:rs_value_out to mux_jump_merge:in1", + "pos": [ + [ + 416.0, + 195.0 + ], + [ + 436.0, + 195.0 + ], + [ + 436.0, + 72.0 + ], + [ + 67.0, + 72.0 + ], + [ + 67.0, + 384.0 + ], + [ + 88.0, + 384.0 + ] + ], + "input": { + "id": "reg_file", + "field": "rs_value_out" + } + }, + { + "type": "BranchLogic", + "id": "branch", + "pos": [ + 475.0, + 225.0 + ], + "op_in": { + "id": "instruction_split", + "field": "op_out" + }, + "rt_in": { + "id": "instruction_split", + "field": "rt_out" + }, + "funct_in": { + "id": "instruction_split", + "field": "funct_out" + }, + "rs_value": { + "id": "reg_file", + "field": "rs_value_out" + }, + "rt_value": { + "id": "reg_file", + "field": "rt_value_out" + } + }, + { + "type": "Wire", + "id": "from branch:branch_out to mux_jump_merge:select", + "pos": [ + [ + 475.0, + 211.0 + ], + [ + 475.0, + 90.0 + ], + [ + 94.0, + 90.0 + ], + [ + 94.0, + 360.0 + ] + ], + "input": { + "id": "branch", + "field": "branch_out" + }, + "color_rgba": [ + 0, + 0, + 0, + 20 + ] + }, + { + "type": "Mux", + "id": "mux_source_a", + "pos": [ + 650.0, + 195.0 + ], + "select": { + "id": "control_unit", + "field": "alu_src_a" + }, + "m_in": [ + { + "id": "zero_extend_for_chamt", + "field": "zero_extend_out" + }, + { + "id": "reg_file", + "field": "rs_value_out" + }, + { + "id": "0_a_inp", + "field": "constant_out" + } + ], + "scale": 0.6 + }, + { + "type": "Wire", + "id": "from mux_source_a:mux_out to alu:full_add_a_in", + "pos": [ + [ + 656.0, + 195.0 + ], + [ + 700.0, + 195.0 + ] + ], + "input": { + "id": "mux_source_a", + "field": "mux_out" + } + }, + { + "type": "Wire", + "id": "from reg_file:rt_value_out to mux_source_b:in0", + "pos": [ + [ + 416.0, + 265.0 + ], + [ + 448.5, + 265.0 + ], + [ + 448.5, + 243.0 + ], + [ + 638.0, + 243.0 + ] + ], + "input": { + "id": "reg_file", + "field": "rt_value_out" + } + }, + { + "type": "Wire", + "id": "from reg_file:rt_value_out to data_mem:data_mem_write_data_in", + "pos": [ + [ + 520.0, + 244.0 + ], + [ + 520.0, + 575.0 + ], + [ + 534.0, + 575.0 + ] + ], + "input": { + "id": "reg_file", + "field": "rt_value_out" + } + }, + { + "type": "Wire", + "id": "from reg_file:rs_value_out to branch:branch_rs_value_id", + "pos": [ + [ + 448.5, + 245.0 + ], + [ + 448.5, + 238.0 + ] + ], + "input": { + "id": "reg_file", + "field": "rs_value_out" + } + }, + { + "type": "Constant", + "id": "+4", + "pos": [ + 150.0, + 440.0 + ], + "value": { + "data": { + "Data": 4 + }, + "fmt": { + "Hex": [ + "_32", + false + ] + } + } + }, + { + "type": "Wire", + "id": "from +4:constant_out to pc+4:a_in", + "pos": [ + [ + 150.0, + 440.0 + ], + [ + 188.0, + 412.0 + ] + ], + "input": { + "id": "+4", + "field": "constant_out" + } + }, + { + "type": "Add", + "id": "pc+4", + "pos": [ + 200.0, + 400.0 + ], + "a_in": { + "id": "+4", + "field": "constant_out" + }, + "b_in": { + "id": "pc", + "field": "register_out" + }, + "scale": 0.6 + }, + { + "type": "Add", + "id": "pc_add_branch", + "pos": [ + 400.0, + 475.0 + ], + "a_in": { + "id": "pc+4", + "field": "add_out" + }, + "b_in": { + "id": "branch_shift", + "field": "shift_left_const_out" + }, + "scale": 0.6 + }, + { + "type": "Wire", + "id": "from pc_add_branch:add_out to mux_jump_merge:in0", + "pos": [ + [ + 412.0, + 475.0 + ], + [ + 422.5, + 475.0 + ], + [ + 422.5, + 365.0 + ], + [ + 213.0, + 365.0 + ], + [ + 213.0, + 356.0 + ], + [ + 75.0, + 356.0 + ], + [ + 75.0, + 372.0 + ], + [ + 88.0, + 372.0 + ] + ], + "input": { + "id": "pc_add_branch", + "field": "add_out" + } + }, + { + "type": "Mux", + "id": "mux_jump_merge", + "pos": [ + 100.0, + 390.0 + ], + "select": { + "id": "branch", + "field": "branch_out" + }, + "m_in": [ + { + "id": "pc_add_branch", + "field": "add_out" + }, + { + "id": "reg_file", + "field": "rs_value_out" + }, + { + "id": "jump_merge", + "field": "merge_out" + }, + { + "id": "pc+4", + "field": "add_out" + } + ], + "scale": 0.6 + }, + { + "type": "Wire", + "id": "from mux_jump_merge:mux_out to pc:r_in", + "pos": [ + [ + 106.0, + 390.0 + ], + [ + 140.0, + 390.0 + ] + ], + "input": { + "id": "mux_jump_merge", + "field": "mux_out" + } + }, + { + "type": "Wire", + "id": "from pc+4:add_out to mux_jump_merge:in3", + "pos": [ + [ + 212.0, + 400.0 + ], + [ + 225.0, + 400.0 + ], + [ + 225.0, + 437.0 + ], + [ + 77.0, + 437.0 + ], + [ + 77.0, + 408.0 + ], + [ + 88.0, + 408.0 + ] + ], + "input": { + "id": "pc+4", + "field": "add_out" + } + }, + { + "type": "Mux", + "id": "mux_source_b", + "pos": [ + 650.0, + 255.0 + ], + "select": { + "id": "control_unit", + "field": "alu_src_b" + }, + "m_in": [ + { + "id": "reg_file", + "field": "rt_value_out" + }, + { + "id": "pc+4", + "field": "add_out" + }, + { + "id": "signzero_extend", + "field": "sz_out" + } + ], + "scale": 0.6 + }, + { + "type": "Wire", + "id": "from mux_source_b:mux_out to alu:full_add_b_in", + "pos": [ + [ + 656.0, + 255.0 + ], + [ + 700.0, + 255.0 + ] + ], + "input": { + "id": "mux_source_b", + "field": "mux_out" + } + }, + { + "type": "FullAdd", + "id": "alu", + "pos": [ + 720.0, + 225.0 + ], + "a_in": { + "id": "mux_source_a", + "field": "mux_out" + }, + "b_in": { + "id": "mux_source_b", + "field": "mux_out" + }, + "op_in": { + "id": "control_unit", + "field": "alu_op" + } + }, + { + "type": "Wire", + "id": "from alu:alu_out to mux_write_back:in0", + "pos": [ + [ + 750.0, + 225.0 + ], + [ + 764.0, + 225.0 + ], + [ + 764.0, + 219.0 + ], + [ + 788.0, + 219.0 + ] + ], + "input": { + "id": "alu", + "field": "alu_out" + } + }, + { + "type": "Wire", + "id": "from alu:alu_out to data_mem:data_mem_address_in", + "pos": [ + [ + 740.0, + 225.0 + ], + [ + 750.0, + 225.0 + ], + [ + 750.0, + 450.0 + ], + [ + 570.0, + 450.0 + ], + [ + 570.0, + 541.5 + ] + ], + "input": { + "id": "alu", + "field": "alu_out" + } + }, + { + "type": "DataMem", + "id": "data_mem", + "pos": [ + 600.0, + 575.0 + ], + "address_input": { + "id": "alu", + "field": "alu_out" + }, + "data_input": { + "id": "reg_file", + "field": "rt_value_out" + }, + "op_input": { + "id": "control_unit", + "field": "mem_mode" + }, + "write_enable_input": { + "id": "control_unit", + "field": "mem_write_enable" + }, + "phys_mem_id": "phys_mem", + "regfile_id": "reg_file", + "mem_view": { + "visible": false, + "title": "Data memory view", + "id": "data_mem", + "row_offset": 0, + "max_rows": 1024, + "big_endian": true, + "format": "ByteAndUtf8", + "show_settings": { + "symbols": true, + "sections": false, + "program_counter": false, + "registers": [ + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false + ] + }, + "register_values": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2147483648, + 0, + 0 + ], + "dynamic_symbols": { + "DM_ADRS": [ + 0, + false + ] + }, + "break_points": [] + } + }, + { + "type": "Wire", + "id": "from data_mem:data_out to mux_write_back:in1", + "pos": [ + [ + 666.0, + 575.0 + ], + [ + 775.0, + 575.0 + ], + [ + 775.0, + 231.0 + ], + [ + 788.0, + 231.0 + ] + ], + "input": { + "id": "data_mem", + "field": "data_out" + } + }, + { + "type": "Mux", + "id": "mux_write_back", + "pos": [ + 800.0, + 225.0 + ], + "select": { + "id": "control_unit", + "field": "reg_write_src" + }, + "m_in": [ + { + "id": "alu", + "field": "alu_out" + }, + { + "id": "data_mem", + "field": "data_out" + } + ], + "scale": 0.6 + }, + { + "type": "Wire", + "id": "from mux_write_back:mux_out to result_reg:r_in", + "pos": [ + [ + 806.0, + 225.0 + ], + [ + 840.0, + 225.0 + ] + ], + "input": { + "id": "mux_write_back", + "field": "mux_out" + } + }, + { + "type": "Wire", + "id": "from pc+4:add_out to pc_add_branch:a_in", + "pos": [ + [ + 225.0, + 436.5 + ], + [ + 225.0, + 463.0 + ], + [ + 388.0, + 463.0 + ] + ], + "input": { + "id": "pc+4", + "field": "add_out" + } + }, + { + "type": "Wire", + "id": "from pc+4:add_out to mux_source_b:in1", + "pos": [ + [ + 225.0, + 400.0 + ], + [ + 477.0, + 400.0 + ], + [ + 477.0, + 256.0 + ], + [ + 638.0, + 255.0 + ] + ], + "input": { + "id": "pc+4", + "field": "add_out" + } + }, + { + "type": "Wire", + "id": "from control_unit:mem_write_enable to data_mem:data_mem_write_enable", + "pos": [ + [ + 600.0, + 63.5 + ], + [ + 600.0, + 541.5 + ] + ], + "input": { + "id": "control_unit", + "field": "mem_write_enable" + }, + "color_rgba": [ + 0, + 0, + 0, + 20 + ] + }, + { + "type": "Wire", + "id": "from signzero_extend:sz_out to mux_source_b:in2", + "pos": [ + [ + 390.0, + 425.0 + ], + [ + 541.0, + 425.0 + ], + [ + 541.0, + 268.0 + ], + [ + 638.0, + 267.0 + ] + ], + "input": { + "id": "signzero_extend", + "field": "sz_out" + } + }, + { + "type": "Wire", + "id": "from instr_mem:instruction to instruction_split:instruction_in", + "pos": [ + [ + 245.0, + 483.0 + ], + [ + 245.0, + 343.5 + ], + [ + 200.0, + 343.5 + ], + [ + 200.0, + 330.5 + ] + ], + "input": { + "id": "instr_mem", + "field": "instruction" + } + } + ] +} \ No newline at end of file From afe459ecc75b2391a511f5ed33f21d3df5ed661a Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 11 Sep 2024 16:50:50 +0200 Subject: [PATCH 107/126] FIX go_to_type defaulted to none, now defaults to top --- mips-lib/src/gui_egui/mips_mem_view_window.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mips-lib/src/gui_egui/mips_mem_view_window.rs b/mips-lib/src/gui_egui/mips_mem_view_window.rs index c782796d..b606746a 100644 --- a/mips-lib/src/gui_egui/mips_mem_view_window.rs +++ b/mips-lib/src/gui_egui/mips_mem_view_window.rs @@ -24,7 +24,7 @@ pub struct MemViewWindow { #[serde(skip)] go_to_address: GoAddress, // determents what is used as GoAddress in the top bar - #[serde(skip)] + #[serde(skip, default = "MemViewWindow::go_type_def")] go_type: GoAddress, // used when user wants to go to another address #[serde(skip)] @@ -90,6 +90,9 @@ fn set_address(adrs: &GoAddress, new_adrs: u32) -> GoAddress { } impl MemViewWindow { + fn go_type_def() -> GoAddress { + GoAddress::Top(0) + } // creates a new memory view window with id string and the given memory pub fn new(id: String, title: String) -> Self { MemViewWindow { From d079e326412471d6b40fc4dc8572a60d90691a16 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 12 Sep 2024 11:12:28 +0200 Subject: [PATCH 108/126] git fixed wrong order of shift in alu, and made other shifts panic resistant --- mips-lib/src/components/full_adder.rs | 6 +++--- mips-lib/src/components/mips_jump_merge.rs | 2 +- src/components/shift_left_const.rs | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mips-lib/src/components/full_adder.rs b/mips-lib/src/components/full_adder.rs index 9b1cf239..6833b736 100644 --- a/mips-lib/src/components/full_adder.rs +++ b/mips-lib/src/components/full_adder.rs @@ -153,13 +153,13 @@ impl Component for FullAdd { output = (a < b) as u32; } alu_op::SLL => { - output = a.overflowing_shl(b).0; // https://doc.rust-lang.org/std/primitive.u32.html#method.overflowing_shl + output = b.overflowing_shl(a).0; // https://doc.rust-lang.org/std/primitive.u32.html#method.overflowing_shl } alu_op::SRL => { - output = a.overflowing_shr(b).0; + output = b.overflowing_shr(a).0; } alu_op::SRA => { - output = (a as i32).overflowing_shr(b).0 as u32; + output = (b as i32).overflowing_shr(a).0 as u32; } alu_op::LUI => { output = (a & 0x0000_ffff) | b.overflowing_shl(16).0; diff --git a/mips-lib/src/components/mips_jump_merge.rs b/mips-lib/src/components/mips_jump_merge.rs index 760f751b..dcce5b40 100644 --- a/mips-lib/src/components/mips_jump_merge.rs +++ b/mips-lib/src/components/mips_jump_merge.rs @@ -75,7 +75,7 @@ impl Component for JumpMerge { .try_into() .unwrap(); - let output = (instr_addr & 0xf000_0000) | ((jump_addr << 2) & 0x0fff_ffff); + let output = (instr_addr & 0xf000_0000) | (jump_addr.overflowing_shl(2).0 & 0x0fff_ffff); simulator.set_out_value(&self.id, MERGE_OUT_ID, SignalValue::Data(output)); Ok(()) diff --git a/src/components/shift_left_const.rs b/src/components/shift_left_const.rs index b6428315..6b621ec5 100644 --- a/src/components/shift_left_const.rs +++ b/src/components/shift_left_const.rs @@ -66,7 +66,8 @@ impl Component for ShiftConst { .try_into() .unwrap(); - let output: u32 = signal_in << self.shift_by; + // let output: u32 = signal_in << self.shift_by; + let output: u32 = signal_in.overflowing_shl(self.shift_by).0; simulator.set_out_value(&self.id, SHIFT_OUT_ID, SignalValue::Data(output)); Ok(()) } From 6b8b77a5999135c7ca0682183d7dfecdb31c6de1 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 12 Sep 2024 11:58:43 +0200 Subject: [PATCH 109/126] moved mips simple to an example of mips-lib and json file --- Cargo.toml | 2 +- .../examples/mips_singel_sycle.rs | 0 mips-simple/Cargo.toml | 17 ----------------- 3 files changed, 1 insertion(+), 18 deletions(-) rename mips-simple/src/main.rs => mips-lib/examples/mips_singel_sycle.rs (100%) delete mode 100644 mips-simple/Cargo.toml diff --git a/Cargo.toml b/Cargo.toml index 056b2b51..7c07cb5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [workspace] -members = [ "mips-lib","mips-simple", "riscv"] +members = [ "mips-lib", "riscv"] [dependencies] MIPS_disassembly = "0.1.2" diff --git a/mips-simple/src/main.rs b/mips-lib/examples/mips_singel_sycle.rs similarity index 100% rename from mips-simple/src/main.rs rename to mips-lib/examples/mips_singel_sycle.rs diff --git a/mips-simple/Cargo.toml b/mips-simple/Cargo.toml deleted file mode 100644 index a43f59a1..00000000 --- a/mips-simple/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "mips-simple" -version = "0.1.0" -edition = "2021" - -[dependencies] -mips-lib = {path = "../mips-lib/"} -[dependencies.syncrim] -path = "../" -default-features = false - -[features] -default = ["gui-egui"] - -components = ["syncrim/components"] -gui-vizia = ["syncrim/gui-vizia", "components"] -gui-egui = ["syncrim/gui-egui", "components"] From e8c6853c5f7a033aeb78de526f3eafed1d320cff Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:39:38 +0200 Subject: [PATCH 110/126] fixed names of functions and files --- mips-lib/examples/{full_adder.rs => mips_alu.rs} | 4 ++-- mips-lib/examples/mips_controll_unit.rs | 2 +- mips-lib/examples/mips_im_dm_regfile.rs | 1 - mips-lib/examples/mips_instruction_splitter.rs | 2 +- mips-lib/examples/mips_jump_merge.rs | 2 +- mips-lib/examples/mips_pipe_example_1.rs | 4 ++-- mips-lib/examples/mips_singel_sycle.rs | 6 +++--- 7 files changed, 10 insertions(+), 11 deletions(-) rename mips-lib/examples/{full_adder.rs => mips_alu.rs} (96%) diff --git a/mips-lib/examples/full_adder.rs b/mips-lib/examples/mips_alu.rs similarity index 96% rename from mips-lib/examples/full_adder.rs rename to mips-lib/examples/mips_alu.rs index b5c2151e..6c12b85e 100644 --- a/mips-lib/examples/full_adder.rs +++ b/mips-lib/examples/mips_alu.rs @@ -1,8 +1,8 @@ use mips_lib::components::*; use std::path::PathBuf; +use syncrim::autowire::autowire; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; -use syncrim::mips_helper_functions::autowire; use syncrim::{ common::{ComponentStore, Input}, components::*, @@ -13,7 +13,7 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - FullAdd::rc_new( + ALU::rc_new( "full_adder", (200.0, 120.0), Input::new("c0", "out"), diff --git a/mips-lib/examples/mips_controll_unit.rs b/mips-lib/examples/mips_controll_unit.rs index 9e743616..9d20d07e 100644 --- a/mips-lib/examples/mips_controll_unit.rs +++ b/mips-lib/examples/mips_controll_unit.rs @@ -1,9 +1,9 @@ use mips_lib::components::*; use std::path::PathBuf; use std::rc::Rc; +use syncrim::autowire::autowire; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; -use syncrim::mips_helper_functions::autowire; use syncrim::{ common::{ComponentStore, Input}, components::*, diff --git a/mips-lib/examples/mips_im_dm_regfile.rs b/mips-lib/examples/mips_im_dm_regfile.rs index 2eeb7b96..abdbef19 100644 --- a/mips-lib/examples/mips_im_dm_regfile.rs +++ b/mips-lib/examples/mips_im_dm_regfile.rs @@ -1,5 +1,4 @@ use mips_lib::components::*; -use std::cell::RefCell; use std::path::PathBuf; use std::rc::Rc; #[cfg(feature = "gui-egui")] diff --git a/mips-lib/examples/mips_instruction_splitter.rs b/mips-lib/examples/mips_instruction_splitter.rs index 9741c22e..d404d23a 100644 --- a/mips-lib/examples/mips_instruction_splitter.rs +++ b/mips-lib/examples/mips_instruction_splitter.rs @@ -1,8 +1,8 @@ use mips_lib::components::*; use std::path::PathBuf; +use syncrim::autowire::autowire; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; -use syncrim::mips_helper_functions::autowire; use syncrim::{ common::{ComponentStore, Input}, components::*, diff --git a/mips-lib/examples/mips_jump_merge.rs b/mips-lib/examples/mips_jump_merge.rs index 129fcf8f..182d07ce 100644 --- a/mips-lib/examples/mips_jump_merge.rs +++ b/mips-lib/examples/mips_jump_merge.rs @@ -1,8 +1,8 @@ use mips_lib::components::*; use std::path::PathBuf; +use syncrim::autowire::autowire; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; -use syncrim::mips_helper_functions::autowire; use syncrim::{ common::{ComponentStore, Input}, components::*, diff --git a/mips-lib/examples/mips_pipe_example_1.rs b/mips-lib/examples/mips_pipe_example_1.rs index 1bf8d94a..1bfbcfd7 100644 --- a/mips-lib/examples/mips_pipe_example_1.rs +++ b/mips-lib/examples/mips_pipe_example_1.rs @@ -5,10 +5,10 @@ use std::rc::Rc; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ + autowire::autowire, common::{ComponentStore, Input}, components::*, fern::fern_setup, - mips_helper_functions::autowire, }; fn main() { @@ -303,7 +303,7 @@ fn main() { // // // - FullAdd::rc_new( + ALU::rc_new( "alu", (720.0, 220.0), Input::new("mux_source_a", MUX_OUT_ID), diff --git a/mips-lib/examples/mips_singel_sycle.rs b/mips-lib/examples/mips_singel_sycle.rs index 73e1c3a7..d9951e79 100644 --- a/mips-lib/examples/mips_singel_sycle.rs +++ b/mips-lib/examples/mips_singel_sycle.rs @@ -1,13 +1,13 @@ // use crate::src::components::cntr_unit_signals; use mips_lib::components::*; +use std::path::PathBuf; use std::rc::Rc; -use std::{cell::RefCell, path::PathBuf}; use syncrim::gui_egui::editor::Library; use syncrim::{ + autowire::autowire, common::{ComponentStore, Input}, components::*, fern::fern_setup, - mips_helper_functions::autowire, }; fn main() { @@ -139,7 +139,7 @@ fn main() { ), // // - FullAdd::rc_new( + ALU::rc_new( "alu", (720.0, 225.0), Input::new("mux_source_a", MUX_OUT_ID), From 2cd13790ee752770107e19fe795aff12e4566102 Mon Sep 17 00:00:00 2001 From: malco <56635871+salon64@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:40:57 +0200 Subject: [PATCH 111/126] fixed names of functions and files --- .vscode/settings.json | 3 +-- examples/clk.rs | 2 +- .../src/components/{full_adder.rs => mips_alu.rs} | 14 +++++++------- mips-lib/src/components/mod.rs | 4 ++-- mips-lib/src/gui_egui/components/full_adder.rs | 6 +++--- src/{mips_helper_functions.rs => autowire.rs} | 1 + src/lib.rs | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) rename mips-lib/src/components/{full_adder.rs => mips_alu.rs} (97%) rename src/{mips_helper_functions.rs => autowire.rs} (92%) diff --git a/.vscode/settings.json b/.vscode/settings.json index 2f25db43..933a85b1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,8 @@ { "json.schemaDownload.enable": true, "rust-analyzer.linkedProjects": [ - // "./mips-lib/Cargo.toml", + "./mips-lib/Cargo.toml", // "./Cargo.toml", - "./mips-simple/Cargo.toml" ], "cSpell.ignoreWords": [ "Clippy", diff --git a/examples/clk.rs b/examples/clk.rs index b3dd3baa..7b6a7fec 100644 --- a/examples/clk.rs +++ b/examples/clk.rs @@ -2,10 +2,10 @@ use std::path::PathBuf; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ + autowire::autowire, common::{ComponentStore, Input}, components::*, fern::fern_setup, - mips_helper_functions::autowire, }; fn main() { diff --git a/mips-lib/src/components/full_adder.rs b/mips-lib/src/components/mips_alu.rs similarity index 97% rename from mips-lib/src/components/full_adder.rs rename to mips-lib/src/components/mips_alu.rs index 6833b736..3eca9d7a 100644 --- a/mips-lib/src/components/full_adder.rs +++ b/mips-lib/src/components/mips_alu.rs @@ -33,7 +33,7 @@ pub mod alu_op { } #[derive(Serialize, Deserialize, Clone)] -pub struct FullAdd { +pub struct ALU { pub(crate) id: Id, pub(crate) pos: (f32, f32), pub(crate) a_in: Input, @@ -42,14 +42,14 @@ pub struct FullAdd { } #[typetag::serde] -impl Component for FullAdd { +impl Component for ALU { fn to_(&self) { trace!("full_adder"); } #[cfg(feature = "gui-egui")] fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { let dummy_input = Input::new("dummy", "out"); - Box::new(Rc::new(FullAdd { + Box::new(Rc::new(ALU { id: "dummy".to_string(), pos: (0.0, 0.0), a_in: dummy_input.clone(), @@ -184,9 +184,9 @@ impl Component for FullAdd { } } -impl FullAdd { +impl ALU { pub fn new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input, op_in: Input) -> Self { - FullAdd { + ALU { id: id.to_string(), pos, a_in, @@ -196,7 +196,7 @@ impl FullAdd { } pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input, op_in: Input) -> Rc { - Rc::new(FullAdd::new(id, pos, a_in, b_in, op_in)) + Rc::new(ALU::new(id, pos, a_in, b_in, op_in)) } } #[cfg(test)] @@ -216,7 +216,7 @@ mod test { Rc::new(ProbeOut::new("op")), Rc::new(ProbeOut::new("a")), Rc::new(ProbeOut::new("b")), - FullAdd::rc_new( + ALU::rc_new( "ALU", (0.0, 0.0), Input::new("a", "out"), diff --git a/mips-lib/src/components/mod.rs b/mips-lib/src/components/mod.rs index 406a81de..95d9675a 100644 --- a/mips-lib/src/components/mod.rs +++ b/mips-lib/src/components/mod.rs @@ -1,4 +1,4 @@ -mod full_adder; +mod mips_alu; mod mips_branch_logic; mod mips_control_unit; mod mips_dm; @@ -9,7 +9,7 @@ mod mips_reg_file; mod physical_mem; mod sz_extend; -pub use full_adder::*; +pub use mips_alu::*; pub use mips_branch_logic::*; pub use mips_control_unit::*; pub use mips_dm::*; diff --git a/mips-lib/src/gui_egui/components/full_adder.rs b/mips-lib/src/gui_egui/components/full_adder.rs index 5a6fbcd8..1e33146e 100644 --- a/mips-lib/src/gui_egui/components/full_adder.rs +++ b/mips-lib/src/gui_egui/components/full_adder.rs @@ -1,5 +1,5 @@ use crate::components::{ - alu_op, FullAdd, FULL_ADD_A_IN_ID, FULL_ADD_B_IN_ID, FULL_ADD_OP_IN_ID, FULL_ADD_OUT_ID, + alu_op, ALU, FULL_ADD_A_IN_ID, FULL_ADD_B_IN_ID, FULL_ADD_OP_IN_ID, FULL_ADD_OUT_ID, FULL_ADD_OVERFLOW_OUT_ID, }; use egui::{ @@ -17,7 +17,7 @@ use syncrim::gui_egui::helper::offset_helper; use syncrim::signal::Id; #[typetag::serde] -impl EguiComponent for FullAdd { +impl EguiComponent for ALU { fn render( &self, ui: &mut Ui, @@ -119,7 +119,7 @@ impl EguiComponent for FullAdd { grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { - let r_vec = FullAdd::render( + let r_vec = ALU::render( self, ui, context, diff --git a/src/mips_helper_functions.rs b/src/autowire.rs similarity index 92% rename from src/mips_helper_functions.rs rename to src/autowire.rs index 8221c478..91aaa179 100644 --- a/src/mips_helper_functions.rs +++ b/src/autowire.rs @@ -3,6 +3,7 @@ use std::rc::Rc; use crate::common::{ComponentStore, EguiComponent, Input}; use crate::components::Wire; +/// Adds a wire component in a straight line from the output port location of the source component to the inut port locaition of the destination component. pub fn autowire(mut cs: ComponentStore) -> ComponentStore { let mut wires: Vec> = vec![]; diff --git a/src/lib.rs b/src/lib.rs index 74a9fa91..e0ee4639 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ +pub mod autowire; pub mod common; pub mod component_store; pub mod fern; -pub mod mips_helper_functions; pub mod signal; pub mod simulator; From e5ea71ebdcde678f25af5e4f50a33b5e0a2acdb5 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Fri, 13 Sep 2024 11:08:21 +0200 Subject: [PATCH 112/126] update mips_single_cycle file with the name changes to components --- mips-lib/mips_singel_cycle.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mips-lib/mips_singel_cycle.json b/mips-lib/mips_singel_cycle.json index e36af0e7..859fa0a6 100644 --- a/mips-lib/mips_singel_cycle.json +++ b/mips-lib/mips_singel_cycle.json @@ -813,7 +813,7 @@ }, { "type": "Wire", - "id": "from control_unit:alu_op to alu:full_add_op_in", + "id": "from control_unit:alu_op to alu:alu_op_in", "pos": [ [ 660.0, @@ -1246,7 +1246,7 @@ }, { "type": "Wire", - "id": "from mux_source_a:mux_out to alu:full_add_a_in", + "id": "from mux_source_a:mux_out to alu:alu_a_in", "pos": [ [ 656.0, @@ -1553,7 +1553,7 @@ }, { "type": "Wire", - "id": "from mux_source_b:mux_out to alu:full_add_b_in", + "id": "from mux_source_b:mux_out to alu:alu_b_in", "pos": [ [ 656.0, @@ -1570,7 +1570,7 @@ } }, { - "type": "FullAdd", + "type": "ALU", "id": "alu", "pos": [ 720.0, @@ -1952,4 +1952,4 @@ } } ] -} \ No newline at end of file +} From fb1daf10970938d42fcacb27462036cd591a1bbf Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Fri, 13 Sep 2024 13:26:20 +0200 Subject: [PATCH 113/126] made load reset simulator --- mips-lib/src/components/physical_mem.rs | 8 +++ mips-lib/src/gui_egui/components/mips_im.rs | 68 +++++++++------------ mips-lib/src/helpers.rs | 13 ++++ mips-lib/src/lib.rs | 2 + 4 files changed, 52 insertions(+), 39 deletions(-) create mode 100644 mips-lib/src/helpers.rs diff --git a/mips-lib/src/components/physical_mem.rs b/mips-lib/src/components/physical_mem.rs index c474fa52..8531842f 100644 --- a/mips-lib/src/components/physical_mem.rs +++ b/mips-lib/src/components/physical_mem.rs @@ -3,6 +3,8 @@ use std::{ any::Any, cell::RefCell, collections::{BTreeMap, HashMap}, + fs, + path::PathBuf, }; use syncrim::{ common::{Component, Ports}, @@ -35,6 +37,12 @@ impl PhysicalMem { cycle: RefCell::default(), } } + + pub fn load_file(&self, path: &PathBuf) { + let data = fs::read(path).unwrap(); + self.mem.replace(MipsMem::from_sections(&data).unwrap()); + self.history.borrow_mut().clear(); + } } #[typetag::serde] diff --git a/mips-lib/src/gui_egui/components/mips_im.rs b/mips-lib/src/gui_egui/components/mips_im.rs index 12dd9313..5fc26218 100644 --- a/mips-lib/src/gui_egui/components/mips_im.rs +++ b/mips-lib/src/gui_egui/components/mips_im.rs @@ -1,16 +1,12 @@ -// use std::borrow::BorrowMut; -// use std::cell::RefCell; -use std::fs; use std::path::PathBuf; use crate::components::InstrMem; -use crate::components::MipsMem; use crate::components::PhysicalMem; use crate::components::RegFile; use crate::components::INSTR_MEM_INSTRUCTION_ID; +use crate::helpers::find_component_with_type; use egui::pos2; use egui::Pos2; -// use crate::gui_egui::mips_mem_view_window::MemViewWindow; use egui::{Rect, Response, RichText, Ui, Vec2}; use syncrim::common::Input; use syncrim::common::{EguiComponent, Id, Ports, Simulator}; @@ -21,6 +17,16 @@ use syncrim::gui_egui::helper::basic_component_gui; const WIDTH: f32 = 120.0; const HEIGHT: f32 = 55.0; +impl InstrMem { + fn update_mem_view_register_values(&self, sim: &Simulator) { + let reg: &RegFile = find_component_with_type(sim, &self.regfile_id) + .expect(&format!("can't find {} with type Regfile", self.regfile_id)); + self.mem_view + .borrow_mut() + .set_reg_values(reg.registers.borrow().clone()); + } +} + #[typetag::serde] impl EguiComponent for InstrMem { fn render( @@ -68,44 +74,28 @@ impl EguiComponent for InstrMem { // }); }); + // handle mem_window and load of new file if let Some(sim) = &simulator { - let v = &sim.ordered_components; - let comp = v - .into_iter() - .find(|x| x.get_id_ports().0 == self.regfile_id) - .expect(&format!("cant find {} in simulator", self.regfile_id)); - // deref to get &dyn EguiComponent - let comp_any = (*comp).as_any(); - let regfile: &RegFile = comp_any - .downcast_ref() - .expect("can't downcast to physical memory"); - self.mem_view - .borrow_mut() - .set_reg_values(regfile.registers.borrow().clone()); - } + self.update_mem_view_register_values(sim); - if let Some(sim) = &simulator { - let v = &sim.ordered_components; - let comp = v - .into_iter() - .find(|x| x.get_id_ports().0 == self.phys_mem_id) - .expect(&format!("cant find {} in simulator", self.phys_mem_id)); - // deref to get &dyn EguiComponent - let comp_any = (*comp).as_any(); - let phys_mem: &PhysicalMem = comp_any - .downcast_ref() - .expect("can't downcast to physical memory"); - - if let Some(path) = path_option { - let data = fs::read(path).unwrap(); - let _ = phys_mem.mem.replace(MipsMem::from_sections(&data).unwrap()); + let phys_mem: &PhysicalMem = find_component_with_type(sim, &self.phys_mem_id).expect( + &format!("can't find {} with type PhysicalMem", self.regfile_id), + ); + + if let Some(path) = &path_option { + let _ = phys_mem.load_file(path); mem_view_vis = true; }; - // {} to drop RefMut as early as possible - { - let mut mem_view = self.mem_view.borrow_mut(); - mem_view.visible = mem_view_vis; - mem_view.render(ui.ctx(), &*phys_mem.mem.borrow()); + + let mut mem_view = self.mem_view.borrow_mut(); + mem_view.visible = mem_view_vis; + mem_view.render(ui.ctx(), &*phys_mem.mem.borrow()); + } + + // this is done after handle mem_window, because our simulator need to be returned + if let Some(sim) = simulator { + if path_option.is_some() { + sim.reset(); } } diff --git a/mips-lib/src/helpers.rs b/mips-lib/src/helpers.rs new file mode 100644 index 00000000..5208cfec --- /dev/null +++ b/mips-lib/src/helpers.rs @@ -0,0 +1,13 @@ +use syncrim::common::Simulator; + +pub fn find_component_with_type<'a, T: 'static>(sim: &'a Simulator, id: &str) -> Option<&'a T> { + let v = &sim.ordered_components; + let o_comp = v.into_iter().find(|x| x.get_id_ports().0 == id); + if let Some(comp) = o_comp { + // deref to get &dyn EguiComponent + let comp_any = (*comp).as_any(); + comp_any.downcast_ref() + } else { + None + } +} diff --git a/mips-lib/src/lib.rs b/mips-lib/src/lib.rs index b0c0d777..fefacb34 100644 --- a/mips-lib/src/lib.rs +++ b/mips-lib/src/lib.rs @@ -1,3 +1,5 @@ pub mod components; pub mod gui_egui; + +pub mod helpers; From 1fd9019fd93a2b94d7e4b577d1ed380d48ad929a Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Mon, 16 Sep 2024 08:41:43 +0200 Subject: [PATCH 114/126] updated wire hover to only show hover once, and be bold when hovered --- src/gui_egui/components/wire.rs | 43 ++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index abc354b2..e5ae339b 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -80,18 +80,7 @@ impl EguiComponent for Wire { line_vec.push(oh(pos, s, o)); } - ui.painter().add(Shape::line( - line_vec.clone(), - Stroke { - width: scale, - color: Color32::from_rgba_unmultiplied( - self.color_rgba[0], - self.color_rgba[1], - self.color_rgba[2], - self.color_rgba[3], - ), - }, - )); + let mut hovered = false; let mut r: Vec = vec![]; for val in line_vec.windows(2) { @@ -140,17 +129,33 @@ impl EguiComponent for Wire { < TOOLTIP_DISTANCE && clip_rect.contains(cursor) { - egui::containers::popup::show_tooltip_at( - ui.ctx(), - ui.layer_id(), - egui::Id::new(&self.id), - (first_pos + last_pos.to_vec2()) / 2.0, - |ui| basic_on_hover(ui, self, &simulator), - ); + if !hovered { + hovered = true; + egui::containers::popup::show_tooltip_at( + ui.ctx(), + ui.layer_id(), + egui::Id::new(&self.id), + (first_pos + last_pos.to_vec2()) / 2.0, + |ui| basic_on_hover(ui, self, &simulator), + ); + } } }; } + ui.painter().add(Shape::line( + line_vec.clone(), + Stroke { + width: if hovered { scale * 3.0 } else { scale }, + color: Color32::from_rgba_unmultiplied( + self.color_rgba[0], + self.color_rgba[1], + self.color_rgba[2], + self.color_rgba[3], + ), + }, + )); + match editor_mode { EditorMode::Simulator => (), _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), From 121199e1d3e19a1a3f6121564b68ed31e0349d43 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 26 Sep 2024 10:12:09 +0200 Subject: [PATCH 115/126] made autowire dependent on egui feature --- src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index e0ee4639..30025954 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,3 @@ -pub mod autowire; pub mod common; pub mod component_store; pub mod fern; @@ -13,6 +12,8 @@ pub mod components; #[cfg(feature = "gui-vizia")] pub mod gui_vizia; +#[cfg(feature = "gui-egui")] +pub mod autowire; // Egui frontend #[cfg(feature = "gui-egui")] pub mod gui_egui; From 90192d961cf1ad33aebf792d5a8d38fde6e18a51 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 26 Sep 2024 11:12:52 +0200 Subject: [PATCH 116/126] fix conditional compile --- mips-lib/src/components/mips_dm.rs | 8 ++++++++ mips-lib/src/components/mips_im.rs | 9 +++++++++ mips-lib/src/components/mips_reg_file.rs | 14 +------------- mips-lib/src/components/sz_extend.rs | 10 +--------- mips-lib/src/lib.rs | 1 + 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/mips-lib/src/components/mips_dm.rs b/mips-lib/src/components/mips_dm.rs index eafe1eec..27d8f924 100644 --- a/mips-lib/src/components/mips_dm.rs +++ b/mips-lib/src/components/mips_dm.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "gui-egui")] use crate::gui_egui::mips_mem_view_window::MemViewWindow; use core::cell::RefCell; use std::cell::RefMut; @@ -42,6 +43,7 @@ pub struct DataMem { pub write_enable_input: Input, pub phys_mem_id: String, pub regfile_id: String, + #[cfg(feature = "gui-egui")] pub mem_view: RefCell, } @@ -56,6 +58,7 @@ impl DataMem { phys_mem_id: String, regfile_id: String, ) -> Self { + #[cfg(feature = "gui-egui")] let mem_view = MemViewWindow::new(id.clone(), "Data memory view".into()).set_data_view(None); DataMem { @@ -66,6 +69,7 @@ impl DataMem { data_input: data_input, op_input: op_input, write_enable_input: write_enable_input, + #[cfg(feature = "gui-egui")] mem_view: RefCell::new(mem_view), regfile_id: regfile_id, } @@ -215,6 +219,7 @@ impl Component for DataMem { .unwrap(); // update dynamic symbol PC_IM + #[cfg(feature = "gui-egui")] self.mem_view .borrow_mut() .set_dynamic_symbol("DM_ADRS", address); @@ -362,6 +367,7 @@ impl Component for DataMem { Ok(_) => match mem_op { data_op::NO_OP => Ok(()), _ => { + #[cfg(feature = "gui-egui")] if self.mem_view.borrow().is_break_point(&(address & !0b11)) { Err(Condition::Halt(format!( "Read or write at breakpoint address {:#0x}", @@ -370,6 +376,8 @@ impl Component for DataMem { } else { Ok(()) } + #[cfg(not(feature = "gui-egui"))] + Ok(()) } }, Err(_) => ret, diff --git a/mips-lib/src/components/mips_im.rs b/mips-lib/src/components/mips_im.rs index c9947a37..dbb8b86f 100644 --- a/mips-lib/src/components/mips_im.rs +++ b/mips-lib/src/components/mips_im.rs @@ -8,6 +8,7 @@ use syncrim::common::{Component, Condition, Id, Input, InputPort, OutputType, Po use crate::components::physical_mem::{MemOpSize, MipsMem}; use crate::components::RegFile; +#[cfg(feature = "gui-egui")] use crate::gui_egui::mips_mem_view_window::MemViewWindow; use super::PhysicalMem; @@ -24,6 +25,7 @@ pub struct InstrMem { // All components who deal with memory acess this pub phys_mem_id: String, pub regfile_id: String, + #[cfg(feature = "gui-egui")] pub mem_view: RefCell, } @@ -35,6 +37,7 @@ impl InstrMem { phys_mem_id: String, regfile_id: String, ) -> InstrMem { + #[cfg(feature = "gui-egui")] let mem_view = MemViewWindow::new(id.clone(), "instruction memory view".into()).set_code_view(None); InstrMem { @@ -42,6 +45,7 @@ impl InstrMem { pos: pos, pc: pc_input, phys_mem_id: phys_mem_id, + #[cfg(feature = "gui-egui")] mem_view: RefCell::new(mem_view), regfile_id: regfile_id, } @@ -74,6 +78,7 @@ impl Component for InstrMem { pos: pos, pc: dummy_input, phys_mem_id: "dummy".into(), + #[cfg(feature = "gui-egui")] mem_view: RefCell::new(MemViewWindow::new("dummy".into(), "IM dummy".into())), regfile_id: "dummy".into(), })) @@ -123,6 +128,7 @@ impl Component for InstrMem { }; // update dynamic symbol PC_IM + #[cfg(feature = "gui-egui")] self.mem_view.borrow_mut().set_dynamic_symbol("PC_IM", pc); // Get a word at PC with the size of 32bits, read as big endian, @@ -131,10 +137,13 @@ impl Component for InstrMem { Ok(instr) => { simulator.set_out_value(&self.id, INSTR_MEM_INSTRUCTION_ID, instr); // check if pc is at breakpoint + #[cfg(feature = "gui-egui")] match self.mem_view.borrow().is_break_point(&pc) { true => Err(Condition::Halt(format!("Reached breakpoint at {:#0x}", pc))), false => Ok(()), } + #[cfg(not(feature = "gui-egui"))] + Ok(()) } Err(_) => Err(Condition::Error(format!("Unaligned Read, PC = {:#0x}", pc))), } diff --git a/mips-lib/src/components/mips_reg_file.rs b/mips-lib/src/components/mips_reg_file.rs index 3225e5f5..184413c1 100644 --- a/mips-lib/src/components/mips_reg_file.rs +++ b/mips-lib/src/components/mips_reg_file.rs @@ -61,19 +61,7 @@ impl Component for RegFile { fn to_(&self) { trace!("reg_file"); } - #[cfg(feature = "gui-egui")] - // fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { - // let dummy_input = Input::new("dummy", "out"); - // Box::new(Rc::new(RegFile { - // id: "dummy".to_string(), - // pos: (0.0, 0.0), - // a1_in: dummy_input.clone(), - // a2_in: dummy_input.clone(), - // a3_in: dummy_input.clone(), - // wd3_in: dummy_input.clone(), - // we3_in: dummy_input.clone(), - // })) - // } + fn get_id_ports(&self) -> (Id, Ports) { ( self.id.clone(), diff --git a/mips-lib/src/components/sz_extend.rs b/mips-lib/src/components/sz_extend.rs index dfcdf929..69e36bfe 100644 --- a/mips-lib/src/components/sz_extend.rs +++ b/mips-lib/src/components/sz_extend.rs @@ -26,15 +26,7 @@ impl Component for SignZeroExtend { fn to_(&self) { trace!("pc+4"); } - #[cfg(feature = "gui-egui")] - // fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { - // let dummy_input = Input::new("dummy", "out"); - // Box::new(Rc::new(SignZeroExtend { - // id: "dummy".to_string(), - // pos: (0.0, 0.0), - // signzero_extend_in: dummy_input.clone(), - // })) - // } + fn get_id_ports(&self) -> (Id, Ports) { ( self.id.clone(), diff --git a/mips-lib/src/lib.rs b/mips-lib/src/lib.rs index fefacb34..24f68941 100644 --- a/mips-lib/src/lib.rs +++ b/mips-lib/src/lib.rs @@ -1,5 +1,6 @@ pub mod components; +#[cfg(feature = "gui-egui")] pub mod gui_egui; pub mod helpers; From af1bf7684bb9584d934c54cc35f7173b442f02b0 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 26 Sep 2024 11:25:17 +0200 Subject: [PATCH 117/126] Final cfg fix hopefully --- examples/clk.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/clk.rs b/examples/clk.rs index 7b6a7fec..bbf8598e 100644 --- a/examples/clk.rs +++ b/examples/clk.rs @@ -20,7 +20,7 @@ fn main() { // Probe::rc_new("p1", (270.0, 120.0), Input::new("clk", CLK_OUT_ID)), ], }; - + #[cfg(feature = "gui-egui")] let cs = autowire(cs); let path = PathBuf::from("add.json"); From 94fefb0d11fdf92ad94d53604a4f9f4ad009f4b8 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 26 Sep 2024 11:43:51 +0200 Subject: [PATCH 118/126] final final cfg fix --- examples/clk.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/clk.rs b/examples/clk.rs index bbf8598e..5f05c395 100644 --- a/examples/clk.rs +++ b/examples/clk.rs @@ -1,8 +1,9 @@ use std::path::PathBuf; #[cfg(feature = "gui-egui")] +use syncrim::autowire::autowire; +#[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ - autowire::autowire, common::{ComponentStore, Input}, components::*, fern::fern_setup, From 2076e1ba0e3f3962ae8dfdb4b3e0c81690c3996c Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Mon, 30 Sep 2024 10:56:42 +0200 Subject: [PATCH 119/126] final? --- examples/clk.rs | 13 +++++++------ mips-lib/examples/mips_alu.rs | 12 +++++++----- mips-lib/examples/mips_controll_unit.rs | 13 +++++++------ mips-lib/examples/mips_instruction_splitter.rs | 10 ++++++---- mips-lib/examples/mips_jump_merge.rs | 11 +++++++---- mips-lib/examples/mips_pipe_example_1.rs | 12 +++++++----- mips-lib/examples/mips_singel_sycle.rs | 12 +++++++----- 7 files changed, 48 insertions(+), 35 deletions(-) diff --git a/examples/clk.rs b/examples/clk.rs index 5f05c395..79707f1a 100644 --- a/examples/clk.rs +++ b/examples/clk.rs @@ -1,7 +1,5 @@ use std::path::PathBuf; #[cfg(feature = "gui-egui")] -use syncrim::autowire::autowire; -#[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ common::{ComponentStore, Input}, @@ -21,14 +19,17 @@ fn main() { // Probe::rc_new("p1", (270.0, 120.0), Input::new("clk", CLK_OUT_ID)), ], }; - #[cfg(feature = "gui-egui")] - let cs = autowire(cs); - let path = PathBuf::from("add.json"); + let path = PathBuf::from("clk.json"); cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + { + use syncrim::autowire::autowire; + let cs = autowire(cs); + cs.save_file(&path); + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + } #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); diff --git a/mips-lib/examples/mips_alu.rs b/mips-lib/examples/mips_alu.rs index 6c12b85e..125a5d8a 100644 --- a/mips-lib/examples/mips_alu.rs +++ b/mips-lib/examples/mips_alu.rs @@ -1,6 +1,5 @@ use mips_lib::components::*; use std::path::PathBuf; -use syncrim::autowire::autowire; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ @@ -54,13 +53,16 @@ fn main() { ], }; - let cs = autowire(cs); - - let path = PathBuf::from("add.json"); + let path = PathBuf::from("alu.json"); cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + { + use syncrim::autowire::autowire; + let cs = autowire(cs); + cs.save_file(&path); + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + } #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); diff --git a/mips-lib/examples/mips_controll_unit.rs b/mips-lib/examples/mips_controll_unit.rs index 9d20d07e..fd7cb951 100644 --- a/mips-lib/examples/mips_controll_unit.rs +++ b/mips-lib/examples/mips_controll_unit.rs @@ -1,7 +1,6 @@ use mips_lib::components::*; use std::path::PathBuf; use std::rc::Rc; -use syncrim::autowire::autowire; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ @@ -63,14 +62,16 @@ fn main() { ), ], }; - - let cs = autowire(cs); - - let path = PathBuf::from("add.json"); + let path = PathBuf::from("cntr_unit.json"); cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + { + use syncrim::autowire::autowire; + let cs = autowire(cs); + cs.save_file(&path); + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + } #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); diff --git a/mips-lib/examples/mips_instruction_splitter.rs b/mips-lib/examples/mips_instruction_splitter.rs index d404d23a..04086b19 100644 --- a/mips-lib/examples/mips_instruction_splitter.rs +++ b/mips-lib/examples/mips_instruction_splitter.rs @@ -1,6 +1,5 @@ use mips_lib::components::*; use std::path::PathBuf; -use syncrim::autowire::autowire; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ @@ -61,13 +60,16 @@ fn main() { ], }; - let cs = autowire(cs); - let path = PathBuf::from("add.json"); cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + { + use syncrim::autowire::autowire; + let cs = autowire(cs); + cs.save_file(&path); + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + } #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); diff --git a/mips-lib/examples/mips_jump_merge.rs b/mips-lib/examples/mips_jump_merge.rs index 182d07ce..53727528 100644 --- a/mips-lib/examples/mips_jump_merge.rs +++ b/mips-lib/examples/mips_jump_merge.rs @@ -1,6 +1,6 @@ use mips_lib::components::*; use std::path::PathBuf; -use syncrim::autowire::autowire; + #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ @@ -27,13 +27,16 @@ fn main() { ], }; - let cs = autowire(cs); - let path = PathBuf::from("add.json"); cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + { + use syncrim::autowire::autowire; + let cs = autowire(cs); + cs.save_file(&path); + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + } #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); diff --git a/mips-lib/examples/mips_pipe_example_1.rs b/mips-lib/examples/mips_pipe_example_1.rs index 1bfbcfd7..b7cbc065 100644 --- a/mips-lib/examples/mips_pipe_example_1.rs +++ b/mips-lib/examples/mips_pipe_example_1.rs @@ -5,7 +5,6 @@ use std::rc::Rc; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ - autowire::autowire, common::{ComponentStore, Input}, components::*, fern::fern_setup, @@ -415,13 +414,16 @@ fn main() { ], }; - let cs = autowire(cs); - - let path = PathBuf::from("add.json"); + let path = PathBuf::from("mips_pipe_ex.json"); cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + { + use syncrim::autowire::autowire; + let cs = autowire(cs); + cs.save_file(&path); + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + } #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); diff --git a/mips-lib/examples/mips_singel_sycle.rs b/mips-lib/examples/mips_singel_sycle.rs index d9951e79..36407957 100644 --- a/mips-lib/examples/mips_singel_sycle.rs +++ b/mips-lib/examples/mips_singel_sycle.rs @@ -4,7 +4,6 @@ use std::path::PathBuf; use std::rc::Rc; use syncrim::gui_egui::editor::Library; use syncrim::{ - autowire::autowire, common::{ComponentStore, Input}, components::*, fern::fern_setup, @@ -229,13 +228,16 @@ fn main() { ], }; - let cs = autowire(cs); - - let path = PathBuf::from("add.json"); + let path = PathBuf::from("mips_single_ex.json"); cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + { + use syncrim::autowire::autowire; + let cs = autowire(cs); + cs.save_file(&path); + syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); + } #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &path); From a6f002ed7acf5ed967fac45369ef1ec6993c9055 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Mon, 30 Sep 2024 11:35:19 +0200 Subject: [PATCH 120/126] I want to be able to run github actions locally instead of pushing each time --- mips-lib/examples/mips_singel_sycle.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/mips-lib/examples/mips_singel_sycle.rs b/mips-lib/examples/mips_singel_sycle.rs index 36407957..5b3fb84c 100644 --- a/mips-lib/examples/mips_singel_sycle.rs +++ b/mips-lib/examples/mips_singel_sycle.rs @@ -2,6 +2,7 @@ use mips_lib::components::*; use std::path::PathBuf; use std::rc::Rc; +#[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; use syncrim::{ common::{ComponentStore, Input}, From 1dad0a303d751c7cbcf5c3018cd9ecd95673d1e4 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Mon, 30 Sep 2024 15:38:05 +0200 Subject: [PATCH 121/126] fixed test error --- mips-lib/src/components/mips_alu.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mips-lib/src/components/mips_alu.rs b/mips-lib/src/components/mips_alu.rs index 3eca9d7a..9a02311f 100644 --- a/mips-lib/src/components/mips_alu.rs +++ b/mips-lib/src/components/mips_alu.rs @@ -201,6 +201,8 @@ impl ALU { } #[cfg(test)] mod test { + use crate::components::cntr_field::ALU_OP_OUT; + use super::*; use std::rc::Rc; @@ -230,7 +232,7 @@ mod test { assert_eq!(simulator.cycle, 1); // outputs - let alu_val = &Input::new("ALU", "out"); + let alu_val = &Input::new("ALU", FULL_ADD_OUT_ID); // reset assert_eq!(simulator.get_input_value(alu_val), (0 + 0).into()); From 10e4fec09681a7675c832f491b3c53440715739e Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Mon, 30 Sep 2024 18:19:36 +0200 Subject: [PATCH 122/126] clippy + rust_doc fix --- mips-lib/src/components/physical_mem.rs | 2 +- mips-lib/src/components/sz_extend.rs | 2 +- mips-lib/src/gui_egui/components/mips_dm.rs | 8 +-- mips-lib/src/gui_egui/components/mips_im.rs | 4 +- .../src/gui_egui/components/mips_reg_file.rs | 4 +- mips-lib/src/gui_egui/mips_mem_view_window.rs | 69 ++++++++----------- mips-lib/src/helpers.rs | 2 +- src/autowire.rs | 5 +- src/components/add.rs | 2 +- src/components/clk.rs | 1 + src/components/mem.rs | 4 +- src/components/sext.rs | 4 +- src/components/shift_left_const.rs | 1 + src/components/zero_extend.rs | 1 + src/gui_egui/components/and.rs | 2 +- src/gui_egui/components/clk.rs | 2 +- src/gui_egui/components/register.rs | 7 +- src/gui_egui/components/wire.rs | 23 ++++--- src/gui_egui/helper.rs | 28 ++++++-- src/simulator.rs | 2 +- 20 files changed, 87 insertions(+), 86 deletions(-) diff --git a/mips-lib/src/components/physical_mem.rs b/mips-lib/src/components/physical_mem.rs index 8531842f..3e9816fd 100644 --- a/mips-lib/src/components/physical_mem.rs +++ b/mips-lib/src/components/physical_mem.rs @@ -115,7 +115,7 @@ impl MemWriteReturn { match self.op_size { MemOpSize::Byte => vec![self.bytes[0]], MemOpSize::Half => vec![self.bytes[0], self.bytes[1]], - MemOpSize::Word => vec![self.bytes[0], self.bytes[1], self.bytes[4], self.bytes[3]], + MemOpSize::Word => vec![self.bytes[0], self.bytes[1], self.bytes[2], self.bytes[3]], } } } diff --git a/mips-lib/src/components/sz_extend.rs b/mips-lib/src/components/sz_extend.rs index 69e36bfe..ceefa121 100644 --- a/mips-lib/src/components/sz_extend.rs +++ b/mips-lib/src/components/sz_extend.rs @@ -71,7 +71,7 @@ impl Component for SignZeroExtend { if ctrl == cntr_unit_signals::EXTEND_SIGNED { if (signal >> 15) == 1 { - signal = signal | 0xffff_0000; + signal |= 0xffff_0000; } } diff --git a/mips-lib/src/gui_egui/components/mips_dm.rs b/mips-lib/src/gui_egui/components/mips_dm.rs index fb5f61ef..1f1524b9 100644 --- a/mips-lib/src/gui_egui/components/mips_dm.rs +++ b/mips-lib/src/gui_egui/components/mips_dm.rs @@ -59,7 +59,7 @@ impl EguiComponent for DataMem { if let Some(sim) = &simulator { let v = &sim.ordered_components; let comp = v - .into_iter() + .iter() .find(|x| x.get_id_ports().0 == self.regfile_id) .expect(&format!("cant find {} in simulator", self.regfile_id)); // deref to get &dyn EguiComponent @@ -69,13 +69,13 @@ impl EguiComponent for DataMem { .expect("can't downcast to physical memory"); self.mem_view .borrow_mut() - .set_reg_values(regfile.registers.borrow().clone()); + .set_reg_values(*regfile.registers.borrow()); } if let Some(sim) = &simulator { let v = &sim.ordered_components; let comp = v - .into_iter() + .iter() .find(|x| x.get_id_ports().0 == self.phys_mem_id) .expect(&format!("cant find {} in simulator", self.phys_mem_id)); // deref to get &dyn EguiComponent @@ -87,7 +87,7 @@ impl EguiComponent for DataMem { { let mut mem_view = self.mem_view.borrow_mut(); mem_view.visible = mem_view_vis; - mem_view.render(ui.ctx(), &*phys_mem.mem.borrow()); + mem_view.render(ui.ctx(), &phys_mem.mem.borrow()); } } // return response from basic component gui diff --git a/mips-lib/src/gui_egui/components/mips_im.rs b/mips-lib/src/gui_egui/components/mips_im.rs index 5fc26218..41a7d310 100644 --- a/mips-lib/src/gui_egui/components/mips_im.rs +++ b/mips-lib/src/gui_egui/components/mips_im.rs @@ -23,7 +23,7 @@ impl InstrMem { .expect(&format!("can't find {} with type Regfile", self.regfile_id)); self.mem_view .borrow_mut() - .set_reg_values(reg.registers.borrow().clone()); + .set_reg_values(*reg.registers.borrow()); } } @@ -89,7 +89,7 @@ impl EguiComponent for InstrMem { let mut mem_view = self.mem_view.borrow_mut(); mem_view.visible = mem_view_vis; - mem_view.render(ui.ctx(), &*phys_mem.mem.borrow()); + mem_view.render(ui.ctx(), &phys_mem.mem.borrow()); } // this is done after handle mem_window, because our simulator need to be returned diff --git a/mips-lib/src/gui_egui/components/mips_reg_file.rs b/mips-lib/src/gui_egui/components/mips_reg_file.rs index 2313561e..b7386909 100644 --- a/mips-lib/src/gui_egui/components/mips_reg_file.rs +++ b/mips-lib/src/gui_egui/components/mips_reg_file.rs @@ -30,7 +30,7 @@ impl EguiComponent for RegFile { ui.label("Register File"); // A toggle button for showing register names - ui.toggle_value(&mut *self.show_reg_names.borrow_mut(), "Show names"); + ui.toggle_value(&mut self.show_reg_names.borrow_mut(), "Show names"); // showing the display format of the register let mut tmp: RegFormat = self.reg_format.borrow().clone(); @@ -83,7 +83,7 @@ impl EguiComponent for RegFile { } .as_str(), ); - str.push_str("\n") + str.push('\n') } // push the string as monospace to the ui diff --git a/mips-lib/src/gui_egui/mips_mem_view_window.rs b/mips-lib/src/gui_egui/mips_mem_view_window.rs index b606746a..32f0b50d 100644 --- a/mips-lib/src/gui_egui/mips_mem_view_window.rs +++ b/mips-lib/src/gui_egui/mips_mem_view_window.rs @@ -136,10 +136,7 @@ impl MemViewWindow { } /// Get the address of a symbol, if no such symbol exist return None pub fn get_dynamic_symbol(&self, symbol: &str) -> Option { - match self.dynamic_symbols.get(symbol) { - Some((adrs, _)) => Some(*adrs), - None => None, - } + self.dynamic_symbols.get(symbol).map(|(adrs, _)| *adrs) } /// This sets the format to hex + mips and if possible goes to the section .text @@ -271,55 +268,43 @@ impl MemViewWindow { }); // Does any PC pointer exists, make them visible in this menu for quick access - if self.dynamic_symbols.get("PC_IM").is_some() - || self.dynamic_symbols.get("PC_DE").is_some() - || self.dynamic_symbols.get("PC_EX").is_some() - || self.dynamic_symbols.get("PC_DM").is_some() + if self.dynamic_symbols.contains_key("PC_IM") + || self.dynamic_symbols.contains_key("PC_DE") + || self.dynamic_symbols.contains_key("PC_EX") + || self.dynamic_symbols.contains_key("PC_DM") { ui.separator(); - match self.dynamic_symbols.get("PC_IM") { - Some((adrs, _)) => { - if ui.button(format!("PC_IM ({:#0x})", adrs)).clicked() { - self.go_to_address = set_address(&self.go_type, *adrs); - ui.close_menu(); - close_menu = true; - } + if let Some((adrs, _)) = self.dynamic_symbols.get("PC_IM") { + if ui.button(format!("PC_IM ({:#0x})", adrs)).clicked() { + self.go_to_address = set_address(&self.go_type, *adrs); + ui.close_menu(); + close_menu = true; } - None => {} } - match self.dynamic_symbols.get("PC_DE") { - Some((adrs, _)) => { - if ui.button(format!("PC_DE ({:#0x})", adrs)).clicked() { - self.go_to_address = set_address(&self.go_type, *adrs); - ui.close_menu(); - close_menu = true; - } + if let Some((adrs, _)) = self.dynamic_symbols.get("PC_DE") { + if ui.button(format!("PC_DE ({:#0x})", adrs)).clicked() { + self.go_to_address = set_address(&self.go_type, *adrs); + ui.close_menu(); + close_menu = true; } - None => {} } - match self.dynamic_symbols.get("PC_EX") { - Some((adrs, _)) => { - if ui.button(format!("PC_EX ({:#0x})", adrs)).clicked() { - self.go_to_address = set_address(&self.go_type, *adrs); - ui.close_menu(); - close_menu = true; - } + if let Some((adrs, _)) = self.dynamic_symbols.get("PC_EX") { + if ui.button(format!("PC_EX ({:#0x})", adrs)).clicked() { + self.go_to_address = set_address(&self.go_type, *adrs); + ui.close_menu(); + close_menu = true; } - None => {} } - match self.dynamic_symbols.get("PC_DM") { - Some((adrs, _)) => { - if ui.button(format!("PC_DM ({:#0x})", adrs)).clicked() { - self.go_to_address = set_address(&self.go_type, *adrs); - ui.close_menu(); - close_menu = true; - } + if let Some((adrs, _)) = self.dynamic_symbols.get("PC_DM") { + if ui.button(format!("PC_DM ({:#0x})", adrs)).clicked() { + self.go_to_address = set_address(&self.go_type, *adrs); + ui.close_menu(); + close_menu = true; } - None => {} } } @@ -408,7 +393,7 @@ impl MemViewWindow { ui.menu_button("Show", |ui| { ui.checkbox(&mut self.show_settings.symbols, "Symbols"); ui.checkbox(&mut self.show_settings.sections, "Sections"); - if let Some(_) = &self.register_values { + if self.register_values.is_some() { ui.separator(); ui.checkbox(&mut self.show_settings.registers[28], "Global Pointer"); @@ -598,7 +583,7 @@ impl MemViewWindow { .iter() .filter(|(_name, (sym_adrs, vis))| sym_adrs == adrs && *vis) { - out_vec.push(&name) + out_vec.push(name) } if self.show_settings.sections && sect.contains_key(adrs) { out_vec.push(sect.get(adrs).unwrap()) diff --git a/mips-lib/src/helpers.rs b/mips-lib/src/helpers.rs index 5208cfec..2274d87e 100644 --- a/mips-lib/src/helpers.rs +++ b/mips-lib/src/helpers.rs @@ -2,7 +2,7 @@ use syncrim::common::Simulator; pub fn find_component_with_type<'a, T: 'static>(sim: &'a Simulator, id: &str) -> Option<&'a T> { let v = &sim.ordered_components; - let o_comp = v.into_iter().find(|x| x.get_id_ports().0 == id); + let o_comp = v.iter().find(|x| x.get_id_ports().0 == id); if let Some(comp) = o_comp { // deref to get &dyn EguiComponent let comp_any = (*comp).as_any(); diff --git a/src/autowire.rs b/src/autowire.rs index 91aaa179..99872a12 100644 --- a/src/autowire.rs +++ b/src/autowire.rs @@ -19,8 +19,7 @@ pub fn autowire(mut cs: ComponentStore) -> ComponentStore { let source_component = cs .store .iter() - .filter(|comp| comp.get_id_ports().0 == source_port.id) // compare id - .next() + .find(|comp| comp.get_id_ports().0 == source_port.id) .expect(&format!("can't find comonent with id {}", source_port.id)); // create wire with correct source destination and positions @@ -45,5 +44,5 @@ pub fn autowire(mut cs: ComponentStore) -> ComponentStore { } } cs.store.append(&mut wires); - return cs; + cs } diff --git a/src/components/add.rs b/src/components/add.rs index 302eba64..64ae84e3 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -171,7 +171,7 @@ mod test { assert_eq!(simulator.cycle, 1); // outputs - let add_val = &Input::new("add", "out"); + let add_val = &Input::new("add", ADD_OUT_ID); let add_overflow = &Input::new("add", "overflow"); // reset diff --git a/src/components/clk.rs b/src/components/clk.rs index a0ae9f71..dad46d2d 100644 --- a/src/components/clk.rs +++ b/src/components/clk.rs @@ -48,6 +48,7 @@ impl Component for MIPSCLK { ) } + #[allow(clippy::single_match)] fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { match target_port_id.as_str() { CLK_IN_ID => self.clk_in = new_input, diff --git a/src/components/mem.rs b/src/components/mem.rs index 6aa300f4..11bcbd16 100644 --- a/src/components/mem.rs +++ b/src/components/mem.rs @@ -136,7 +136,7 @@ impl Memory { Memory(Rc::new(RefCell::new(data))) } - /// Aligns a memory address to the size + /// is one if addres is unaligend, and zero if it is. /// # Example /// ``` /// use syncrim::components::Memory; @@ -145,7 +145,7 @@ impl Memory { /// let mem = Memory::default(); // creates a memory with only zeros /// /// let align_adrs = mem.align(0xa3f5, 4); - /// assert_eq!(SignalValue::from(0xa3f4), align_adrs) + /// assert_eq!(SignalValue::from(1), align_adrs) /// ``` pub fn align(&self, addr: usize, size: usize) -> SignalValue { ((addr % size != 0) as SignalUnsigned).into() diff --git a/src/components/sext.rs b/src/components/sext.rs index 60636285..2727c6af 100644 --- a/src/components/sext.rs +++ b/src/components/sext.rs @@ -150,8 +150,8 @@ mod test { assert_eq!(simulator.cycle, 1); // outputs - let sext32_out = &Input::new("sext32", "out"); - let sext16_out = &Input::new("sext16", "out"); + let sext32_out = &Input::new("sext32", SEXT_OUT_ID); + let sext16_out = &Input::new("sext16", SEXT_OUT_ID); // reset assert_eq!(simulator.get_input_value(sext32_out), 0.into()); diff --git a/src/components/shift_left_const.rs b/src/components/shift_left_const.rs index 6b621ec5..fdea867e 100644 --- a/src/components/shift_left_const.rs +++ b/src/components/shift_left_const.rs @@ -50,6 +50,7 @@ impl Component for ShiftConst { ) } + #[allow(clippy::single_match)] fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { match target_port_id.as_str() { SHIFT_SIGNAL_IN_ID => self.signal_in = new_input, diff --git a/src/components/zero_extend.rs b/src/components/zero_extend.rs index 3e1ef677..3d33a8db 100644 --- a/src/components/zero_extend.rs +++ b/src/components/zero_extend.rs @@ -48,6 +48,7 @@ impl Component for ZeroExtend { ) } + #[allow(clippy::single_match)] fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { match target_port_id.as_str() { ZEROEXTEND_SIGNAL_IN_ID => self.signal_in = new_input, diff --git a/src/gui_egui/components/and.rs b/src/gui_egui/components/and.rs index 9966ef1e..3c0fd900 100644 --- a/src/gui_egui/components/and.rs +++ b/src/gui_egui/components/and.rs @@ -3,7 +3,7 @@ use crate::components::{And, AND_A_IN_ID, AND_B_IN_ID, AND_OUT_ID}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::basic_component_gui; -use egui::{pos2, Pos2, Rect, Response, Ui, Vec2}; +use egui::{pos2, Rect, Response, Ui, Vec2}; #[typetag::serde] impl EguiComponent for And { diff --git a/src/gui_egui/components/clk.rs b/src/gui_egui/components/clk.rs index f820c136..f696d0a1 100644 --- a/src/gui_egui/components/clk.rs +++ b/src/gui_egui/components/clk.rs @@ -61,7 +61,7 @@ impl EguiComponent for MIPSCLK { Ok(data) => s += &format!("{:#x}", data), _ => s += &format!("{:?}", clk_r), } - format!("{}", s) + s.to_string() }); ui.label("pc+4"); } diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index 1b50a424..5707f42b 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -1,5 +1,4 @@ -use crate::common::{self, EguiComponent, Input, Ports, SignalUnsigned, Simulator}; -use crate::component_store; +use crate::common::{EguiComponent, Input, Ports, SignalUnsigned, Simulator}; use crate::components::{Register, REGISTER_OUT_ID}; use crate::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, @@ -178,9 +177,7 @@ impl EguiComponent for Register { )); } - println!("{:?} == {:?}\n\n", self.r_in, input); - - return self.get_pos().into(); + None } fn top_padding(&self) -> f32 { diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 8e653f8e..02cef4d0 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -94,6 +94,8 @@ impl EguiComponent for Wire { let first_pos = val[0]; let last_pos = val[1]; let rect = Rect::from_two_pos(first_pos, last_pos).expand(2.5); + + #[allow(clippy::single_match)] match editor_mode { EditorMode::Default => { // why the fuck do i need this much code just to make sure its rendered at the correct layer @@ -135,17 +137,16 @@ impl EguiComponent for Wire { if min_from_line(first_pos.to_vec2(), last_pos.to_vec2(), cursor.to_vec2()) < TOOLTIP_DISTANCE && clip_rect.contains(cursor) + && !hovered { - if !hovered { - hovered = true; - egui::containers::popup::show_tooltip_at( - ui.ctx(), - ui.layer_id(), - egui::Id::new(&self.id), - (first_pos + last_pos.to_vec2()) / 2.0, - |ui| basic_on_hover(ui, self, &simulator), - ); - } + hovered = true; + egui::containers::popup::show_tooltip_at( + ui.ctx(), + ui.layer_id(), + egui::Id::new(&self.id), + (first_pos + last_pos.to_vec2()) / 2.0, + |ui| basic_on_hover(ui, self, &simulator), + ); } }; } @@ -292,7 +293,7 @@ impl EguiComponent for Wire { delete = true; } if ui.button("NEW").clicked() { - to_insert = Some((i, seg_pos.clone())); + to_insert = Some((i, *seg_pos)); } }); i += 1; diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index d4fba37b..fa098a52 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -165,6 +165,23 @@ pub fn component_area( /// out-> 0x00000000 /// /// ``` +/// # use std::any::Any; +/// # use egui::{Ui, Vec2, Rect, Response}; +/// # use syncrim::common::{Ports, EguiComponent, Component, Simulator}; +/// # use syncrim::gui_egui::{EguiExtra, editor::EditorMode}; +/// # use serde::{Deserialize, Serialize}; +/// # #[derive(Serialize, Deserialize, Clone)] +/// # struct JumpMerge {tmp: u32} +/// # impl Component for JumpMerge { +/// # fn get_id_ports(&self) -> (std::string::String, Ports) { todo!() } +/// # fn as_any(&self) -> &(dyn Any + 'static) { todo!() } +/// # fn typetag_name(&self) -> &'static str { todo!() } +/// # fn typetag_deserialize(&self) { todo!() } +/// # } +/// +/// use syncrim::gui_egui::helper::basic_component_gui_with_on_hover; +/// +/// # #[typetag::serde] /// impl EguiComponent for JumpMerge { /// fn render( /// &self, @@ -173,24 +190,23 @@ pub fn component_area( /// simulator: Option<&mut Simulator>, /// offset: Vec2, /// scale: f32, -/// _clip_rect: Rect, +/// clip_rect: Rect, /// _editor_mode: EditorMode, /// ) -> Option> { /// // size of the component /// let width = 100f32; /// let height: f32 = 20f32; -/// basic_component_gui( +/// basic_component_gui_with_on_hover( /// self, -/// &simulator, /// ui.ctx(), -/// (width, height), /// offset, /// scale, +/// clip_rect, /// |ui| { -/// ui.label("Jump Merge")); +/// ui.label("Jump Merge"); /// }, /// |ui| { -/// ui.label("i am hovered") +/// ui.label("i am hovered"); /// }, /// ) /// } diff --git a/src/simulator.rs b/src/simulator.rs index c008128c..036601b4 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -603,6 +603,6 @@ mod test { let simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); - let _ = simulator.get_input_fmt(&Input::new("c", "out")); + let _ = simulator.get_input_fmt(&Input::new("c", CONSTANT_OUT_ID)); } } From d19ff005c6cada6c3a12b9012063ec30e0cd3c5c Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 2 Oct 2024 17:49:31 +0200 Subject: [PATCH 123/126] update default file to mips single cycle --- mips-lib/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mips-lib/src/main.rs b/mips-lib/src/main.rs index ba21d2e8..91b6e1c5 100644 --- a/mips-lib/src/main.rs +++ b/mips-lib/src/main.rs @@ -9,7 +9,7 @@ use syncrim::{common::ComponentStore, fern::fern_setup}; #[command(author, version, about, long_about = None)] struct Args { /// Path to the model to load on startup - #[arg(short, long, default_value = "empty.json")] + #[arg(short, long, default_value = "mips_singel_cycle.json")] model: String, } From 3c77dbf7ddc4bc5016e9541505ee179077ecf897 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Wed, 2 Oct 2024 18:24:35 +0200 Subject: [PATCH 124/126] clippy --- mips-lib/src/components/mips_control_unit.rs | 7 +- mips-lib/src/components/mips_dm.rs | 65 +++++++++---------- mips-lib/src/components/mips_im.rs | 16 ++--- .../components/mips_instruction_splitter.rs | 2 +- mips-lib/src/components/mips_reg_file.rs | 7 +- mips-lib/src/components/physical_mem.rs | 35 +++++----- mips-lib/src/components/sz_extend.rs | 6 +- mips-lib/src/gui_egui/components/mips_dm.rs | 2 + mips-lib/src/gui_egui/components/mips_im.rs | 5 +- .../src/gui_egui/components/physical_mem.rs | 2 +- mips-lib/src/gui_egui/mips_mem_view_window.rs | 25 +++---- mips-lib/src/main.rs | 1 - src/autowire.rs | 1 + src/gui_egui/editor.rs | 1 + 14 files changed, 82 insertions(+), 93 deletions(-) diff --git a/mips-lib/src/components/mips_control_unit.rs b/mips-lib/src/components/mips_control_unit.rs index 999e2155..607a3923 100644 --- a/mips-lib/src/components/mips_control_unit.rs +++ b/mips-lib/src/components/mips_control_unit.rs @@ -224,6 +224,7 @@ impl Component for ControlUnit { } fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + #[allow(clippy::single_match)] match target_port_id.as_str() { cntr_field::INSTR_IN => self.a_in = new_input, _ => {} @@ -632,9 +633,9 @@ impl Component for ControlUnit { // Err(Condition::Error(format!("unknown funct {:#07b}for opcode {:#08b} CP0", cp0_funct, OP_CP0))) // } // } - Err(Condition::Error(format!( - "CP0 instructions not yet implemented" - ))) + Err(Condition::Error( + "CP0 instructions not yet implemented".to_string(), + )) } //TODO use mem_mode, now it assumed data_mem uses opcode to determine that itself OP_LB => { diff --git a/mips-lib/src/components/mips_dm.rs b/mips-lib/src/components/mips_dm.rs index 27d8f924..e18199e3 100644 --- a/mips-lib/src/components/mips_dm.rs +++ b/mips-lib/src/components/mips_dm.rs @@ -4,7 +4,7 @@ use core::cell::RefCell; use std::cell::RefMut; // use log::*; use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, rc::Rc}; +use std::rc::Rc; #[cfg(feature = "gui-egui")] use syncrim::common::EguiComponent; use syncrim::common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}; @@ -48,6 +48,7 @@ pub struct DataMem { } impl DataMem { + #[allow(clippy::too_many_arguments)] pub fn new( id: String, pos: (f32, f32), @@ -62,18 +63,19 @@ impl DataMem { let mem_view = MemViewWindow::new(id.clone(), "Data memory view".into()).set_data_view(None); DataMem { - id: id, - pos: pos, - phys_mem_id: phys_mem_id, - address_input: address_input, - data_input: data_input, - op_input: op_input, - write_enable_input: write_enable_input, + id, + pos, + phys_mem_id, + address_input, + data_input, + op_input, + write_enable_input, #[cfg(feature = "gui-egui")] mem_view: RefCell::new(mem_view), - regfile_id: regfile_id, + regfile_id, } } + #[allow(clippy::too_many_arguments)] pub fn rc_new( id: String, pos: (f32, f32), @@ -101,10 +103,11 @@ impl DataMem { /// /// Panics if This functions panics if phys_mem_id is not found in simulator /// or phys_mem_id is not of type PhysicalMem + #[allow(clippy::expect_fun_call)] fn get_phys_mem<'a>(&self, sim: &'a Simulator) -> &'a PhysicalMem { let v = &sim.ordered_components; let comp = v - .into_iter() + .iter() .find(|x| x.get_id_ports().0 == self.phys_mem_id) .expect(&format!("cant find {} in simulator", self.phys_mem_id)); // deref to get &dyn EguiComponent @@ -195,7 +198,7 @@ impl Component for DataMem { fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { let cycle = simulator.cycle; - self.up_cycle(&simulator); + self.up_cycle(simulator); // get instr at pc/4s let address: u32 = simulator .get_input_value(&self.address_input) @@ -250,7 +253,7 @@ impl Component for DataMem { Ok(()) } data_op::LOAD_BYTE => { - let val = self.get_mut_mem(&simulator).get_unaligned( + let val = self.get_mut_mem(simulator).get_unaligned( address, MemOpSize::Byte, SIGNED, @@ -260,7 +263,7 @@ impl Component for DataMem { Ok(()) } data_op::LOAD_BYTE_U => { - let val = self.get_mut_mem(&simulator).get_unaligned( + let val = self.get_mut_mem(simulator).get_unaligned( address, MemOpSize::Byte, UNSIGNED, @@ -270,9 +273,9 @@ impl Component for DataMem { Ok(()) } data_op::LOAD_HALF => { - let l_ret = - self.get_mut_mem(&simulator) - .get(address, MemOpSize::Half, SIGNED, true); + let l_ret = self + .get_mut_mem(simulator) + .get(address, MemOpSize::Half, SIGNED, true); match l_ret { Ok(val) => { simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, val); @@ -286,7 +289,7 @@ impl Component for DataMem { } data_op::LOAD_HALF_U => { let l_ret = - self.get_mut_mem(&simulator) + self.get_mut_mem(simulator) .get(address, MemOpSize::Half, UNSIGNED, true); match l_ret { Ok(val) => { @@ -301,7 +304,7 @@ impl Component for DataMem { } data_op::LOAD_WORD => { let l_ret = - self.get_mut_mem(&simulator) + self.get_mut_mem(simulator) .get(address, MemOpSize::Word, UNSIGNED, true); match l_ret { Ok(val) => { @@ -316,22 +319,19 @@ impl Component for DataMem { } data_op::STORE_BYTE => { let ret = self - .get_mut_mem(&simulator) + .get_mut_mem(simulator) .write(address, data, MemOpSize::Byte, true); - self.up_hist(&simulator, ret, cycle); + self.up_hist(simulator, ret, cycle); simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); Ok(()) } data_op::STORE_HALF => { - let w_ret = self.get_mut_mem(&simulator).write_aligned( - address, - data, - MemOpSize::Half, - true, - ); + let w_ret = + self.get_mut_mem(simulator) + .write_aligned(address, data, MemOpSize::Half, true); match w_ret { Ok(ret) => { - self.up_hist(&simulator, ret, cycle); + self.up_hist(simulator, ret, cycle); simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); Ok(()) } @@ -342,15 +342,12 @@ impl Component for DataMem { } } data_op::STORE_WORD => { - let w_ret = self.get_mut_mem(&simulator).write_aligned( - address, - data, - MemOpSize::Word, - true, - ); + let w_ret = + self.get_mut_mem(simulator) + .write_aligned(address, data, MemOpSize::Word, true); match w_ret { Ok(ret) => { - self.up_hist(&simulator, ret, cycle); + self.up_hist(simulator, ret, cycle); simulator.set_out_value(&self.id, DATA_MEM_READ_DATA_OUT_ID, 0); Ok(()) } diff --git a/mips-lib/src/components/mips_im.rs b/mips-lib/src/components/mips_im.rs index dbb8b86f..3c484d98 100644 --- a/mips-lib/src/components/mips_im.rs +++ b/mips-lib/src/components/mips_im.rs @@ -6,8 +6,7 @@ use std::rc::Rc; use syncrim::common::EguiComponent; use syncrim::common::{Component, Condition, Id, Input, InputPort, OutputType, Ports, Simulator}; -use crate::components::physical_mem::{MemOpSize, MipsMem}; -use crate::components::RegFile; +use crate::components::physical_mem::MemOpSize; #[cfg(feature = "gui-egui")] use crate::gui_egui::mips_mem_view_window::MemViewWindow; @@ -41,13 +40,13 @@ impl InstrMem { let mem_view = MemViewWindow::new(id.clone(), "instruction memory view".into()).set_code_view(None); InstrMem { - id: id, - pos: pos, + id, + pos, pc: pc_input, - phys_mem_id: phys_mem_id, + phys_mem_id, #[cfg(feature = "gui-egui")] mem_view: RefCell::new(mem_view), - regfile_id: regfile_id, + regfile_id, } } pub fn rc_new( @@ -75,7 +74,7 @@ impl Component for InstrMem { let dummy_input = Input::new("dummy", "out"); Box::new(Rc::new(InstrMem { id: id.into(), - pos: pos, + pos, pc: dummy_input, phys_mem_id: "dummy".into(), #[cfg(feature = "gui-egui")] @@ -109,10 +108,11 @@ impl Component for InstrMem { let pc: u32 = simulator.get_input_value(&self.pc).try_into().unwrap(); // this is inside a {} to make sure our simulator borrow is returned before its used to set signal + #[allow(clippy::expect_fun_call)] let option_instr = { let v = &simulator.ordered_components; let comp = v - .into_iter() + .iter() .find(|x| x.get_id_ports().0 == self.phys_mem_id) .expect(&format!("cant find {} in simulator", self.phys_mem_id)); // deref to get Rc diff --git a/mips-lib/src/components/mips_instruction_splitter.rs b/mips-lib/src/components/mips_instruction_splitter.rs index f23bd7fd..84787486 100644 --- a/mips-lib/src/components/mips_instruction_splitter.rs +++ b/mips-lib/src/components/mips_instruction_splitter.rs @@ -63,8 +63,8 @@ impl Component for InstrSplit { ), ) } - fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + #[allow(clippy::single_match)] match target_port_id.as_str() { INSTRUCTION_SPLITTER_IN_ID => self.instruction_in = new_input, _ => {} diff --git a/mips-lib/src/components/mips_reg_file.rs b/mips-lib/src/components/mips_reg_file.rs index 184413c1..c38cb0d2 100644 --- a/mips-lib/src/components/mips_reg_file.rs +++ b/mips-lib/src/components/mips_reg_file.rs @@ -137,12 +137,7 @@ impl Component for RegFile { //save value to history before write, no need for {} as borrows is dropped after operation? self.history.borrow_mut().push(RegOp { addr: w_addr as u8, - data: self - .registers - .borrow() - .get(w_addr as usize) - .unwrap() - .clone(), + data: *self.registers.borrow().get(w_addr).unwrap(), }); // write data diff --git a/mips-lib/src/components/physical_mem.rs b/mips-lib/src/components/physical_mem.rs index 3e9816fd..e81aa7d9 100644 --- a/mips-lib/src/components/physical_mem.rs +++ b/mips-lib/src/components/physical_mem.rs @@ -31,7 +31,7 @@ impl PhysicalMem { pub fn new(id: impl Into, pos: (f32, f32)) -> Self { Self { id: id.into(), - pos: pos, + pos, mem: RefCell::default(), history: RefCell::default(), cycle: RefCell::default(), @@ -149,7 +149,7 @@ impl MipsMem { let elf_address = sect.sh_offset; // offset into elf file where data is stored (note inside of elf Segment) let elf_end_address = elf_address + sect.sh_size; // end address of data let sect_data = &elf_bytes[elf_address as usize..elf_end_address as usize]; - for (i, byte) in sect_data.into_iter().enumerate() { + for (i, byte) in sect_data.iter().enumerate() { mem.data.insert(v_address + i as u32, byte.to_owned()); } }; @@ -211,7 +211,9 @@ impl MipsMem { uint_16 as u32 } } - MemOpSize::Word => { + MemOpSize::Word => + { + #[allow(clippy::collapsible_else_if)] if sign_extend { let int_32 = if big_endian { i32::from_be_bytes(bytes.try_into().unwrap()) @@ -326,24 +328,23 @@ impl MipsMem { /// Gets the elf symbol table, and set the self hashmap fn get_symbols(&mut self, elf_file: &ElfBytes) { - match elf_file.symbol_table().unwrap() { - Some((sym_table, string_table)) => { - let mut sym_hash_map: HashMap = HashMap::new(); - let mut _hash_map: HashMap = HashMap::new(); + if let Some((sym_table, string_table)) = elf_file.symbol_table().unwrap() { + let mut sym_hash_map: HashMap = HashMap::new(); + let mut _hash_map: HashMap = HashMap::new(); - // for each symbol entry - for sym_entry in sym_table { - let sym_name = string_table.get(sym_entry.st_name as usize).unwrap(); + // for each symbol entry + for sym_entry in sym_table { + let sym_name = string_table.get(sym_entry.st_name as usize).unwrap(); - // if the symbol type is NOTYPE, bind is LOCAL and has a string add it - if sym_entry.st_symtype() == 0x0 && sym_entry.st_bind() == 0x0 && sym_name != "" - { - sym_hash_map.insert(sym_entry.st_value as u32, sym_name.to_string()); - } + // if the symbol type is NOTYPE, bind is LOCAL and has a string add it + if sym_entry.st_symtype() == 0x0 + && sym_entry.st_bind() == 0x0 + && !sym_name.is_empty() + { + sym_hash_map.insert(sym_entry.st_value as u32, sym_name.to_string()); } - self.symbols = sym_hash_map } - None => (), + self.symbols = sym_hash_map } } /// consumes undo the passed related mem write operation diff --git a/mips-lib/src/components/sz_extend.rs b/mips-lib/src/components/sz_extend.rs index ceefa121..a639f4da 100644 --- a/mips-lib/src/components/sz_extend.rs +++ b/mips-lib/src/components/sz_extend.rs @@ -69,10 +69,8 @@ impl Component for SignZeroExtend { .try_into() .unwrap(); - if ctrl == cntr_unit_signals::EXTEND_SIGNED { - if (signal >> 15) == 1 { - signal |= 0xffff_0000; - } + if ctrl == cntr_unit_signals::EXTEND_SIGNED && (signal >> 15) == 1 { + signal |= 0xffff_0000; } simulator.set_out_value(&self.id, SIGNZEROEXTEND_OUT_ID, SignalValue::Data(signal)); diff --git a/mips-lib/src/gui_egui/components/mips_dm.rs b/mips-lib/src/gui_egui/components/mips_dm.rs index 1f1524b9..02d8c0d2 100644 --- a/mips-lib/src/gui_egui/components/mips_dm.rs +++ b/mips-lib/src/gui_egui/components/mips_dm.rs @@ -58,6 +58,7 @@ impl EguiComponent for DataMem { if let Some(sim) = &simulator { let v = &sim.ordered_components; + #[allow(clippy::expect_fun_call)] let comp = v .iter() .find(|x| x.get_id_ports().0 == self.regfile_id) @@ -74,6 +75,7 @@ impl EguiComponent for DataMem { if let Some(sim) = &simulator { let v = &sim.ordered_components; + #[allow(clippy::expect_fun_call)] let comp = v .iter() .find(|x| x.get_id_ports().0 == self.phys_mem_id) diff --git a/mips-lib/src/gui_egui/components/mips_im.rs b/mips-lib/src/gui_egui/components/mips_im.rs index 41a7d310..adaca143 100644 --- a/mips-lib/src/gui_egui/components/mips_im.rs +++ b/mips-lib/src/gui_egui/components/mips_im.rs @@ -19,6 +19,7 @@ const HEIGHT: f32 = 55.0; impl InstrMem { fn update_mem_view_register_values(&self, sim: &Simulator) { + #[allow(clippy::expect_fun_call)] let reg: &RegFile = find_component_with_type(sim, &self.regfile_id) .expect(&format!("can't find {} with type Regfile", self.regfile_id)); self.mem_view @@ -77,13 +78,13 @@ impl EguiComponent for InstrMem { // handle mem_window and load of new file if let Some(sim) = &simulator { self.update_mem_view_register_values(sim); - + #[allow(clippy::expect_fun_call)] let phys_mem: &PhysicalMem = find_component_with_type(sim, &self.phys_mem_id).expect( &format!("can't find {} with type PhysicalMem", self.regfile_id), ); if let Some(path) = &path_option { - let _ = phys_mem.load_file(path); + phys_mem.load_file(path); mem_view_vis = true; }; diff --git a/mips-lib/src/gui_egui/components/physical_mem.rs b/mips-lib/src/gui_egui/components/physical_mem.rs index b88e1229..2763b584 100644 --- a/mips-lib/src/gui_egui/components/physical_mem.rs +++ b/mips-lib/src/gui_egui/components/physical_mem.rs @@ -1,5 +1,5 @@ use crate::components::PhysicalMem; -use egui::{Rect, Response, RichText, Ui, Vec2}; +use egui::{Rect, Response, Ui, Vec2}; use syncrim::common::{EguiComponent, Id, Ports, Simulator}; use syncrim::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use syncrim::gui_egui::gui::EguiExtra; diff --git a/mips-lib/src/gui_egui/mips_mem_view_window.rs b/mips-lib/src/gui_egui/mips_mem_view_window.rs index 32f0b50d..0fa4f661 100644 --- a/mips-lib/src/gui_egui/mips_mem_view_window.rs +++ b/mips-lib/src/gui_egui/mips_mem_view_window.rs @@ -1,11 +1,6 @@ use egui::{RichText, ScrollArea, TextWrapMode, Ui, ViewportBuilder, ViewportId}; -use std::{ - cell::RefCell, - collections::{HashMap, HashSet}, - rc::Rc, -}; +use std::collections::{HashMap, HashSet}; -use crate::components::RegFile; use crate::components::{MemOpSize, MipsMem}; use MIPS_disassembly; @@ -96,8 +91,8 @@ impl MemViewWindow { // creates a new memory view window with id string and the given memory pub fn new(id: String, title: String) -> Self { MemViewWindow { - title: title, - id: id, + title, + id, visible: false, row_offset: 0, max_rows: 1024, @@ -189,7 +184,7 @@ impl MemViewWindow { pub fn render(&mut self, ctx: &egui::Context, mem: &MipsMem) { if !self.visible { - return (); + return; }; ctx.show_viewport_immediate( @@ -436,13 +431,11 @@ impl MemViewWindow { if scroll_area_row == 0 { if self.row_offset == 0 { _ = ui.small_button(more_row_text.clone().strikethrough()); - } else { - if ui.small_button(more_row_text).clicked() { - // 4* to get memory address - // -1 because the button takes up a row - self.go_to_address = GoAddress::Top((self.row_offset - 1) * 4); - }; - } + } else if ui.small_button(more_row_text).clicked() { + // 4* to get memory address + // -1 because the button takes up a row + self.go_to_address = GoAddress::Top((self.row_offset - 1) * 4); + }; } else if scroll_area_row == self.max_rows as usize + 1 { if ui.small_button(more_row_text).clicked() { self.go_to_address = GoAddress::Bottom((self.row_offset + self.max_rows) * 4); diff --git a/mips-lib/src/main.rs b/mips-lib/src/main.rs index 91b6e1c5..5a9e9892 100644 --- a/mips-lib/src/main.rs +++ b/mips-lib/src/main.rs @@ -1,5 +1,4 @@ use clap::Parser; -use mips_lib; use std::path::PathBuf; #[cfg(feature = "gui-egui")] use syncrim::gui_egui::editor::Library; diff --git a/src/autowire.rs b/src/autowire.rs index 99872a12..824b3d1a 100644 --- a/src/autowire.rs +++ b/src/autowire.rs @@ -16,6 +16,7 @@ pub fn autowire(mut cs: ComponentStore) -> ComponentStore { let dest_comp_field = &input_port.port_id; // find component with correct source id + #[allow(clippy::expect_fun_call)] let source_component = cs .store .iter() diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 1363df8b..5ed71b91 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -365,6 +365,7 @@ impl Editor { let old_key = c.as_ref().get_id_ports().0; let mut context = e.contexts.remove(&old_key).unwrap(); let debug_id = c.get_id_ports().0; + #[allow(clippy::expect_fun_call)] let render_return = (*Rc::get_mut(c) .expect(&format!("More than one reference exist to {}, can't get mut, therefore not render editor", debug_id))) .render_editor( From 29d9553782f2cf7fdb8eaa93fe838a1497fda7c9 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 3 Oct 2024 10:56:52 +0200 Subject: [PATCH 125/126] removed commented out code --- examples/mips_mux.rs | 25 ---------------- mips-lib/examples/mips_alu.rs | 23 --------------- mips-lib/examples/mips_im_dm_regfile.rs | 2 -- mips-lib/examples/mips_jump_merge.rs | 3 -- mips-lib/examples/mips_pipe_example_1.rs | 16 ----------- mips-lib/examples/mips_reg_file.rs | 2 -- mips-lib/examples/mips_singel_sycle.rs | 1 - mips-lib/src/components/mips_alu.rs | 1 - mips-lib/src/components/mips_branch_logic.rs | 12 +------- mips-lib/src/components/mips_control_unit.rs | 30 ++------------------ mips-lib/src/components/mips_jump_merge.rs | 12 +------- src/common.rs | 3 -- src/components/shift_left_const.rs | 2 -- src/components/zero_extend.rs | 2 -- 14 files changed, 5 insertions(+), 129 deletions(-) diff --git a/examples/mips_mux.rs b/examples/mips_mux.rs index 93ac11e6..3d7c0e47 100644 --- a/examples/mips_mux.rs +++ b/examples/mips_mux.rs @@ -24,31 +24,6 @@ fn main() { ), Constant::rc_new("c0", (140.0, 170.0), 0), Constant::rc_new("c1", (140.0, 190.0), 1), - // Wire::rc_new( - // "w1", - // vec![(150.0, 170.0), (180.0, 170.0)], - // Input::new("c1", "out"), - // ), - // Wire::rc_new( - // "w2", - // vec![(150.0, 190.0), (180.0, 190.0)], - // Input::new("c2", "out"), - // ), - // Wire::rc_new( - // "w3", - // vec![(150.0, 210.0), (180.0, 210.0)], - // Input::new("c3", "out"), - // ), - // Wire::rc_new( - // "w4", - // vec![(150.0, 230.0), (180.0, 230.0)], - // Input::new("c4", "out"), - // ), - // Wire::rc_new( - // "w5", - // vec![(220.0, 200.0), (250.0, 200.0)], - // Input::new("mux", "out"), - // ), Probe::rc_new("p_mux", (260.0, 200.0), Input::new("mux", "out")), ], }; diff --git a/mips-lib/examples/mips_alu.rs b/mips-lib/examples/mips_alu.rs index 125a5d8a..f1c7a330 100644 --- a/mips-lib/examples/mips_alu.rs +++ b/mips-lib/examples/mips_alu.rs @@ -19,32 +19,9 @@ fn main() { Input::new("c1", "out"), Input::new("c2", "out"), ), - // Constant::rc_new("c0", (60.0, 100.0), 10), - // Constant::rc_new("c1", (60.0, 140.0), 5), - // Constant::rc_new("c2", (60.0, 180.0), 1), ProbeEdit::rc_new("c0", (60.0, 100.0)), ProbeEdit::rc_new("c1", (60.0, 140.0)), ProbeEdit::rc_new("c2", (60.0, 180.0)), - // Wire::rc_new( - // "w1", - // vec![(110.0, 100.0), (180.0, 100.0)], - // Input::new("c0", "out"), - // ), - // Wire::rc_new( - // "w2", - // vec![(110.0, 140.0), (180.0, 140.0)], - // Input::new("c1", "out"), - // ), - // Wire::rc_new( - // "w3", - // vec![(110.0, 180.0), (180.0, 180.0)], - // Input::new("c2", "out"), - // ), - // Wire::rc_new( - // "w4", - // vec![(220.0, 120.0), (260.0, 120.0)], - // Input::new("full_adder", FULL_ADD_OUT_ID), - // ), Probe::rc_new( "p1", (270.0, 120.0), diff --git a/mips-lib/examples/mips_im_dm_regfile.rs b/mips-lib/examples/mips_im_dm_regfile.rs index abdbef19..c02edd52 100644 --- a/mips-lib/examples/mips_im_dm_regfile.rs +++ b/mips-lib/examples/mips_im_dm_regfile.rs @@ -64,8 +64,6 @@ fn main() { ], }; - // let cs = autowire(cs); - let path = PathBuf::from("add.json"); cs.save_file(&path); diff --git a/mips-lib/examples/mips_jump_merge.rs b/mips-lib/examples/mips_jump_merge.rs index 53727528..bb1ac068 100644 --- a/mips-lib/examples/mips_jump_merge.rs +++ b/mips-lib/examples/mips_jump_merge.rs @@ -18,9 +18,6 @@ fn main() { Input::new("c0", "out"), Input::new("c1", "out"), ), - // Constant::rc_new("c0", (60.0, 100.0), 10), - // Constant::rc_new("c1", (60.0, 140.0), 5), - // Constant::rc_new("c2", (60.0, 180.0), 1), ProbeEdit::rc_new("c0", (60.0, 100.0)), ProbeEdit::rc_new("c1", (60.0, 140.0)), Probe::rc_new("p1", (270.0, 120.0), Input::new("jump_merge", MERGE_OUT_ID)), diff --git a/mips-lib/examples/mips_pipe_example_1.rs b/mips-lib/examples/mips_pipe_example_1.rs index b7cbc065..9dc69ee5 100644 --- a/mips-lib/examples/mips_pipe_example_1.rs +++ b/mips-lib/examples/mips_pipe_example_1.rs @@ -1,4 +1,3 @@ -// use crate::src::components::cntr_unit_signals; use mips_lib::components::*; use std::path::PathBuf; use std::rc::Rc; @@ -23,16 +22,6 @@ fn main() { Input::new("control_unit_4", cntr_field::REG_WRITE_ENABLE_OUT), ); - // RegFile::rc_new( - // "reg_file", - // (3100.0, 2000.0), - // Input::new("instruction_split", INSTRUCTION_SPLITTER_RS_ID), - // Input::new("instruction_split", INSTRUCTION_SPLITTER_RT_ID), - // Input::new("reg_addr_reg", REGISTER_OUT_ID), //write address - // Input::new("result_reg_EX", REGISTER_OUT_ID), //write data - // Input::new("control_unit_4", cntr_field::REG_WRITE_ENABLE_OUT), - // ), - let cs = ComponentStore { store: vec![ Rc::new(PhysicalMem::new("phys_mem", (0.0, 0.0))), @@ -405,11 +394,6 @@ fn main() { Input::new("0x_1F", "out"), ], ), - // - // - - // - // rc_reg_file, ], }; diff --git a/mips-lib/examples/mips_reg_file.rs b/mips-lib/examples/mips_reg_file.rs index e65283aa..4b8c28f2 100644 --- a/mips-lib/examples/mips_reg_file.rs +++ b/mips-lib/examples/mips_reg_file.rs @@ -39,8 +39,6 @@ fn main() { ], }; - // let cs = autowire(cs); - let path = PathBuf::from("add.json"); cs.save_file(&path); diff --git a/mips-lib/examples/mips_singel_sycle.rs b/mips-lib/examples/mips_singel_sycle.rs index 5b3fb84c..69d67d4f 100644 --- a/mips-lib/examples/mips_singel_sycle.rs +++ b/mips-lib/examples/mips_singel_sycle.rs @@ -1,4 +1,3 @@ -// use crate::src::components::cntr_unit_signals; use mips_lib::components::*; use std::path::PathBuf; use std::rc::Rc; diff --git a/mips-lib/src/components/mips_alu.rs b/mips-lib/src/components/mips_alu.rs index 9a02311f..469c418b 100644 --- a/mips-lib/src/components/mips_alu.rs +++ b/mips-lib/src/components/mips_alu.rs @@ -1,4 +1,3 @@ -// use std::fmt::Alignment; use log::*; use serde::{Deserialize, Serialize}; use std::any::Any; diff --git a/mips-lib/src/components/mips_branch_logic.rs b/mips-lib/src/components/mips_branch_logic.rs index ef46b2f2..9844ac1a 100644 --- a/mips-lib/src/components/mips_branch_logic.rs +++ b/mips-lib/src/components/mips_branch_logic.rs @@ -37,15 +37,7 @@ impl Component for BranchLogic { fn to_(&self) { trace!("branch_logic"); } - // #[cfg(feature = "gui-egui")] - // fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { - // let dummy_input = Input::new("dummy", "out"); - // Box::new(Rc::new(BranchLogic { - // id: "dummy".to_string(), - // pos: (0.0, 0.0), - // clk_in: dummy_input.clone(), - // })) - // } + fn get_id_ports(&self) -> (Id, Ports) { ( self.id.clone(), @@ -89,8 +81,6 @@ impl Component for BranchLogic { } } - // propagate sign extension to output - // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { // get input values let op: u32 = simulator.get_input_value(&self.op_in).try_into().unwrap(); diff --git a/mips-lib/src/components/mips_control_unit.rs b/mips-lib/src/components/mips_control_unit.rs index 607a3923..19de48ac 100644 --- a/mips-lib/src/components/mips_control_unit.rs +++ b/mips-lib/src/components/mips_control_unit.rs @@ -62,9 +62,6 @@ pub mod cntr_field { // Opcode is passed to branch unit which is responsible to control branch logic // pub const BRANCH_TYPE_OUT: &str = "branch"; - //TODO - // NOTE no mem mode, decided to pass opcode to data mem instead, - // might change when LWL/LWR is implemented along with the load/store controller pub const MEM_MODE_OUT: &str = "mem_mode"; } @@ -614,30 +611,9 @@ impl Component for ControlUnit { set!(cntr_field::ALU_OP_OUT, alu_op::LUI); Ok(()) } - OP_CP0 => { - // let cp0_funct:u32 = (&instr_in >> 21) & 0b11111; - // match cp0_funct { - // CP0_FUNCT_MFC0 =>{ - // set!(cntr_field::REG_DEST_OUT,cntr_unit_signals::REG_DEST_RT); - // set!(cntr_field::REG_WRITE_ENABLE_OUT, cntr_unit_signals::REG_WRITE_ENABLE); - - // //TODO no idea why alu would be required for this operation and cant find any path in syncsim, - // // but following blindly. If time permits figure out why and change - // set!(cntr_field::ALU_OP_OUT, alu_op::ADDU); - // set!(cntr_field::ALU_SRC_A_OUT,cntr_unit_signals::ALU_SRC_A_SHAMT); - // set!(cntr_field::ALU_SRC_B_OUT,cntr_unit_signals::ALU_SRC_B_IMM); - // todo!("implement memory mode to complete MFC0") - - // } - // _ => { - // Err(Condition::Error(format!("unknown funct {:#07b}for opcode {:#08b} CP0", cp0_funct, OP_CP0))) - // } - // } - Err(Condition::Error( - "CP0 instructions not yet implemented".to_string(), - )) - } - //TODO use mem_mode, now it assumed data_mem uses opcode to determine that itself + OP_CP0 => Err(Condition::Error( + "CP0 instructions not yet implemented".to_string(), + )), OP_LB => { set!(cntr_field::MEM_MODE_OUT, data_op::LOAD_BYTE); set_load_instr!(); diff --git a/mips-lib/src/components/mips_jump_merge.rs b/mips-lib/src/components/mips_jump_merge.rs index dcce5b40..2119c65a 100644 --- a/mips-lib/src/components/mips_jump_merge.rs +++ b/mips-lib/src/components/mips_jump_merge.rs @@ -25,15 +25,7 @@ impl Component for JumpMerge { fn to_(&self) { trace!("jump_merge"); } - // #[cfg(feature = "gui-egui")] - // fn dummy(&self, id: &str, pos: (f32, f32)) -> Box> { - // let dummy_input = Input::new("dummy", "out"); - // Box::new(Rc::new(JumpMerge { - // id: "dummy".to_string(), - // pos: (0.0, 0.0), - // clk_in: dummy_input.clone(), - // })) - // } + fn get_id_ports(&self) -> (Id, Ports) { ( self.id.clone(), @@ -62,8 +54,6 @@ impl Component for JumpMerge { } } - // propagate sign extension to output - // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { // get input values let instr_addr: u32 = simulator diff --git a/src/common.rs b/src/common.rs index fe25297e..ac90ca14 100644 --- a/src/common.rs +++ b/src/common.rs @@ -96,9 +96,6 @@ pub trait Component { /// returns the (id, Ports) of the component fn get_id_ports(&self) -> (Id, Ports); - // #default - // fn get_pos(&self) -> (Position); - fn set_id_port(&mut self, _target_port_id: Id, _new_input: Input) { todo!("Set set_id_port for this Component"); } diff --git a/src/components/shift_left_const.rs b/src/components/shift_left_const.rs index fdea867e..37eeee54 100644 --- a/src/components/shift_left_const.rs +++ b/src/components/shift_left_const.rs @@ -58,8 +58,6 @@ impl Component for ShiftConst { } } - // propagate sign extension to output - // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { // get input values let signal_in: u32 = simulator diff --git a/src/components/zero_extend.rs b/src/components/zero_extend.rs index 3d33a8db..b4615ce6 100644 --- a/src/components/zero_extend.rs +++ b/src/components/zero_extend.rs @@ -56,8 +56,6 @@ impl Component for ZeroExtend { } } - // propagate sign extension to output - // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { // get input values let signal_in: u32 = simulator From 1fadfac92d277c0ca8defc5a5deaf9a1c460c578 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 3 Oct 2024 11:07:50 +0200 Subject: [PATCH 126/126] removed unnecessary clk components --- examples/clk.rs | 36 ----- mips-lib/examples/mips_pipe_example_1.rs | 2 +- src/components/clk.rs | 90 ------------- src/components/mod.rs | 2 - src/gui_egui/components/clk.rs | 160 ----------------------- src/gui_egui/components/mod.rs | 1 - src/gui_egui/editor.rs | 5 - 7 files changed, 1 insertion(+), 295 deletions(-) delete mode 100644 examples/clk.rs delete mode 100644 src/components/clk.rs delete mode 100644 src/gui_egui/components/clk.rs diff --git a/examples/clk.rs b/examples/clk.rs deleted file mode 100644 index 79707f1a..00000000 --- a/examples/clk.rs +++ /dev/null @@ -1,36 +0,0 @@ -use std::path::PathBuf; -#[cfg(feature = "gui-egui")] -use syncrim::gui_egui::editor::Library; -use syncrim::{ - common::{ComponentStore, Input}, - components::*, - fern::fern_setup, -}; - -fn main() { - fern_setup(); - let cs = ComponentStore { - store: vec![ - MIPSCLK::rc_new("clk", (200.0, 120.0), Input::new("reg", "out")), - //Constant::rc_new("c1", (60.0, 100.0), 10), - // ProbeEdit::rc_new("c1", (60.0, 100.0)), - Register::rc_new("reg", (150.0, 250.0), Input::new("clk", "out")), - //Register::rc_new("reg2", (250.0, 250.0), Input::new("reg", "reg_out")), - // Probe::rc_new("p1", (270.0, 120.0), Input::new("clk", CLK_OUT_ID)), - ], - }; - - let path = PathBuf::from("clk.json"); - cs.save_file(&path); - - #[cfg(feature = "gui-egui")] - { - use syncrim::autowire::autowire; - let cs = autowire(cs); - cs.save_file(&path); - syncrim::gui_egui::gui(cs, &path, Library::default()).ok(); - } - - #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(cs, &path); -} diff --git a/mips-lib/examples/mips_pipe_example_1.rs b/mips-lib/examples/mips_pipe_example_1.rs index 9dc69ee5..441249bc 100644 --- a/mips-lib/examples/mips_pipe_example_1.rs +++ b/mips-lib/examples/mips_pipe_example_1.rs @@ -55,7 +55,7 @@ fn main() { Input::new("pc_add_branch", ADD_OUT_ID), // describe origin Input::new("reg_file", reg_file_fields::RS_VALUE_OUT_ID), // goes to addr, RD2 Input::new("merge_reg", REGISTER_OUT_ID), // - Input::new("pc+4", CLK_OUT_ID), + Input::new("pc+4", ADD_OUT_ID), ], ), // diff --git a/src/components/clk.rs b/src/components/clk.rs deleted file mode 100644 index dad46d2d..00000000 --- a/src/components/clk.rs +++ /dev/null @@ -1,90 +0,0 @@ -// use std::fmt::Alignment; -#[cfg(feature = "gui-egui")] -use crate::common::EguiComponent; -use crate::common::{ - Component, Condition, Id, Input, InputPort, OutputType, Ports, SignalValue, Simulator, -}; -use log::*; -use serde::{Deserialize, Serialize}; -use std::any::Any; -use std::rc::Rc; - -pub const CLK_IN_ID: &str = "clk_in"; - -pub const CLK_OUT_ID: &str = "out"; - -#[derive(Serialize, Deserialize, Clone)] -pub struct MIPSCLK { - pub(crate) id: Id, - pub(crate) pos: (f32, f32), - pub(crate) clk_in: Input, -} - -#[typetag::serde] -impl Component for MIPSCLK { - fn to_(&self) { - trace!("pc+4"); - } - #[cfg(feature = "gui-egui")] - fn dummy(&self, _id: &str, _pos: (f32, f32)) -> Box> { - let dummy_input = Input::new("dummy", "out"); - Box::new(Rc::new(MIPSCLK { - id: "dummy".to_string(), - pos: (0.0, 0.0), - clk_in: dummy_input.clone(), - })) - } - fn get_id_ports(&self) -> (Id, Ports) { - ( - self.id.clone(), - Ports::new( - vec![&InputPort { - port_id: CLK_IN_ID.to_string(), - input: self.clk_in.clone(), - }], - OutputType::Combinatorial, - vec![CLK_OUT_ID], - ), - ) - } - - #[allow(clippy::single_match)] - fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { - match target_port_id.as_str() { - CLK_IN_ID => self.clk_in = new_input, - _ => {} - } - } - - // propagate sign extension to output - // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) - fn clock(&self, simulator: &mut Simulator) -> Result<(), Condition> { - // get input values - let start_time: u32 = simulator.get_input_value(&self.clk_in).try_into().unwrap(); - - simulator.set_out_value( - &self.id, - CLK_OUT_ID, - SignalValue::Data(start_time.wrapping_add(4)), - ); - Ok(()) - } - - fn as_any(&self) -> &dyn Any { - self - } -} - -impl MIPSCLK { - pub fn new(id: &str, pos: (f32, f32), clk_in: Input) -> Self { - MIPSCLK { - id: id.to_string(), - pos, - clk_in, - } - } - - pub fn rc_new(id: &str, pos: (f32, f32), clk_in: Input) -> Rc { - Rc::new(MIPSCLK::new(id, pos, clk_in)) - } -} diff --git a/src/components/mod.rs b/src/components/mod.rs index 2266d426..53382f69 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,6 +1,5 @@ mod add; mod and; -mod clk; mod constant; mod cross; mod equals; @@ -20,7 +19,6 @@ mod zero_extend; pub use add::*; pub use and::*; -pub use clk::*; pub use constant::*; pub use cross::*; pub use equals::*; diff --git a/src/gui_egui/components/clk.rs b/src/gui_egui/components/clk.rs deleted file mode 100644 index f696d0a1..00000000 --- a/src/gui_egui/components/clk.rs +++ /dev/null @@ -1,160 +0,0 @@ -use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; -use crate::components::MIPSCLK; -use crate::gui_egui::component_ui::{ - drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, - rect_with_hover, visualize_ports, -}; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; -use crate::gui_egui::gui::EguiExtra; -use crate::gui_egui::helper::offset_helper; -use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; - -#[typetag::serde] -impl EguiComponent for MIPSCLK { - fn render( - &self, - ui: &mut Ui, - _context: &mut EguiExtra, - simulator: Option<&mut Simulator>, - offset: Vec2, - scale: f32, - clip_rect: Rect, - editor_mode: EditorMode, - ) -> Option> { - // 81x41 - // middle: 41x 21y (0 0) - let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; - let offset_old = offset; - let mut offset = offset; - offset.x += self.pos.0 * scale; - offset.y += self.pos.1 * scale; - let s = scale; - let o = offset; - // The shape - ui.painter().add(Shape::closed_line( - vec![ - oh((-40f32, 0f32), s, o), - oh((40f32, 0f32), s, o), - oh((40f32, 20f32), s, o), - oh((-40f32, 20f32), s, o), - ], - Stroke { - width: scale, - color: Color32::RED, - }, - )); - - let rect = Rect { - min: oh((-40f32, -20f32), s, o), - max: oh((40f32, 20f32), s, o), - }; - let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { - ui.label(format!("Id: {}", self.id.clone())); - // todo: is this actually correct? - if let Some(s) = &simulator { - ui.label({ - let clk_r: Result = - s.get_input_value(&self.clk_in).try_into(); - let mut s: String = "".to_string(); - - match clk_r { - Ok(data) => s += &format!("{:#x}", data), - _ => s += &format!("{:?}", clk_r), - } - s.to_string() - }); - ui.label("pc+4"); - } - }); - match editor_mode { - EditorMode::Simulator => (), - _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), - } - Some(vec![r]) - } - - fn render_editor( - &mut self, - ui: &mut Ui, - context: &mut EguiExtra, - simulator: Option<&mut Simulator>, - offset: Vec2, - scale: f32, - clip_rect: Rect, - id_ports: &[(crate::common::Id, Ports)], - grid: &GridOptions, - editor_mode: EditorMode, - ) -> EditorRenderReturn { - let r_vec = MIPSCLK::render( - self, - ui, - context, - simulator, - offset, - scale, - clip_rect, - editor_mode, - ) - .unwrap(); - let resp = &r_vec[0]; - let delete = drag_logic( - ui.ctx(), - resp, - &mut self.pos, - &mut context.pos_tmp, - scale, - offset, - grid, - ); - - properties_window( - ui, - self.id.clone(), - resp, - &mut context.properties_window, - |ui| { - let mut clicked_dropdown = false; - input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_drag_value(ui, &mut self.pos); - clicked_dropdown |= input_selector( - ui, - &mut self.clk_in, - crate::components::CLK_IN_ID.to_string(), - id_ports, - self.id.clone(), - ); - clicked_dropdown - }, - ); - EditorRenderReturn { - delete, - resp: Some(r_vec), - } - } - - fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { - let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![ - ( - crate::components::SEXT_IN_ID.to_string(), - Pos2::new(-40f32, 0f32) + own_pos, - ), - ( - crate::components::SEXT_OUT_ID.to_string(), - Pos2::new(40f32, 0f32) + own_pos, - ), - ] - } - - fn top_padding(&self) -> f32 { - 20f32 - } - - fn set_pos(&mut self, pos: (f32, f32)) { - self.pos = pos; - } - - fn get_pos(&self) -> (f32, f32) { - self.pos - } -} diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index cae8832f..6976570d 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -1,6 +1,5 @@ mod add; mod and; -mod clk; mod constant; mod cross; mod equal; diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 5ed71b91..ff1da204 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -135,11 +135,6 @@ impl Default for Library { pos: (0.0, 0.0), r_in: dummy_input.clone(), }), - Rc::new(MIPSCLK { - id: "clk".to_string(), - pos: (0.0, 0.0), - clk_in: dummy_input.clone(), - }), ]; Library(library) }