From b4eb623979cc9566d2a22c718b4ba8ded3bca5a4 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sat, 10 May 2025 10:10:24 -0700 Subject: clean up tests BubbleSort is complete but ugly risc5 encoding <= test EvalR5/Arm handles stdout/stderr. --- chapter22/docs/examples/BubbleSort.smp | 30 ++++++++++++++++++---- .../simple/node/cpus/riscv/XorIRISC.java | 1 + .../seaofnodes/simple/node/cpus/riscv/riscv.java | 2 +- .../java/com/seaofnodes/simple/Chapter20Test.java | 2 +- .../java/com/seaofnodes/simple/Chapter22Test.java | 4 ++- .../test/java/com/seaofnodes/simple/EvalArm64.java | 16 +++++++----- .../test/java/com/seaofnodes/simple/EvalRisc5.java | 16 +++++++----- 7 files changed, 50 insertions(+), 21 deletions(-) diff --git a/chapter22/docs/examples/BubbleSort.smp b/chapter22/docs/examples/BubbleSort.smp index f6b30752..a80d6bd8 100644 --- a/chapter22/docs/examples/BubbleSort.smp +++ b/chapter22/docs/examples/BubbleSort.smp @@ -1,5 +1,10 @@ // -*- mode: java; -*- +// An implementation of +// https://sampleprograms.io/projects/bubble-sort/ +// +// Bubble sort, with reading (parsing) and writing (formatting) the data. + val _exit = { u8[~] msg -> sys.io.p(msg); sys.libc._exit(1); @@ -40,6 +45,19 @@ val number = { Scan s -> return n; }; +val sort = { int[] ns, int len -> + var done = false; + while( !done ) { + done = true; + for( var i = 0; i < len-1; i++ ) + if( ns[i] > ns[i+1] ) { + int tmp = ns[i]; + ns[i] = ns[i+1]; + ns[i+1] = tmp; // Swap + done = false; + } + } +}; // Read from stdin a line of the form "[ 4, 3, 2, 1]" and print it sorted. val main = { -> @@ -47,23 +65,26 @@ val main = { -> require(s,'['); // Array of parsed results int[] !ns = new int[16]; - i32 num = 0; + i32 len = 0; // Parse a list of numbers if( !peek(s,']') ) { // Handle the empty list // Parse "123, " until a something else while( s.x < s.buf# ) { int n = number(s); - ns[num++] = n; + ns[len++] = n; if( !peek(s,',') ) break; }; require(s,']'); // Close the list } + // Bubble sort array of integers + sort(ns,len); + // Print a list of numbers sys.io.p("[ "); u8[] !junk = new u8[1]; - for( int i=0; i sys.io.p(", "); } sys.io.p("]"); - - return num; + return 0; }; diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java index 61f25be2..27098033 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/XorIRISC.java @@ -5,6 +5,7 @@ import com.seaofnodes.simple.node.Node; public class XorIRISC extends ImmRISC { public XorIRISC( Node and, int imm) { super(and,imm); } + public XorIRISC( Node and, int imm, boolean pop) { super(and,imm,pop); } @Override int opcode() { return riscv.OP_IMM; } @Override int func3() { return 4; } @Override public String glabel() { return "^"; } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java index 8e722563..3b8ff100 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java @@ -420,7 +420,7 @@ public class riscv extends Machine { ? new SetIRISC(bool, (int)ti.value(),false) : new SetRISC(bool, false); // x <= y - flip and negate; !(y < x); `slt tmp=y,x; xori dst=tmp,#1` - case "<=" -> new XorIRISC(new SetRISC(bool.swap12(), false),1); + case "<=" -> new XorIRISC(new SetRISC(bool.swap12(), false),1,false); // x == y - sub and vs0 == `sub tmp=x-y; sltu dst=tmp,#1` case "==" -> new SetIRISC(new SubRISC(bool),1,true); default -> throw Utils.TODO(); diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter20Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter20Test.java index 4c4ac4e4..f442ae1a 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter20Test.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter20Test.java @@ -66,7 +66,7 @@ val sqrt = { int x -> int cast_int = arg+2; return sqrt(arg) + sqrt(cast_int); """; - testCPU(src,"x86_64_v2", "Win64" ,23,null); + testCPU(src,"x86_64_v2", "Win64" ,55,null); testCPU(src,"riscv" , "SystemV",19,null); testCPU(src,"arm" , "SystemV",19,null); } diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java index 304fb1cf..4823dff8 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java @@ -116,12 +116,14 @@ return cc.cz; int trap = R5.step(100); assertEquals(0,trap); assertEquals(0,R5.regs[riscv.A0]); + assertEquals("Hello, World!",R5._stdout.toString()); // Evaluate on ARM emulator EvalArm64 arm = TestArm64.build("helloWorld", 0, 2, false); trap = arm.step(100); assertEquals(0,trap); assertEquals(0,arm.regs[0]); + assertEquals("Hello, World!",arm._stdout.toString()); } @Test @@ -131,7 +133,7 @@ int N=4; i32[] !is = new i32[N]; for( int i=0; i +val sum = { i32[~] is -> // final array int sum=0; for( int i=0; i System.out; - case 2 -> System.err; + ByteArrayOutputStream baos = switch((int)regs[0]) { + case 1 -> _stdout==null ? (_stdout = new ByteArrayOutputStream()) : _stdout; + case 2 -> _stderr==null ? (_stderr = new ByteArrayOutputStream()) : _stderr; default -> throw new IllegalArgumentException(); }; - ps.write(_buf,(int)regs[1],(int)regs[2]); + baos.write(_buf,(int)regs[1],(int)regs[2]); regs[0] = regs[2]; pc = (int)rval; rdid = -1; diff --git a/chapter22/src/test/java/com/seaofnodes/simple/EvalRisc5.java b/chapter22/src/test/java/com/seaofnodes/simple/EvalRisc5.java index d2255278..0a1c034f 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/EvalRisc5.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/EvalRisc5.java @@ -10,11 +10,10 @@ import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.node.cpus.riscv.riscv; - -import java.io.PrintStream; +import java.io.ByteArrayOutputStream; import java.util.Arrays; - public class EvalRisc5 { +public class EvalRisc5 { // Memory image, always 0-based public final byte[] _buf; @@ -29,6 +28,9 @@ import java.util.Arrays; // Start of free memory for allocation int _heap; + // Standard out and err streams + ByteArrayOutputStream _stdout, _stderr; + // Cycle counters int _cycle; @@ -102,12 +104,12 @@ import java.util.Arrays; rval = pc + 4; pc = pc + reladdy - 4; if( pc+4 == Encoding.SENTINEL_WRITE ) { - PrintStream ps = switch((int)regs[10]) { - case 1 -> System.out; - case 2 -> System.err; + ByteArrayOutputStream baos = switch((int)regs[10]) { + case 1 -> _stdout==null ? (_stdout = new ByteArrayOutputStream()) : _stdout; + case 2 -> _stderr==null ? (_stderr = new ByteArrayOutputStream()) : _stderr; default -> throw new IllegalArgumentException(); }; - ps.write(_buf,(int)regs[11],(int)regs[12]); + baos.write(_buf,(int)regs[11],(int)regs[12]); regs[10] = regs[12]; rdid = 0; pc = (int)(rval - 4); // Unwind PC, as-if returned from write -- cgit v1.2.3