diff --git a/interp/src/debugger/commands/command_parser.rs b/interp/src/debugger/commands/command_parser.rs index 60af379f6..c48179d1a 100644 --- a/interp/src/debugger/commands/command_parser.rs +++ b/interp/src/debugger/commands/command_parser.rs @@ -1,5 +1,8 @@ -use super::core::{ - Command, ParsedBreakPointID, ParsedGroupName, PrintMode, WatchPosition, +use super::{ + core::{ + Command, ParsedBreakPointID, ParsedGroupName, PrintMode, WatchPosition, + }, + PrintCommand, }; use baa::WidthInt; use pest_consume::{match_nodes, Error, Parser}; @@ -21,10 +24,15 @@ impl CommandParser { fn EOI(_input: Node) -> ParseResult<()> { Ok(()) } + fn code_calyx(_input: Node) -> ParseResult<()> { Ok(()) } + fn code_nodes(_input: Node) -> ParseResult<()> { + Ok(()) + } + // ---------------------- fn help(_input: Node) -> ParseResult { @@ -60,8 +68,9 @@ impl CommandParser { fn comm_where(input: Node) -> ParseResult { Ok(match_nodes!(input.into_children(); - [code_calyx(_)] => Command::PrintPC(true), - [] => Command::PrintPC(false), + [code_calyx(_)] => Command::PrintPC(PrintCommand::PrintCalyx), + [code_nodes(_)] => Command::PrintPC(PrintCommand::PrintNodes), + [] => Command::PrintPC(PrintCommand::Normal), )) } diff --git a/interp/src/debugger/commands/commands.pest b/interp/src/debugger/commands/commands.pest index 799971648..7a1920c68 100644 --- a/interp/src/debugger/commands/commands.pest +++ b/interp/src/debugger/commands/commands.pest @@ -14,6 +14,7 @@ pc_s = { ^"s" } pc_ufx = { ^"u." ~ num } pc_sfx = { ^"s." ~ num } code_calyx = { ^"calyx" } +code_nodes = {^"nodes"} print_code = { "\\" ~ (pc_ufx | pc_sfx | pc_s | pc_un) @@ -67,7 +68,7 @@ disable_watch = { (^"disable-watch " | ^"disw ") ~ brk_id+ } exit = { ^"exit" | ^"quit" } -comm_where = { (^"where" | "pc") ~ (code_calyx)? } +comm_where = { (^"where" | "pc") ~ (code_calyx | code_nodes)? } explain = { ^"explain" } diff --git a/interp/src/debugger/commands/core.rs b/interp/src/debugger/commands/core.rs index 46f86279b..37148ef8a 100644 --- a/interp/src/debugger/commands/core.rs +++ b/interp/src/debugger/commands/core.rs @@ -299,6 +299,13 @@ impl From<(Vec, Option, PrintMode)> for PrintTuple { } } +// Different types of printing commands +pub enum PrintCommand { + Normal, + PrintCalyx, + PrintNodes, +} + /// A command that can be sent to the debugger. pub enum Command { /// Advance the execution by a given number of steps (cycles). @@ -345,7 +352,7 @@ pub enum Command { PrintMode, ), /// Print the current program counter - PrintPC(bool), + PrintPC(PrintCommand), /// Show command examples Explain, /// Restart the debugger from the beginning of the execution. Command history, breakpoints, watchpoints, etc. are preserved. diff --git a/interp/src/debugger/debugger_core.rs b/interp/src/debugger/debugger_core.rs index 837869f9f..e9fc878c2 100644 --- a/interp/src/debugger/debugger_core.rs +++ b/interp/src/debugger/debugger_core.rs @@ -6,7 +6,9 @@ use super::{ }; use crate::{ configuration::RuntimeConfig, - debugger::{source::SourceMap, unwrap_error_message}, + debugger::{ + commands::PrintCommand, source::SourceMap, unwrap_error_message, + }, errors::{CiderError, CiderResult}, flatten::{ flat_ir::prelude::GroupIdx, @@ -368,10 +370,15 @@ impl + Clone> Debugger { Command::InfoWatch => self .debugging_context .print_watchpoints(self.interpreter.env()), - Command::PrintPC(_override_flag) => { - self.interpreter.print_pc(); - } + Command::PrintPC(print_mode) => match print_mode { + PrintCommand::Normal | PrintCommand::PrintCalyx => { + self.interpreter.print_pc(); + } + PrintCommand::PrintNodes => { + self.interpreter.print_pc_string(); + } + }, Command::Explain => { print!("{}", Command::get_explain_string()) } diff --git a/interp/src/flatten/structures/environment/env.rs b/interp/src/flatten/structures/environment/env.rs index 65769f4d1..7b7360a57 100644 --- a/interp/src/flatten/structures/environment/env.rs +++ b/interp/src/flatten/structures/environment/env.rs @@ -357,6 +357,11 @@ impl + Clone> Environment { pub fn ctx(&self) -> &Context { self.ctx.as_ref() } + + pub fn pc_iter(&self) -> impl Iterator { + self.pc.iter().map(|(_, x)| x) + } + /// Returns the full name and port list of each cell in the context pub fn iter_cells( &self, @@ -857,6 +862,17 @@ impl + Clone> Environment { } } + pub fn print_pc_string(&self) { + let ctx = self.ctx.as_ref(); + for node in self.pc_iter() { + println!( + "{}: {}", + self.get_full_name(node.comp), + node.string_path(ctx) + ); + } + } + fn get_name_from_cell_and_parent( &self, parent: GlobalCellIdx, @@ -1458,6 +1474,10 @@ impl + Clone> Simulator { ) -> DataDump { self.base.dump_memories(dump_registers, all_mems) } + + pub fn print_pc_string(&self) { + self.base.print_pc_string() + } } impl + Clone> BaseSimulator { @@ -1516,6 +1536,10 @@ impl + Clone> BaseSimulator { self.env.print_pc() } + pub fn print_pc_string(&self) { + self.env.print_pc_string() + } + /// Pins the port with the given name to the given value. This may only be /// used for input ports on the entrypoint component (excluding the go port) /// and will panic if used otherwise. Intended for external use. diff --git a/interp/src/flatten/structures/environment/program_counter.rs b/interp/src/flatten/structures/environment/program_counter.rs index dc8223d24..918303141 100644 --- a/interp/src/flatten/structures/environment/program_counter.rs +++ b/interp/src/flatten/structures/environment/program_counter.rs @@ -59,6 +59,67 @@ impl ControlPoint { false } } + + /// Returns a string showing the path from the root node to input node. This + /// path is displayed in the minimal metadata path syntax. + pub fn string_path(&self, ctx: &Context) -> String { + let path = SearchPath::find_path_from_root(self.control_node_idx, ctx); + let mut path_vec = path.path; + + // Remove first element since we know it is a root + path_vec.remove(0); + let mut string_path = String::new(); + string_path.push('.'); + let control_map = &ctx.primary.control; + let mut count = -1; + let mut body = false; + let mut if_branches: HashMap = HashMap::new(); + for search_node in path_vec { + // The control_idx should exist in the map, so we shouldn't worry about it + // exploding. First SearchNode is root, hence "." + let control_idx = search_node.node; + let control_node = control_map.get(control_idx).unwrap(); + match control_node { + // These are terminal nodes + // ControlNode::Empty(_) => "empty", + // ControlNode::Invoke(_) => "invoke", + // ControlNode::Enable(_) => "enable", + + // These have unbounded children + // ControlNode::Seq(_) => "seq", + // ControlNode::Par(_) => "par", + + // Special cases + ControlNode::If(if_node) => { + if_branches.insert(if_node.tbranch(), String::from("t")); + if_branches.insert(if_node.tbranch(), String::from("f")); + } + ControlNode::While(_) => { + body = true; + } + ControlNode::Repeat(_) => { + body = true; + } + _ => {} + }; + + let control_type = if body { + body = false; + count = -1; + String::from("b") + } else if if_branches.contains_key(&control_idx) { + let (_, branch) = + if_branches.get_key_value(&control_idx).unwrap(); + branch.clone() + } else { + count += 1; + count.to_string() + }; + + string_path = string_path + "-" + &control_type; + } + string_path + } } #[derive(Debug, Clone)]