diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index 4cff6ae5..f2c700e6 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -11,6 +11,7 @@ --- ## HEAD - `PS` initialized now with `000000` (see [ECO-028](ECO-028-ps_init.md)) +- `CPUERR` cleared with cpu reset (see [ECO-029](ECO-029-cpuerr_creset.md)) --- diff --git a/doc/ECO-028-ps_init.md b/doc/ECO-028-ps_init.md index bf31fada..e64a01c0 100644 --- a/doc/ECO-028-ps_init.md +++ b/doc/ECO-028-ps_init.md @@ -23,6 +23,6 @@ See the full story in the exhaustive commit message for Hopefully none. All `ibus` devices come up with interrupts disabled, so there shouldn't be any spurious interrupts at start-up. -### Provisos +### Hindsights Even a very plausible behavior like _"disable all interrupts at power on"_ can be the incorrect one. diff --git a/doc/ECO-029-cpuerr_creset.md b/doc/ECO-029-cpuerr_creset.md new file mode 100644 index 00000000..47c84a50 --- /dev/null +++ b/doc/ECO-029-cpuerr_creset.md @@ -0,0 +1,18 @@ +# ECO-029: `CPUERR` cleared by cpu reset (2016-12-27) + +### Scope +- Was in w11a from the very beginning +- Affects: all w11a systems + +### Symptom summary +- the `cpuerr` register is not cleared by a `$cpu cp -creset` command +- the `cpuerr` status can affect cpu behaviour, e.g. yellow stack traps are + only taken when the corresponding `cpuerr` flag is not set +- this makes tbench test execution on FPGA potentially depending on pre-history + +### Fixes +Changed `pdp11_sequencer.vhd` to clear `cpuerr` with both general reset and +with cpu reset. + +### Side effects +None because this affects a very early phase of system startup. diff --git a/rtl/w11a/pdp11_sequencer.vhd b/rtl/w11a/pdp11_sequencer.vhd index 6dea3360..4afdad76 100644 --- a/rtl/w11a/pdp11_sequencer.vhd +++ b/rtl/w11a/pdp11_sequencer.vhd @@ -1,4 +1,4 @@ --- $Id: pdp11_sequencer.vhd 812 2016-10-03 18:39:50Z mueller $ +-- $Id: pdp11_sequencer.vhd 831 2016-12-27 16:51:12Z mueller $ -- -- Copyright 2006-2016 by Walter F.J. Mueller -- @@ -18,10 +18,11 @@ -- Dependencies: ib_sel -- Test bench: tb/tb_pdp11_core (implicit) -- Target Devices: generic --- Tool versions: ise 8.2-14.7; viv 2014.4-2016.1; ghdl 0.18-0.33 +-- Tool versions: ise 8.2-14.7; viv 2014.4-2016.2; ghdl 0.18-0.33 -- -- Revision History: -- Date Rev Version Comment +-- 2016-12-27 831 1.6.8 CPUERR now cleared with creset -- 2016-10-03 812 1.6.7 always define DM_STAT_SE.snum -- 2016-05-26 768 1.6.6 don't init N_REGS (vivado fix for fsm inference) -- proc_snum conditional (vivado fsm workaround) @@ -303,18 +304,28 @@ begin if rising_edge(CLK) then if GRESET = '1' then R_STATUS <= cpustat_init; - R_CPUERR <= cpuerr_init; R_IDSTAT <= decode_stat_init; R_VMSTAT <= vm_stat_init; else R_STATUS <= N_STATUS; - R_CPUERR <= N_CPUERR; R_IDSTAT <= N_IDSTAT; R_VMSTAT <= VM_STAT; end if; end if; end process proc_status; + -- ensure that CPUERR is reset with GRESET and CRESET + proc_cpuerr: process (CLK) + begin + if rising_edge(CLK) then + if GRESET = '1' or R_STATUS.creset = '1' then + R_CPUERR <= cpuerr_init; + else + R_CPUERR <= N_CPUERR; + end if; + end if; + end process proc_cpuerr; + proc_state: process (CLK) begin if rising_edge(CLK) then diff --git a/rtl/w11a/tb/tb_pdp11core_stim.dat b/rtl/w11a/tb/tb_pdp11core_stim.dat index 392d4540..f0b7baad 100644 --- a/rtl/w11a/tb/tb_pdp11core_stim.dat +++ b/rtl/w11a/tb/tb_pdp11core_stim.dat @@ -1,4 +1,4 @@ -# $Id: tb_pdp11core_stim.dat 829 2016-12-26 18:56:17Z mueller $ +# $Id: tb_pdp11core_stim.dat 831 2016-12-27 16:51:12Z mueller $ # # Revision History: # Date Rev Version Comment @@ -331,7 +331,7 @@ bwm 8 001000 -- 1000 100000 base 001200 -- 1200 120000 base 001400 -- 1400 140000 base - 177600 -- 176000 (map to I/O page) + 177600 -- 177600 (map to I/O page) #----------------------------------------------------------------------------- C Setup code 1 [base 2100] (very basics: cont,start; 'simple' instructions) # diff --git a/tools/asm-11/README.md b/tools/asm-11/README.md new file mode 100644 index 00000000..90fa73c4 --- /dev/null +++ b/tools/asm-11/README.md @@ -0,0 +1,8 @@ +This directory tree contains the **environment for asm-11 assembler** +and is organized in + +| Directory | Content | +| --------- | ------- | +| [lib](lib) | macro and routine library | +| [tests](tests) | asm-11 test suite | +| [tests-err](tests-err) | asm-11 test suite (error resonse part) | diff --git a/tools/asm-11/lib/mminki.mac b/tools/asm-11/lib/mminki.mac new file mode 100644 index 00000000..6470d21f --- /dev/null +++ b/tools/asm-11/lib/mminki.mac @@ -0,0 +1,46 @@ +; $Id: mminki.mac 831 2016-12-27 16:51:12Z mueller $ +; Copyright 2016- by Walter F.J. Mueller +; License disclaimer see License.txt in $RETROBASE directory +; +; Initialize MMU, kernel I space only +; Call: +; jsr pc, mminki +; Arguments: +; none +; Expected includes: +; lib/defs_mmu.mac +; +; All registers preserved +; + +mminki: + mov r0,-(sp) ; save regs + mov r1,-(sp) +; + mov #kipdr,r0 ; kerel I space DR + mov #077406,r1 ; slf=127; ed=0(up); acf=6(w/r) +; + mov r1,(r0)+ ; kipdr(0) + mov r1,(r0)+ ; kipdr(1) + mov r1,(r0)+ ; kipdr(2) + mov r1,(r0)+ ; kipdr(3) + mov r1,(r0)+ ; kipdr(4) + mov r1,(r0)+ ; kipdr(5) + mov r1,(r0)+ ; kipdr(6) + mov r1,(r0)+ ; kipdr(7) +; + mov #kipar,r0 ; kernel I space AR +; + mov #000000,(r0)+ ; kipar(0): 200 000000 base + mov #000200,(r0)+ ; kipar(0): 400 020000 base + mov #000400,(r0)+ ; kipar(0): 600 040000 base + mov #000600,(r0)+ ; kipar(0): 1000 060000 base + mov #001000,(r0)+ ; kipar(0): 1200 100000 base + mov #001200,(r0)+ ; kipar(0): 1400 120000 base + mov #001400,(r0)+ ; kipar(0): 1600 140000 base + mov #177600,(r0)+ ; kipar(0): 177600 (map to I/O page) +; + mov (sp)+,r1 ; restore regs + mov (sp)+,r0 +; + rts pc diff --git a/tools/bin/asm-11 b/tools/bin/asm-11 index f8eff277..8896907f 100755 --- a/tools/bin/asm-11 +++ b/tools/bin/asm-11 @@ -1,5 +1,5 @@ #!/usr/bin/perl -w -# $Id: asm-11 712 2015-11-01 22:53:45Z mueller $ +# $Id: asm-11 831 2016-12-27 16:51:12Z mueller $ # # Copyright 2013-2015 by Walter F.J. Mueller # @@ -1314,17 +1314,17 @@ sub eval_exp { my $v2 = pop @val; my $v1 = pop @val; return undef unless defined $v1 && defined $v2; - if ($bop eq '+') { + if ($bop eq '+') { # '+': addition push @val, int($v1) + int($v2); - } elsif ($bop eq '-') { + } elsif ($bop eq '-') { # '-': subtraction push @val, int($v1) - int($v2); - } elsif ($bop eq '*') { + } elsif ($bop eq '*') { # '*': multiplication push @val, int($v1) * int($v2); - } elsif ($bop eq '/') { + } elsif ($bop eq '/') { # '/': division push @val, int(int($v1) / int($v2)); - } elsif ($bop eq '&') { + } elsif ($bop eq '&') { # '&': bit-wise and push @val, int($v1) & int($v2); - } elsif ($bop eq '!') { + } elsif ($bop eq '!') { # '!': bit-wise or push @val, int($v1) | int($v2); } else { die "BUGCHECK: tag='OP(b)', val='$bop'\n"; diff --git a/tools/tbench/README.md b/tools/tbench/README.md new file mode 100644 index 00000000..3de39e17 --- /dev/null +++ b/tools/tbench/README.md @@ -0,0 +1,10 @@ +This directory tree contains the **w11 test bench** and is organized in + +| Directory | Content | +| --------- | ------- | +| [cp](cp) | test of CPU control port | +| [rhrp](rhrp) | test of `rhrp` ibus device | +| [tm11](tm11) | test of `tm11` ibus devive | +| [w11a](w11a) | test of CPU core | +| [w11a_cmon](w11a_cmon) | test of CPU `cmon` unit (cpu monitor) | +| [w11a_hbpt](w11a_hbpt) | test of CPU `hbpt` unit (hardware breakpoint) | diff --git a/tools/tbench/w11a/test_w11a_cpuerr.tcl b/tools/tbench/w11a/test_w11a_cpuerr.tcl new file mode 100644 index 00000000..091d7aab --- /dev/null +++ b/tools/tbench/w11a/test_w11a_cpuerr.tcl @@ -0,0 +1,223 @@ +# $Id: test_w11a_cpuerr.tcl 831 2016-12-27 16:51:12Z mueller $ +# +# Copyright 2016- by Walter F.J. Mueller +# License disclaimer see License.txt in $RETROBASE directory +# +# Revision History: +# Date Rev Version Comment +# 2016-12-27 831 1.0 Initial version +# +# Test cpuerr register +# + +# ---------------------------------------------------------------------------- +rlc log "test_w11a_cpuerr: test cpuerr register" +rlc log " test basic CPUERR semantics" + +$cpu ldasm -lst lst -sym sym { + .include |lib/defs_cpu.mac| + .include |lib/defs_reg70.mac| + .include |lib/defs_mmu.mac| +; + .include |lib/vec_cpucatch.mac| +; + . = 1000 +stack: +start: +; +; test 001: first test that any write will clear cpuerr ---------------------- +; that test also conveniently erases any pre-history +; + mov #177777,@#cpuerr ; clear cpuerr + mov #001,(r5)+ ; tag + mov @#cpuerr,(r5)+ ; val +; +; test 002: odd address abort, will set bit cp.aer --------------------------- +; + mov @#v..iit,saviit ; save old handler + mov #h.iit,@#v..iit ; setup handler + mov #t.002,r4 ; setup continuation address + mov #1,r0 ; r0 points to odd address + tst (r0) ; access + ; !! will trap to 004 and set 000100 !! + halt ; blocker +t.002: +; +; test 003: clear cpuerr again (now it's really set) ------------------------- +; + mov #177777,@#cpuerr ; clear cpuerr + mov #003,(r5)+ ; tag + mov @#cpuerr,(r5)+ ; val +; +; test 004: non-existent memory abort, will set bit cp.nxm ------------------- +; +; The address space jusr below the I/O page is never accessible in the +; w11 (the 11/70 has ubmap window in this addess space). +; So setup MMU kernel I space AR(6) to point to the 8 kbyte below I/O page +; don't clear CPUERR at end of test ! +; + jsr pc, mminki ; init MMU, kernel I space only + mov #177400,@#kipar+014 ; kipar(6): to page below I/O page + mov #m3.e22,@#ssr3 ; enable 22bit + mov #m0.ena,@#ssr0 ; enable MMU +; + mov #t.004,r4 ; setup continuation address + mov #140000,r0 ; r0 points to non-existent memory + tst (r0) ; access + ; !! will trap to 004 and set 000040 !! + halt ; blocker +t.004: clr @#ssr0 ; disable MMU +; +; test 005: I/O bus timeout abort; will set bit cp.ito ----------------------- +; +; The lowest I/O page address 160000 not occupied by a device in the w11. +; Since CPUERR wasn't cleared after previous test the error bits will +; accumulate +; + mov #t.005,r4 ; setup continuation address + mov #160000,r0 ; r0 points to non-existent device + tst (r0) ; access + ; !! will trap to 004 and set 000020 !! + halt ; blocker +t.005: +; +; test 006: HALT in user mode; will set bit cp.hlt --------------------------- +; + mov #h.hlt,@#v..iit ; setup handler + mov #cp.cmu!cp.pmu,@#cp.psw ; psw: cmode=pmode=11 (user) + mov #t.006,r4 ; setup continuation address +1$: halt + br 1$ ; blocker +t.006: +; clear cpuerr again + mov #177777,@#cpuerr ; clear cpuerr + mov #006,(r5)+ ; tag + mov @#cpuerr,(r5)+ ; val +; +; test 007: yellow stack trap; will set bit cp.ysv --------------------------- +; + mov #h.iit,@#v..iit ; setup handler + mov #t.007,r4 ; setup continuation address + mov #000400,sp ; set stack into 'yellow' zone + clr -(sp) ; and push to stack + ; push will be done plus a trap ! +t.007: +; +; test 010: 2nd yellow stack trap with CPUERR set should *not* trap ---------- +; + mov saviit,@#v..iit ; restore blocker handler + clr -(sp) ; and push to stack + ; push will be done and no trap ! + mov #010,(r5)+ ; tag + mov sp,(r5)+ ; val +; clear cpuerr again + mov #177777,@#cpuerr ; clear cpuerr + mov #010,(r5)+ ; tag + mov @#cpuerr,(r5)+ ; val +; +; test 011: red stack trap from odd stack; will set bit cp.aer and cp.rsv ---- +; + mov #h.rsv,@#v..iit ; setup handler (will also reset stack) + mov #t.011,r4 ; setup continuation address + mov #001001,sp ; set stack odd kernel stack + clr -(sp) ; and push to stack + ; cause 'red stack' and set SP=004 +t.011: +; clear cpuerr again + mov #177777,@#cpuerr ; clear cpuerr + mov #011,(r5)+ ; tag + mov @#cpuerr,(r5)+ ; val +; +; end of tests --------------------------------------------------------------- +; + halt +stop: +; +h.iit: mov r4,(r5)+ ; tag + mov @#cpuerr,(r5)+ ; val + mov r4,(sp) ; set return PC + rti +; +h.hlt: mov r4,(r5)+ ; tag + mov @#cpuerr,(r5)+ ; val + mov r4,(sp) ; set return PC + clr 2(sp) ; set return PS (kernel mode again) + rti +; +h.rsv: mov r4,(r5)+ ; tag + mov @#cpuerr,(r5)+ ; val + mov #1000,sp ; reset stack + clr -(sp) ; PS = kernel mode + mov r4,-(sp) ; PC = continuation address + rti +; +saviit: .word 0 +data: .blkw 12.*2. + .word 177777 +; +; support procedures +; + .include |lib/mminki.mac| + +} + +# puts $lst +# parray sym + +# code register pre/post conditions beyond defaults +# r5 #data -> #data+12*2*2 +rw11::asmrun $cpu sym r5 $sym(data) +rw11::asmwait $cpu sym + +rw11::asmtreg $cpu r1 0 \ + r2 0 \ + r3 0 \ + r5 [expr {$sym(data) + 12*2*2}] \ + sp $sym(stack) +# data: tag val pairs +rw11::asmtmem $cpu $sym(data) \ + [list 001 0000000 \ + $sym(t.002) [regbld rw11::CPUERR adderr] \ + 003 0000000 \ + $sym(t.004) [regbld rw11::CPUERR nxm] \ + $sym(t.005) [regbld rw11::CPUERR nxm iobto] \ + $sym(t.006) 0000260 \ + 006 0000000 \ + $sym(t.007) [regbld rw11::CPUERR ysv] \ + 010 0000374 \ + 010 0000000 \ + $sym(t.011) [regbld rw11::CPUERR adderr rsv] \ + 011 0000000 \ + 0177777 ] + +# ---------------------------------------------------------------------------- +rlc log " test basic CPUERR reset via creset" + +# use minmal code to set CPUERR: odd address abort against vector catcher +$cpu ldasm -lst lst -sym sym { + . = 000004 +v..iit: .word v..iit+2 ; vec 4 + .word 0 +stop: +; + . = 1000 +stack: +start: +; + mov #1,r0 ; r0 points to odd address + tst (r0) ; access +} + +rw11::asmrun $cpu sym +rw11::asmwait $cpu sym + +rw11::asmtreg $cpu r1 0 \ + r2 0 \ + r3 0 \ + r5 0 \ + sp [expr $sym(stack) - 4] + +# now test whether creset clears CPUERR +rw11::asmtmem $cpu $rw11::A_CPUERR [regbld rw11::CPUERR adderr] +cpu0 cp -creset +rw11::asmtmem $cpu $rw11::A_CPUERR 0 diff --git a/tools/tbench/w11a/w11a_all.dat b/tools/tbench/w11a/w11a_all.dat index 8e6a35e5..54181f76 100644 --- a/tools/tbench/w11a/w11a_all.dat +++ b/tools/tbench/w11a/w11a_all.dat @@ -1,4 +1,4 @@ -# $Id: w11a_all.dat 683 2015-05-17 21:54:35Z mueller $ +# $Id: w11a_all.dat 831 2016-12-27 16:51:12Z mueller $ # ## steering file for all w11a tests # @@ -8,5 +8,7 @@ test_w11a_dstm_word_flow.tcl test_w11a_dsta_flow.tcl test_w11a_inst_traps.tcl # +test_w11a_cpuerr.tcl +# test_w11a_div.tcl #