diff options
| author | Cliff Click <cliffc@acm.org> | 2025-04-08 14:28:51 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-04-08 14:28:51 -0700 |
| commit | 938c09baca29b0647dcd56e9581540d7a8142fb4 (patch) | |
| tree | 0c213a1ead31de632b88f29308a9a00f8c8f76ee /chapter21 | |
| parent | 06872d180720c376d3fdcc0bd0a2a973bf9341c4 (diff) | |
| download | Simple-938c09baca29b0647dcd56e9581540d7a8142fb4.tar.gz Simple-938c09baca29b0647dcd56e9581540d7a8142fb4.zip | |
Fix risc5 bugs from emulator
Diffstat (limited to 'chapter21')
7 files changed, 72 insertions, 47 deletions
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java index a92b4e21..b8eb7644 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java @@ -52,7 +52,7 @@ public abstract class MemOpRISC extends MemOpNode implements MachNode { // float if(_declaredType == TypeFloat.F32) func3 = 2; // fLW fSW if(_declaredType == TypeFloat.F64) func3 = 3; // fLD fSD - if( _declaredType instanceof TypeMemPtr ) func3=6; // 4 byte pointers, assumed unsigned? + if( _declaredType instanceof TypeMemPtr ) func3=3; // 8 byte pointers if( func3 == -1 ) throw Utils.TODO(); return func3; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java index e82a6f24..fe767a36 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java @@ -497,7 +497,7 @@ public class riscv extends Machine { return new BranchRISC(iff, bop, bool.in(1), bool.in(2)); } // Vs zero - return new BranchRISC(iff, "==", iff.in(1), null); + return new BranchRISC(iff, "!=", iff.in(1), null); } private Node or(OrNode or) { diff --git a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java index e3239c48..a5316d62 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/Chapter21Test.java @@ -98,19 +98,46 @@ public class Chapter21Test { String fib = "[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]"; TestC.run("fib", fib); - EvalRisc5 R5 = TestRisc5.run("fib", 1000, 8); - // Return register A0 holds 55 + EvalRisc5 R5 = TestRisc5.build("fib", 8); + int trap = R5.step(100); + assertEquals(0,trap); + // Return register A0 holds fib(8)==55 assertEquals(55,R5.regs[riscv.A0]); } @Test public void testBrainFuck() throws IOException { - String brain_fuck = "Hello World!\r\n"; + String brain_fuck = "Hello World!\n"; TestC.run("brain_fuck", brain_fuck); } @Test public void testPerson() throws IOException { String person = "6\n"; TestC.run("person", person); + + // Memory layout starting at PS: + int ps = 1<<16; // Person array pointer + // Person[3] = { len,pad,P0,P1,P2 }; // sizeof = 4*8 + // P0 = { age } // sizeof=8 + int p0 = ps+4*8+0*8; + // P1 = { age } // sizeof=8 + int p1 = ps+4*8+1*8; + // P2 = { age } // sizeof=8 + int p2 = ps+4*8+2*8; + EvalRisc5 R5 = TestRisc5.build("person", ps); + R5.regs[riscv.A1] = 1; // Index 1 + R5.st4(ps,3); // Length + R5.st8(ps+1*8,p0); + R5.st8(ps+2*8,p1); + R5.st8(ps+3*8,p2); + R5.st8(p0, 5); // age= 5 + R5.st8(p1,17); // age=17 + R5.st8(p2,60); // age=60 + + int trap = R5.step(100); + assertEquals(0,trap); + assertEquals( 5+0,R5.ld8(p0)); + assertEquals(17+1,R5.ld8(p1)); + assertEquals(60+0,R5.ld8(p2)); } @Ignore diff --git a/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java b/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java index bced2505..cb5417d8 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/EvalRisc5.java @@ -27,19 +27,21 @@ public class EvalRisc5 { //#endif // Little endian - public int ld1s(int x) { return _buf[x ] ; } - public int ld1z(int x) { return _buf[x ]&0xFF; } - public int ld2s(int x) { return ld1z(x) | ld1s(x+1)<< 8; } - public int ld2z(int x) { return ld1z(x) | ld1z(x+1)<< 8; } - public int ld4s(int x) { return ld2z(x) | ld2s(x+2)<<16; } + public int ld1s(int x) { return _buf[x ] ; } + public int ld1z(int x) { return _buf[x ]&0xFF; } + public int ld2s(int x) { return ld1z(x) | ld1s(x+1)<< 8; } + public int ld2z(int x) { return ld1z(x) | ld1z(x+1)<< 8; } + public int ld4s(int x) { return ld2z(x) | ld2s(x+2)<<16; } + public long ld8 (int x) { return (long)ld4s(x)&0xFFFFFFFFL | ((long)ld4s(x+4))<<32; } - public void st1(int x, int val) { _buf[x] = (byte)val; } - public void st2(int x, int val) { st1(x,val); st1(x+1,val>> 8); } - public void st4(int x, int val) { st2(x,val); st2(x+2,val>>16); } + public void st1(int x, int val) { _buf[x] = (byte)val; } + public void st2(int x, int val) { st1(x,val); st1(x+1,val>> 8); } + public void st4(int x, int val) { st2(x,val); st2(x+2,val>>16); } + public void st8(int x, long val) { st4(x,(int)val); st2(x+4,(int)(val>>32)); } // GPRs - final int[] regs = new int[32]; + final long[] regs = new long[32]; // PC int _pc; @@ -55,7 +57,7 @@ public class EvalRisc5 { public int step( int maxops ) { int trap = 0; - int rval = 0; + long rval = 0; int pc = _pc; int cycle = _cycle; @@ -95,7 +97,7 @@ public class EvalRisc5 { int imm = ir >> 20; int imm_se = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0); rval = pc + 4; - pc = ( (regs[ (ir >> 15) & 0x1f ] + imm_se) & ~1) - 4; + pc = ( ((int)regs[ (ir >> 15) & 0x1f ] + imm_se) & ~1) - 4; // Return from top-level ; exit sim if( pc+4==0 ) { if( rdid!=0 ) regs[rdid] = rval; @@ -106,29 +108,28 @@ public class EvalRisc5 { case 0x63: { // Branch (0b1100011) int immm4 = ((ir & 0xf00)>>7) | ((ir & 0x7e000000)>>20) | ((ir & 0x80) << 4) | ((ir >> 31)<<12); if( (immm4 & 0x1000)!=0 ) immm4 |= 0xffffe000; - int rs1 = regs[(ir >> 15) & 0x1f]; - int rs2 = regs[(ir >> 20) & 0x1f]; + long rs1 = regs[(ir >> 15) & 0x1f]; + long rs2 = regs[(ir >> 20) & 0x1f]; immm4 = pc + immm4 - 4; rdid = 0; switch( ( ir >> 12 ) & 0x7 ) { // BEQ, BNE, BLT, BGE, BLTU, BGEU case 0: if( rs1 == rs2 ) pc = immm4; break; case 1: if( rs1 != rs2 ) pc = immm4; break; - case 4: if( rs1 < rs2 ) pc = immm4; break; - case 5: if( rs1 >= rs2 ) pc = immm4; break; //BGE - case 6: if( (int)rs1 < (int)rs2 ) pc = immm4; break; //BLTU - case 7: if( (int)rs1 >= (int)rs2 ) pc = immm4; break; //BGEU + case 4: if( rs1 < rs2 ) pc = immm4; break; + case 5: if( rs1 >= rs2 ) pc = immm4; break; + case 6: if( Long.compareUnsigned(rs1,rs2) < 0 ) pc = immm4; break; //BLTU + case 7: if( Long.compareUnsigned(rs1,rs2) >= 0 ) pc = immm4; break; //BGEU default: trap = (2+1); } break; } case 0x03: { // Load (0b0000011) - int rs1 = regs[(ir >> 15) & 0x1f]; + int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b int imm = ir >> 20; int imm_se = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0 ); int rsval = rs1 + imm_se; - rsval -= 0; if( rsval >= _buf.length-3 ) { trap = (5+1); rval = rsval; @@ -138,6 +139,7 @@ public class EvalRisc5 { case 0: rval = ld1s( rsval ); break; case 1: rval = ld2s( rsval ); break; case 2: rval = ld4s( rsval ); break; + case 3: rval = ld8 ( rsval ); break; case 4: rval = ld1z( rsval ); break; case 5: rval = ld2z( rsval ); break; default: trap = (2+1); @@ -146,11 +148,11 @@ public class EvalRisc5 { break; } case 0x23: { // Store 0b0100011 - int rs1 = regs[(ir >> 15) & 0x1f]; - int rs2 = regs[(ir >> 20) & 0x1f]; + int rs1 = (int)regs[(ir >> 15) & 0x1f]; // Address chop to 32b + long rs2 = regs[(ir >> 20) & 0x1f]; int addy = ( ( ir >> 7 ) & 0x1f ) | ( ( ir & 0xfe000000 ) >> 20 ); if( (addy & 0x800)!=0 ) addy |= 0xfffff000; - addy += rs1 - 0; + addy += rs1; rdid = 0; if( addy >= _buf.length-3 ) { @@ -158,9 +160,10 @@ public class EvalRisc5 { rval = addy; } else { switch( ( ir >> 12 ) & 0x7 ) { //SB, SH, SW - case 0: st1( addy, rs2 ); break; - case 1: st2( addy, rs2 ); break; - case 2: st4( addy, rs2 ); break; + case 0: st1( addy, (int)rs2 ); break; + case 1: st2( addy, (int)rs2 ); break; + case 2: st4( addy, (int)rs2 ); break; + case 3: st8( addy, rs2 ); break; default: trap = (2+1); } } @@ -170,9 +173,9 @@ public class EvalRisc5 { case 0x33: { // Op 0b0110011 int imm = ir >> 20; imm = imm | (( (imm & 0x800)!=0 ) ? 0xfffff000 : 0); - int rs1 = regs[(ir >> 15) & 0x1f]; + long rs1 = regs[(ir >> 15) & 0x1f]; boolean is_reg = (ir & 0x20)!=0; - int rs2 = is_reg ? regs[imm & 0x1f] : imm; + long rs2 = is_reg ? regs[imm & 0x1f] : imm; if( is_reg && ( ir & 0x02000000 )!=0 ) { switch( (ir>>12)&7 ) { //0x02000000 = RV32M @@ -208,8 +211,8 @@ public class EvalRisc5 { break; case 0x2f: { // RV32A (0b00101111) - int rs1 = regs[(ir >> 15) & 0x1f]; - int rs2 = regs[(ir >> 20) & 0x1f]; + long rs1 = regs[(ir >> 15) & 0x1f]; + long rs2 = regs[(ir >> 20) & 0x1f]; int irmid = ( ir>>27 ) & 0x1f; // We don't implement load/store from UART or CLNT with RV32A here. @@ -217,14 +220,14 @@ public class EvalRisc5 { trap = (7+1); //Store/AMO access fault rval = rs1; } else { - rval = ld4s( rs1 ); + rval = ld4s( (int)rs1 ); // Referenced a little bit of https://github.com/franzflasch/riscv_em/blob/master/src/core/core.c boolean dowrite = true; switch( irmid ) { case 2: //LR.W (0b00010) dowrite = false; - _extraflags = (_extraflags & 0x07) | (rs1<<3); + _extraflags = (_extraflags & 0x07) | (int)(rs1<<3); break; case 3: { //SC.W (0b00011) (Make sure we have a slot, and, it's valid) boolean xflag = _extraflags >> 3 != ( rs1 & 0x1fffffff ); @@ -243,7 +246,7 @@ public class EvalRisc5 { case 28: rs2 = Math.max( rs2, rval ); break; //AMOMAXU.W (0b11100) default: trap = (2+1); dowrite = false; break; //Not supported. } - if( dowrite ) st4( rs1, rs2 ); + if( dowrite ) st4( (int)rs1, (int)rs2 ); } break; } diff --git a/chapter21/src/test/java/com/seaofnodes/simple/TestRisc5.java b/chapter21/src/test/java/com/seaofnodes/simple/TestRisc5.java index 29be1814..275cdebb 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/TestRisc5.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/TestRisc5.java @@ -10,12 +10,12 @@ import java.io.IOException; // Runs 32-bit R5 code in an emulator public abstract class TestRisc5 { - public static EvalRisc5 run( String file, int steps, int arg ) throws IOException { - return run("src/test/java/com/seaofnodes/simple/progs",file,steps, arg); + public static EvalRisc5 build( String file, int arg ) throws IOException { + return build("src/test/java/com/seaofnodes/simple/progs",file, arg); } // Compile and run a simple program - public static EvalRisc5 run( String dir, String file, int steps, int arg ) throws IOException { + public static EvalRisc5 build( String dir, String file, int arg ) throws IOException { // Compile and export Simple String src = Files.readString(Path.of(dir+"/"+file+".smp")); CodeGen code = new CodeGen(src).parse().opto().typeCheck().instSelect( "riscv", "SystemV").GCM().localSched().regAlloc().encode(); @@ -32,11 +32,7 @@ public abstract class TestRisc5 { // Initial incoming int arg R5.regs[riscv.A0] = arg; // malloc memory starts at 64K and goes up - - // Run until stopped or steps - int trap = R5.step(steps); - Assert.assertEquals(0,trap); // Exit for steps, not trap - return R5; } + } diff --git a/chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.c b/chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.c index 9efc7d5b..bf981afd 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.c +++ b/chapter21/src/test/java/com/seaofnodes/simple/progs/brain_fuck.c @@ -11,7 +11,7 @@ extern AryInt* brain_fuck(); int main() { AryInt* ps = brain_fuck(); - printf("%.*s", ps->len, ps->data); + printf("%.*s", ps->len, ps->data); return 0; }
\ No newline at end of file diff --git a/chapter21/src/test/java/com/seaofnodes/simple/progs/person.smp b/chapter21/src/test/java/com/seaofnodes/simple/progs/person.smp index 9791f252..9f0f5bea 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/progs/person.smp +++ b/chapter21/src/test/java/com/seaofnodes/simple/progs/person.smp @@ -4,7 +4,6 @@ struct Person { }; val fcn = { Person?[] ps, int x -> - val tmp = ps[x]; if( ps[x] ) ps[x].age++; };
\ No newline at end of file |
