Skip to content

Commit

Permalink
feat!: add the ability to dump instruction speciic ops with script to…
Browse files Browse the repository at this point in the history
… autoformat Noir tests

Now that I have the actual trace, I can see INX is actually broken. We have some strange status register reads cropping up
  • Loading branch information
goblinoats committed Sep 17, 2023
1 parent ac18cc2 commit 1f7f184
Show file tree
Hide file tree
Showing 9 changed files with 429 additions and 77 deletions.
182 changes: 113 additions & 69 deletions circuits/instr/inx/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -8,85 +8,68 @@ use dep::helpers;
//SR = 8205
fn main(
r: Field,
op_sorted_step: [Field; 21],
op_sorted_addr: [Field; 21],
op_sorted_val: [Field; 21],
op_sorted_op_rw: [Field; 21]
op_sorted_step: [Field; 10],
op_sorted_addr: [Field; 10],
op_sorted_val: [Field; 10],
op_sorted_op_rw: [Field; 10]
) -> pub Field {

let mut index = 0;
let mut padding = false;
let mut end = false;
for q in 0..20 {
if (op_sorted_addr[index] == 1000000000) {
padding = true;
}
if (index as u16 > 20) {
padding = true;
end = true;
}
if (!padding) {
assert(op_sorted_addr[index] == 8203);
assert(op_sorted_op_rw[index] == 0);
assert(op_sorted_val[index] == 232);

let mut sub_arr_addr: [Field; 2] = [0,0];
let mut sub_arr_val: [Field; 2] = [0,0];
let mut sub_arr_op_rw: [Field; 2] = [0,0];
for i in index..2 {
sub_arr_addr[i] = op_sorted_addr[i];
sub_arr_val[i] = op_sorted_val[i];
sub_arr_op_rw[i] = op_sorted_op_rw[i];
}
assert(op_sorted_addr[0] == 8203);
// the value here should map to the addr of the next entry
// but we need to implement "mapping" logic, and I don't
// have good ideas on how to do that at present
assert(op_sorted_op_rw[0] == 0);
assert(op_sorted_op_rw[1] == 0);
assert(op_sorted_val[1] == 232);

let address: Field = helpers::imm(
sub_arr_addr,
sub_arr_val,
sub_arr_op_rw
);
let mut sub_arr_addr: [Field; 2] = [0,0];
let mut sub_arr_val: [Field; 2] = [0,0];
let mut sub_arr_op_rw: [Field; 2] = [0,0];
for i in 2..3 {
sub_arr_addr[i] = op_sorted_addr[i];
sub_arr_val[i] = op_sorted_val[i];
sub_arr_op_rw[i] = op_sorted_op_rw[i];
}

// add the offset to the index
index = index + address;
let address: Field = helpers::imm(
sub_arr_addr,
sub_arr_val,
sub_arr_op_rw
);

// we perform a read of x
assert(op_sorted_addr[index] == 8201);
assert(op_sorted_op_rw[index] == 0);
let value = op_sorted_val[index];
index = index + 1;
// add the offset to the index
index = index + address;

// we then perform a write of x + 1
assert(op_sorted_addr[index] == 8201);
assert(op_sorted_op_rw[index] == 1);
let wadd = helpers::wrapping_add_u8(value, 1);
assert(op_sorted_val[index] == wadd.value);
index = index + 1;
// we perform a read of x
assert(op_sorted_addr[index] == 8201);
assert(op_sorted_op_rw[index] == 0);
let value = op_sorted_val[index];
index = index + 1;

// we then set a new status into the status register
// we then perform a write of x + 1
assert(op_sorted_addr[index] == 8201);
assert(op_sorted_op_rw[index] == 1);
let wadd = helpers::wrapping_add_u8(value, 1);
assert(op_sorted_val[index] == wadd.value);
index = index + 1;

// first there is a read from the status register
assert(op_sorted_addr[index] == 8205);
assert(op_sorted_op_rw[index] == 0);
let sr = op_sorted_val[index];
index = index + 1;
// we then set a new status into the status register

// next there is a write to the status register
// we need to compute the zero and negative flag
let zn = helpers::compute_zn_status(wadd.value);
let srnew = helpers::update_status(sr, zn);
assert(op_sorted_addr[index] == 8205);
assert(op_sorted_op_rw[index] == 1);
assert(op_sorted_val[index] == srnew);
index = index + 1;
} else {
if (!end) {
// this handles any necessary padding
assert(op_sorted_addr[index] == 1000000000);
assert(op_sorted_val[index] == 1000000000);
assert(op_sorted_op_rw[index] == 1000000000);
}
index = index + 1;
}
}
// first there is a read from the status register
assert(op_sorted_addr[index] == 8205);
assert(op_sorted_op_rw[index] == 0);
let sr = op_sorted_val[index];
index = index + 1;

// next there is a write to the status register
// we need to compute the zero and negative flag
let zn = helpers::compute_zn_status(wadd.value);
let srnew = helpers::update_status(sr, zn);
assert(op_sorted_addr[index] == 8205);
assert(op_sorted_op_rw[index] == 1);
assert(op_sorted_val[index] == srnew);
index = index + 1;

// Compute permutation and return it
helpers::compute_permutation(
Expand All @@ -96,4 +79,65 @@ fn main(
op_sorted_val,
op_sorted_op_rw
)
}

#[test]
fn test_0() {
main(
1,
[405465, 405466, 405467, 405468, 405469, 405470, 405471, 405472, 405473, 405474, 405475],
[8203, 79, 8205, 8203, 8203, 80, 8205, 8201, 8201, 8205, 8205],
[49231, 232, 36, 49232, 49232, 224, 36, 0, 1, 36, 36],
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1]
)
}
#[test]
fn test_1() {
main(
1,
[405540, 405541, 405542, 405543, 405544, 405545, 405546, 405547, 405548, 405549, 405550],
[8203, 79, 8205, 8203, 8203, 80, 8205, 8201, 8201, 8205, 8205],
[49231, 232, 36, 49232, 49232, 224, 36, 1, 2, 36, 36],
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1]
)
}
#[test]
fn test_2() {
main(
1,
[405615, 405616, 405617, 405618, 405619, 405620, 405621, 405622, 405623, 405624, 405625],
[8203, 79, 8205, 8203, 8203, 80, 8205, 8201, 8201, 8205, 8205],
[49231, 232, 36, 49232, 49232, 224, 36, 2, 3, 36, 36],
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1]
)
}
#[test]
fn test_3() {
main(
1,
[405690, 405691, 405692, 405693, 405694, 405695, 405696, 405697, 405698, 405699, 405700],
[8203, 79, 8205, 8203, 8203, 80, 8205, 8201, 8201, 8205, 8205],
[49231, 232, 36, 49232, 49232, 224, 36, 3, 4, 36, 36],
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1]
)
}
#[test]
fn test_4() {
main(
1,
[405765, 405766, 405767, 405768, 405769, 405770, 405771, 405772, 405773, 405774, 405775],
[8203, 79, 8205, 8203, 8203, 80, 8205, 8201, 8201, 8205, 8205],
[49231, 232, 36, 49232, 49232, 224, 36, 4, 5, 36, 36],
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1]
)
}
#[test]
fn test_5() {
main(
1,
[405840, 405841, 405842, 405843, 405844, 405845, 405846, 405847, 405848, 405849, 405850],
[8203, 79, 8205, 8203, 8203, 80, 8205, 8201, 8201, 8205, 8205],
[49231, 232, 36, 49232, 49232, 224, 36, 5, 6, 36, 36],
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1]
)
}
89 changes: 89 additions & 0 deletions circuits/scripts/convert_emulator_trace.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
const fs = require('fs');

function readJsonFile(filename) {
const fileContent = fs.readFileSync(filename, 'utf-8');
return JSON.parse(fileContent);
}

function splitIntoSegments(data) {
const segments = [];
let currentSegment = [];

for (const entry of data) {
if (entry.etype === 'DELIMITER') {
if (currentSegment.length) {
updateAddrBasedOnEtype(currentSegment);
segments.push(currentSegment);
currentSegment = [];
}
} else {
currentSegment.push(entry);
}
}

// Add any remaining segment
if (currentSegment.length) {
updateAddrBasedOnEtype(currentSegment);
segments.push(currentSegment);
}

return segments;
}

const etypeToAddrMapping = {
'PC': 8203,
'X': 8201,
'Y': 8202,
'A': 8200,
'S': 8205,
'SP': 8204
}

function updateAddrBasedOnEtype(segment) {
for (const entry of segment) {
if (etypeToAddrMapping[entry.etype] !== undefined) {
entry.addr = etypeToAddrMapping[entry.etype];
}
}
}

function convertSegment(segment) {
const step = [], addr = [], val = [], op_rw = [];
for (const entry of segment) {
step.push(entry.step);
addr.push(entry.addr);
val.push(entry.val);
op_rw.push(entry.op_rw == 'Read' ? 0 : 1);
}
return { step, addr, val, op_rw };
}

function templateSegment(segmentData, index) {
return `
#[test]
fn test_${index}() {
main(
1,
[${segmentData.step.join(", ")}],
[${segmentData.addr.join(", ")}],
[${segmentData.val.join(", ")}],
[${segmentData.op_rw.join(", ")}]
)
}`;
}

function main() {
const filePath = process.argv[2];
const jsonData = readJsonFile(filePath);
const segments = splitIntoSegments(jsonData);
let output = "";

for (let i = 0; i < segments.length; i++) {
const segmentData = convertSegment(segments[i]);
output += templateSegment(segmentData, i);
}

console.log(output);
}

main();
5 changes: 5 additions & 0 deletions emulator/src/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,11 @@ impl CpuBus {
self.oam_dma_addr
}

#[inline]
pub fn set_filter_trace(&mut self, filter_trace: Option<String>) {
self.trace.set_filter_trace(filter_trace);
}

#[inline]
pub fn set_trace_flag(&mut self, trace: bool) {
self.trace_flag = trace;
Expand Down
9 changes: 8 additions & 1 deletion emulator/src/control_deck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
mem::RamState,
ppu::Ppu,
video::{Video, VideoFilter},
NesResult,
NesResult, audio::filter,
};
use anyhow::anyhow;
use std::{io::Read, ops::ControlFlow};
Expand All @@ -26,6 +26,7 @@ pub struct ControlDeck {
cycles_remaining: f32,
cpu: Cpu,
trace: bool,
filter_trace: Option<String>
}

impl Default for ControlDeck {
Expand All @@ -41,6 +42,7 @@ impl ControlDeck {
Self {
running: false,
trace: false,
filter_trace: None,
ram_state,
region: NesRegion::default(),
video: Video::default(),
Expand Down Expand Up @@ -69,6 +71,11 @@ impl ControlDeck {
self.cpu = cpu;
}

#[inline]
pub fn set_filter_trace(&mut self, filter_trace: Option<String>) {
self.cpu.set_filter_trace(filter_trace.clone());
self.filter_trace = filter_trace;
}
#[inline]
pub fn set_trace(&mut self, trace: bool) {
self.trace = trace;
Expand Down
Loading

0 comments on commit 1f7f184

Please sign in to comment.