Show the FP reg table and use the new info format
This commit is contained in:
parent
ac07031631
commit
386a3b7403
1 changed files with 314 additions and 76 deletions
282
src/main.rs
282
src/main.rs
|
@ -1,3 +1,5 @@
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
use codespan_reporting::{
|
use codespan_reporting::{
|
||||||
diagnostic::{Diagnostic, Label},
|
diagnostic::{Diagnostic, Label},
|
||||||
files::SimpleFile,
|
files::SimpleFile,
|
||||||
|
@ -9,13 +11,16 @@ use codespan_reporting::{
|
||||||
};
|
};
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use riscv_interpreter::{
|
use rizz_v::{
|
||||||
env::Env,
|
env::Env,
|
||||||
execution::run_instruction,
|
execution::run_instruction,
|
||||||
|
info::info,
|
||||||
parser::{parse, Token},
|
parser::{parse, Token},
|
||||||
};
|
};
|
||||||
|
use termion::input::TermRead;
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
|
let display_mode = 's';
|
||||||
let writer = StandardStream::stderr(ColorChoice::Always);
|
let writer = StandardStream::stderr(ColorChoice::Always);
|
||||||
let config = Config::default();
|
let config = Config::default();
|
||||||
let input = std::fs::read_to_string("test.s").unwrap();
|
let input = std::fs::read_to_string("test.s").unwrap();
|
||||||
|
@ -25,8 +30,11 @@ fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
let mut env = Env::new();
|
let mut env = Env::new();
|
||||||
|
|
||||||
|
let mut toks: Vec<Token> = Vec::new();
|
||||||
let mut ops: Vec<u32> = Vec::new();
|
let mut ops: Vec<u32> = Vec::new();
|
||||||
|
|
||||||
|
let mut parse_asm_result = String::new();
|
||||||
|
|
||||||
match parse(&env, &input) {
|
match parse(&env, &input) {
|
||||||
Ok(tokens) => {
|
Ok(tokens) => {
|
||||||
let lines: Vec<&str> = input.lines().collect();
|
let lines: Vec<&str> = input.lines().collect();
|
||||||
|
@ -38,7 +46,8 @@ fn main() -> anyhow::Result<()> {
|
||||||
let token = token.clone();
|
let token = token.clone();
|
||||||
|
|
||||||
match token.clone() {
|
match token.clone() {
|
||||||
Token::Op(..) => match env.assemble_op((token, loc.clone())) {
|
Token::Mnemonic(..) => {
|
||||||
|
match env.assemble_op((token.clone(), loc.clone())) {
|
||||||
Ok(op) => {
|
Ok(op) => {
|
||||||
let mut formatted = format!(
|
let mut formatted = format!(
|
||||||
"{:<1$} {3:02x}: {2:032b}",
|
"{:<1$} {3:02x}: {2:032b}",
|
||||||
|
@ -48,6 +57,7 @@ fn main() -> anyhow::Result<()> {
|
||||||
loc.mem_offset
|
loc.mem_offset
|
||||||
);
|
);
|
||||||
ops.push(op[0]);
|
ops.push(op[0]);
|
||||||
|
toks.push(token.clone());
|
||||||
|
|
||||||
if op.len() > 1 {
|
if op.len() > 1 {
|
||||||
for op in op[1..].iter() {
|
for op in op[1..].iter() {
|
||||||
|
@ -59,9 +69,10 @@ fn main() -> anyhow::Result<()> {
|
||||||
loc.mem_offset
|
loc.mem_offset
|
||||||
);
|
);
|
||||||
ops.push(*op);
|
ops.push(*op);
|
||||||
|
toks.push(token.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("{}", formatted);
|
parse_asm_result += &format!("{}\n", formatted);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let diagnostic = Diagnostic::error()
|
let diagnostic = Diagnostic::error()
|
||||||
|
@ -83,10 +94,11 @@ fn main() -> anyhow::Result<()> {
|
||||||
term::emit(&mut writer.lock(), &config, &file, &diagnostic)
|
term::emit(&mut writer.lock(), &config, &file, &diagnostic)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
}
|
||||||
Token::Label(name) => {
|
Token::Label(name) => {
|
||||||
println!(
|
parse_asm_result += &format!(
|
||||||
"{:<1$} <{2:02x}>",
|
"{:<1$} <{2:02x}>\n",
|
||||||
name.clone() + ":",
|
name.clone() + ":",
|
||||||
size + 3,
|
size + 3,
|
||||||
env.get_label(&name).unwrap()
|
env.get_label(&name).unwrap()
|
||||||
|
@ -121,16 +133,22 @@ fn main() -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut file = std::fs::File::create("test.bin")?;
|
||||||
|
for op in ops.iter() {
|
||||||
|
let formatted = format!("{:08x}\n", op);
|
||||||
|
file.write_all(formatted.as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
// Print the register values
|
// Print the register values
|
||||||
|
|
||||||
while env.pc / 4 < ops.clone().len() as u32 {
|
while env.pc / 4 < ops.clone().len() as u32 {
|
||||||
let pc = env.pc.clone();
|
let pc = env.pc.clone();
|
||||||
let prev_regs = env.registers.clone();
|
let prev_regs = env.registers.clone();
|
||||||
|
let prev_fregs = env.fregisters.clone();
|
||||||
|
|
||||||
env.pc += 4 * !run_instruction(&mut env, ops[pc as usize >> 2]) as u32;
|
env.pc += 4 * !run_instruction(&mut env, ops[pc as usize >> 2]) as u32;
|
||||||
|
|
||||||
let mut changed = Vec::new();
|
let mut changed = Vec::new();
|
||||||
|
|
||||||
for (i, _) in prev_regs
|
for (i, _) in prev_regs
|
||||||
.iter()
|
.iter()
|
||||||
.zip(env.registers.iter())
|
.zip(env.registers.iter())
|
||||||
|
@ -140,53 +158,113 @@ fn main() -> anyhow::Result<()> {
|
||||||
changed.push(i);
|
changed.push(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut fchanged = Vec::new();
|
||||||
|
for (i, _) in prev_fregs
|
||||||
|
.iter()
|
||||||
|
.zip(env.fregisters.iter())
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(_, (prev, curr))| prev != curr)
|
||||||
|
{
|
||||||
|
fchanged.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"{}",
|
"{}\n",
|
||||||
make_box(
|
parse_asm_result
|
||||||
term_width as u32,
|
.lines()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, line)| {
|
||||||
|
if i == pc as usize >> 2 {
|
||||||
|
format!("> {}", line).bright_green()
|
||||||
|
} else {
|
||||||
|
format!(" {}", line).normal()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.join("\n")
|
||||||
|
);
|
||||||
|
let (right, tag) = if let Token::Mnemonic(op, args) = &toks[pc as usize >> 2] {
|
||||||
|
info(
|
||||||
|
&env,
|
||||||
|
&op,
|
||||||
|
args.iter().map(|(token, _)| token.to_string()).collect(),
|
||||||
|
display_mode,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
let left = make_box(
|
||||||
|
term_width as u32 / 2,
|
||||||
pc as usize,
|
pc as usize,
|
||||||
env.registers.clone().into_iter().collect(),
|
env.registers.clone().into_iter().collect(),
|
||||||
changed,
|
changed,
|
||||||
's'
|
display_mode,
|
||||||
)
|
true,
|
||||||
|
tag.clone(),
|
||||||
|
) + &make_box_fp(
|
||||||
|
term_width as u32 / 2,
|
||||||
|
env.fregisters.clone().into_iter().collect(),
|
||||||
|
fchanged,
|
||||||
|
display_mode,
|
||||||
|
true,
|
||||||
|
tag,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
left.lines()
|
||||||
|
.zip(right.lines().chain([""].repeat(left.lines().count())))
|
||||||
|
.map(|(l, r)| format!("{} {}", l, r))
|
||||||
|
.join("\n")
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("\nPress enter to continue...");
|
||||||
|
for c in std::io::stdin().keys() {
|
||||||
|
match c.unwrap() {
|
||||||
|
termion::event::Key::Char('\n') => break,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fn round_down_to_power_of_two(n: u32) -> u32 {
|
||||||
fn round_down_to_power_of_two(n: u32) -> u32 {
|
|
||||||
1 << (32 - n.leading_zeros() - 1)
|
1 << (32 - n.leading_zeros() - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assuming the terminal is at least 80 characters wide
|
/// Assuming the terminal is at least 80 characters wide
|
||||||
|
///
|
||||||
/// Display Mode:
|
/// Display Mode:
|
||||||
/// - b: binary
|
|
||||||
/// - u: unsigned decimal
|
|
||||||
/// - h: hex
|
|
||||||
/// - s: signed decimal
|
/// - s: signed decimal
|
||||||
/// - f: float
|
/// - u: unsigned decimal
|
||||||
|
/// - b: binary
|
||||||
|
/// - h: hex
|
||||||
fn make_box(
|
fn make_box(
|
||||||
width: u32,
|
width: u32,
|
||||||
pc: usize,
|
pc: usize,
|
||||||
regs: Vec<u32>,
|
regs: Vec<u32>,
|
||||||
changed: Vec<usize>,
|
changed: Vec<usize>,
|
||||||
display_mode: char,
|
display_mode: char,
|
||||||
|
first: bool,
|
||||||
|
tag: (Vec<usize>, Vec<usize>),
|
||||||
) -> String {
|
) -> String {
|
||||||
let cell_inner_width: u32 = match display_mode {
|
let cell_inner_width: u32 = match display_mode {
|
||||||
'b' => 32,
|
'b' => 32,
|
||||||
'u' => 10,
|
'u' => 10,
|
||||||
'h' => 8,
|
'h' => 8,
|
||||||
's' => 11,
|
's' => 11,
|
||||||
'f' => todo!("float display mode"),
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
} + 7;
|
} + 7;
|
||||||
|
|
||||||
// Nnumber of boxes that fit horizontally
|
// Nnumber of boxes that fit horizontally
|
||||||
let num_boxes = round_down_to_power_of_two((width / (cell_inner_width + 2)) as u32);
|
let num_boxes = round_down_to_power_of_two((width / (cell_inner_width + 2)) as u32);
|
||||||
|
if num_boxes <= 1 {
|
||||||
|
return make_one_wide_box(pc, regs, changed, display_mode, first, tag);
|
||||||
|
}
|
||||||
let mut boxed = String::new();
|
let mut boxed = String::new();
|
||||||
|
|
||||||
|
if first {
|
||||||
boxed += &format!(
|
boxed += &format!(
|
||||||
"┌─╢ pc = {pc:04x} ╟{:─<1$}┬",
|
"┌─╢ pc = {pc:04x} ╟{:─<1$}┬",
|
||||||
"",
|
"",
|
||||||
|
@ -196,6 +274,17 @@ fn make_box(
|
||||||
boxed += &format!("{:─<1$}┬", "", cell_inner_width as usize);
|
boxed += &format!("{:─<1$}┬", "", cell_inner_width as usize);
|
||||||
}
|
}
|
||||||
boxed += &format!("{:─<1$}┐\n", "", cell_inner_width as usize);
|
boxed += &format!("{:─<1$}┐\n", "", cell_inner_width as usize);
|
||||||
|
} else {
|
||||||
|
boxed += &format!(
|
||||||
|
"├─╢ pc = {pc:04x} ╟{:─<1$}┼",
|
||||||
|
"",
|
||||||
|
cell_inner_width.saturating_sub(14) as usize
|
||||||
|
);
|
||||||
|
for _ in 1..(num_boxes - 1) {
|
||||||
|
boxed += &format!("{:─<1$}┼", "", cell_inner_width as usize);
|
||||||
|
}
|
||||||
|
boxed += &format!("{:─<1$}┤\n", "", cell_inner_width as usize);
|
||||||
|
}
|
||||||
|
|
||||||
for chunk in ®s.iter().enumerate().chunks(num_boxes as usize) {
|
for chunk in ®s.iter().enumerate().chunks(num_boxes as usize) {
|
||||||
let chunk = chunk.collect::<Vec<_>>();
|
let chunk = chunk.collect::<Vec<_>>();
|
||||||
|
@ -204,20 +293,27 @@ fn make_box(
|
||||||
for (i, reg) in chunk {
|
for (i, reg) in chunk {
|
||||||
let reg = match display_mode {
|
let reg = match display_mode {
|
||||||
'b' => format!("x{:<3} {1:0>32b}", i.to_string() + ":", reg),
|
'b' => format!("x{:<3} {1:0>32b}", i.to_string() + ":", reg),
|
||||||
'u' => format!("x{:<3} {1:0>10}", i.to_string() + ":", reg),
|
'u' => format!("x{:<3} {1:>10}", i.to_string() + ":", reg),
|
||||||
'h' => format!("x{:<3} {1:0>8x}", i.to_string() + ":", reg),
|
'h' => format!("x{:<3} {1:0>8x}", i.to_string() + ":", reg),
|
||||||
's' => {
|
's' => {
|
||||||
let signed = *reg as i32;
|
let signed = *reg as i32;
|
||||||
let sign = if signed < 0 { "-" } else { "+" };
|
let sign = if signed < 0 { "-" } else { "+" };
|
||||||
format!("x{:<3} {}{:0>10}", i.to_string() + ":", sign, signed)
|
format!(
|
||||||
|
"x{:<3} {:>11}",
|
||||||
|
i.to_string() + ":",
|
||||||
|
sign.to_string() + &signed.abs().to_string()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
'f' => todo!("float display mode"),
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
let reg = if changed.contains(&i) {
|
let reg = if changed.contains(&i) {
|
||||||
reg.bright_green()
|
reg.bright_green()
|
||||||
|
} else {
|
||||||
|
if tag.0.contains(&i) {
|
||||||
|
reg.bright_yellow()
|
||||||
} else {
|
} else {
|
||||||
reg.normal()
|
reg.normal()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
formatted += &format!("{} │ ", reg);
|
formatted += &format!("{} │ ", reg);
|
||||||
}
|
}
|
||||||
|
@ -225,11 +321,153 @@ fn make_box(
|
||||||
boxed += &format!("{}\n", formatted);
|
boxed += &format!("{}\n", formatted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boxed
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_one_wide_box(
|
||||||
|
pc: usize,
|
||||||
|
regs: Vec<u32>,
|
||||||
|
changed: Vec<usize>,
|
||||||
|
display_mode: char,
|
||||||
|
first: bool,
|
||||||
|
tag: (Vec<usize>, Vec<usize>),
|
||||||
|
) -> String {
|
||||||
|
let mut boxed = String::new();
|
||||||
|
|
||||||
|
boxed += &if first {
|
||||||
|
format!("┌─╢ pc = {pc:04x} ╟{:─<1$}┐\n", "", 32)
|
||||||
|
} else {
|
||||||
|
format!("├─╢ pc = {pc:04x} ╟{:─<1$}┤\n", "", 32)
|
||||||
|
};
|
||||||
|
for (i, reg) in regs.iter().enumerate() {
|
||||||
|
let reg = match display_mode {
|
||||||
|
'b' => format!("x{:<3} {1:0>32b}", i.to_string() + ":", reg),
|
||||||
|
'u' => format!("x{:<3} {1:0>10}", i.to_string() + ":", reg),
|
||||||
|
'h' => format!("x{:<3} {1:0>8x}", i.to_string() + ":", reg),
|
||||||
|
's' => {
|
||||||
|
let signed = *reg as i32;
|
||||||
|
let sign = if signed < 0 { "-" } else { "+" };
|
||||||
|
format!("x{:<3} {}{:0>10}", i.to_string() + ":", sign, signed.abs())
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let reg = if changed.contains(&i) {
|
||||||
|
reg.bright_green()
|
||||||
|
} else {
|
||||||
|
if tag.0.contains(&i) {
|
||||||
|
reg.bright_yellow()
|
||||||
|
} else {
|
||||||
|
reg.normal()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
boxed += &format!("│ {} │\n", reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
boxed
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assuming the terminal is at least 80 characters wide
|
||||||
|
/// Display Mode:
|
||||||
|
/// - s,u: floating point
|
||||||
|
/// - b: binary
|
||||||
|
/// - x: hexadecimal
|
||||||
|
/// - e: scientific
|
||||||
|
fn make_box_fp(
|
||||||
|
width: u32,
|
||||||
|
regs: Vec<f32>,
|
||||||
|
changed: Vec<usize>,
|
||||||
|
display_mode: char,
|
||||||
|
last: bool,
|
||||||
|
tag: (Vec<usize>, Vec<usize>),
|
||||||
|
) -> String {
|
||||||
|
let cell_inner_width: u32 = 11 + 7;
|
||||||
|
|
||||||
|
// Nnumber of boxes that fit horizontally
|
||||||
|
let num_boxes = round_down_to_power_of_two((width / (cell_inner_width + 2)) as u32);
|
||||||
|
if num_boxes <= 1 {
|
||||||
|
return make_one_wide_box_fp(regs, changed, last, tag);
|
||||||
|
}
|
||||||
|
let mut boxed = String::new();
|
||||||
|
|
||||||
|
boxed += &format!("├─{:─<1$}┼", "", (cell_inner_width - 1) as usize);
|
||||||
|
for _ in 1..(num_boxes - 1) {
|
||||||
|
boxed += &format!("{:─<1$}┼", "", cell_inner_width as usize);
|
||||||
|
}
|
||||||
|
boxed += &format!("{:─<1$}┤\n", "", cell_inner_width as usize);
|
||||||
|
|
||||||
|
for chunk in ®s.iter().enumerate().chunks(num_boxes as usize) {
|
||||||
|
let chunk = chunk.collect::<Vec<_>>();
|
||||||
|
let mut formatted = String::from("│ ");
|
||||||
|
|
||||||
|
for (i, freg) in chunk {
|
||||||
|
// let freg = format!("f{:<3} {:>11}", i.to_string() + ":", freg);
|
||||||
|
let freg = match display_mode {
|
||||||
|
's' | 'u' => format!("f{:<3} {:>11}", i.to_string() + ":", freg),
|
||||||
|
'b' => format!("f{:<3} {:0>32b}", i.to_string() + ":", freg.to_bits()),
|
||||||
|
'x' => format!("f{:<3} {:0>8x}", i.to_string() + ":", freg.to_bits()),
|
||||||
|
'e' => format!("f{:<3} {:>11e}", i.to_string() + ":", freg),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let reg = if changed.contains(&i) {
|
||||||
|
freg.bright_green()
|
||||||
|
} else {
|
||||||
|
if tag.1.contains(&i) {
|
||||||
|
freg.bright_yellow()
|
||||||
|
} else {
|
||||||
|
freg.normal()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
formatted += &format!("{} │ ", reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
boxed += &format!("{}\n", formatted);
|
||||||
|
}
|
||||||
|
|
||||||
|
if last {
|
||||||
boxed += &format!("└{:─<1$}┴", "", cell_inner_width as usize);
|
boxed += &format!("└{:─<1$}┴", "", cell_inner_width as usize);
|
||||||
for _ in 1..(num_boxes - 1) {
|
for _ in 1..(num_boxes - 1) {
|
||||||
boxed += &format!("{:─<1$}┴", "", cell_inner_width as usize);
|
boxed += &format!("{:─<1$}┴", "", cell_inner_width as usize);
|
||||||
}
|
}
|
||||||
boxed += &format!("{:─<1$}┘", "", cell_inner_width as usize);
|
boxed += &format!("{:─<1$}┘", "", cell_inner_width as usize);
|
||||||
|
} else {
|
||||||
|
boxed += &format!("├{:─<1$}┼", "", cell_inner_width as usize);
|
||||||
|
for _ in 1..(num_boxes - 1) {
|
||||||
|
boxed += &format!("{:─<1$}┼", "", cell_inner_width as usize);
|
||||||
|
}
|
||||||
|
boxed += &format!("{:─<1$}┤", "", cell_inner_width as usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
boxed
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_one_wide_box_fp(
|
||||||
|
regs: Vec<f32>,
|
||||||
|
changed: Vec<usize>,
|
||||||
|
last: bool,
|
||||||
|
tag: (Vec<usize>, Vec<usize>),
|
||||||
|
) -> String {
|
||||||
|
let mut boxed = String::new();
|
||||||
|
|
||||||
|
boxed += &format!("├─{:─<1$}┤\n", "", 32);
|
||||||
|
|
||||||
|
for (i, freg) in regs.iter().enumerate() {
|
||||||
|
let freg = format!("f{:<3} {:0>11}", i.to_string() + ":", freg);
|
||||||
|
let reg = if changed.contains(&i) {
|
||||||
|
freg.bright_green()
|
||||||
|
} else {
|
||||||
|
if tag.1.contains(&i) {
|
||||||
|
freg.bright_yellow()
|
||||||
|
} else {
|
||||||
|
freg.normal()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
boxed += &format!("│ {} │\n", reg);
|
||||||
|
}
|
||||||
|
boxed += &if last {
|
||||||
|
format!("└{:─<1$}┘", "", 32)
|
||||||
|
} else {
|
||||||
|
format!("├{:─<1$}┤", "", 32)
|
||||||
|
};
|
||||||
|
|
||||||
boxed
|
boxed
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue