From 785016763f0e33719ae714bb700f9b435e2069d8 Mon Sep 17 00:00:00 2001 From: wfjm Date: Wed, 24 Apr 2019 12:59:58 +0200 Subject: [PATCH] pc11_buf: buffered PC11; add lp11,pc11 mcodes --- doc/CHANGELOG.md | 2 + rtl/ibus/ibdlib.vhd | 20 + rtl/ibus/ibdr_maxisys.vbom | 1 + rtl/ibus/ibdr_maxisys.vhd | 24 +- rtl/ibus/ibdr_pc11.vhd | 29 +- rtl/ibus/ibdr_pc11_buf.vbom | 9 + rtl/ibus/ibdr_pc11_buf.vhd | 510 +++++++++++++++++++ rtl/sys_gen/w11a/nexys2/sys_w11a_n2.imfset | 3 +- rtl/sys_gen/w11a/nexys3/sys_w11a_n3.vhd | 3 +- rtl/sys_gen/w11a/nexys4/sys_w11a_n4.vhd | 3 +- rtl/sys_gen/w11a/s3board/sys_w11a_s3.imfset | 3 +- tools/mcode/README.md | 2 + tools/mcode/lp11/README.md | 5 + tools/mcode/lp11/lp11write.mac | 112 +++++ tools/mcode/pc11/Makefile | 31 ++ tools/mcode/pc11/README.md | 7 + tools/mcode/pc11/pc11copy.mac | 139 ++++++ tools/mcode/pc11/pc11read.mac | 118 +++++ tools/mcode/pc11/pc11write.mac | 108 +++++ tools/src/librw11/Rw11CntlPC11.cpp | 356 ++++++++++++-- tools/src/librw11/Rw11CntlPC11.hpp | 46 +- tools/src/librw11/Rw11CntlPC11.ipp | 75 +++ tools/src/librw11/Rw11UnitPC11.cpp | 15 +- tools/src/librw11/Rw11UnitPC11.hpp | 6 +- tools/src/librwxxtpp/RtclRw11CntlPC11.cpp | 18 +- tools/tbench/README.md | 2 + tools/tbench/dev_all.dat | 3 +- tools/tbench/pc11/pc11_all.dat | 7 + tools/tbench/pc11/test_pc11_loop.tcl | 129 +++++ tools/tbench/pc11/test_pc11_pp.tcl | 513 ++++++++++++++++++++ tools/tbench/pc11/test_pc11_pr.tcl | 404 +++++++++++++++ tools/tcl/ibd_pc11/util.tcl | 8 +- tools/tcl/rw11/util.tcl | 20 +- 33 files changed, 2666 insertions(+), 65 deletions(-) create mode 100644 rtl/ibus/ibdr_pc11_buf.vbom create mode 100644 rtl/ibus/ibdr_pc11_buf.vhd create mode 100644 tools/mcode/lp11/README.md create mode 100644 tools/mcode/lp11/lp11write.mac create mode 100644 tools/mcode/pc11/Makefile create mode 100644 tools/mcode/pc11/README.md create mode 100644 tools/mcode/pc11/pc11copy.mac create mode 100644 tools/mcode/pc11/pc11read.mac create mode 100644 tools/mcode/pc11/pc11write.mac create mode 100644 tools/src/librw11/Rw11CntlPC11.ipp create mode 100644 tools/tbench/pc11/pc11_all.dat create mode 100644 tools/tbench/pc11/test_pc11_loop.tcl create mode 100644 tools/tbench/pc11/test_pc11_pp.tcl create mode 100644 tools/tbench/pc11/test_pc11_pr.tcl diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index e20bd329..5b74f2ad 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -29,12 +29,14 @@ The full set of tests is only run for tagged releases. - ibd_ibtst: ibus tester device - ib_rlim_{gen,slv}: new modules for implementation of rate limiters - ibdr_lp11_buf: new LP11 interface with fifo buffering + - ibdr_pc11_buf: new PC11 interface with fifo buffering - simclkv: test bench clock generator with variable period - new verification codes - w11a_ibtst/*: tbench for ibd_ibtst - w11a_ibmon/*: tbench for ibd_ibmon - w11a/test_w11a_sdreg.tcl: tbench for sdreg - test_lp11_all.tcl: tbench for lp11 and lp11_buf + - test_pc11_*.tcl: tbench for pc11 and pc11_buf - new test and demonstration codes under tools/mcode - dl11/dl11echo.mac: console interface echo tester - sys/blink.mac: 'blinking lights' demo (rsx,bsd and other modes) diff --git a/rtl/ibus/ibdlib.vhd b/rtl/ibus/ibdlib.vhd index aea0b2f1..43c98586 100644 --- a/rtl/ibus/ibdlib.vhd +++ b/rtl/ibus/ibdlib.vhd @@ -20,6 +20,7 @@ -- Revision History: -- Date Rev Version Comment -- 2019-04-14 1131 1.3.6 RLIM_CEV now slv8 +-- 2019-04-07 1129 1.3.5 add ibdr_pc11_buf -- 2019-04-07 1128 1.3.4 ibdr_dl11: use RLIM_CEV, drop CE_USEC -- 2019-03-09 1121 1.3.3 add ibdr_lp11_buf -- 2018-10-13 1055 1.3.2 update ibdr_maxisys (add IDEC port) @@ -255,6 +256,25 @@ component ibdr_pc11 is -- ibus dev(rem): PC11 ); end component; +component ibdr_pc11_buf is -- ibus dev(rem): PC11 (buffered) + -- fixed address: 177550 + generic ( + AWIDTH : natural := 5); -- fifo address width + port ( + CLK : in slbit; -- clock + RESET : in slbit; -- system reset + BRESET : in slbit; -- ibus reset + RLIM_CEV : in slv8; -- clock enable vector + RB_LAM : out slbit; -- remote attention + IB_MREQ : in ib_mreq_type; -- ibus request + IB_SRES : out ib_sres_type; -- ibus response + EI_REQ_PTR : out slbit; -- interrupt request, reader + EI_REQ_PTP : out slbit; -- interrupt request, punch + EI_ACK_PTR : in slbit; -- interrupt acknowledge, reader + EI_ACK_PTP : in slbit -- interrupt acknowledge, punch + ); +end component; + component ibdr_lp11 is -- ibus dev(rem): LP11 -- fixed address: 177514 port ( diff --git a/rtl/ibus/ibdr_maxisys.vbom b/rtl/ibus/ibdr_maxisys.vbom index 32b271ed..3d261f1c 100644 --- a/rtl/ibus/ibdr_maxisys.vbom +++ b/rtl/ibus/ibdr_maxisys.vbom @@ -15,6 +15,7 @@ ibdr_rk11.vbom ibdr_tm11.vbom ibdr_dl11.vbom ibdr_pc11.vbom +ibdr_pc11_buf.vbom ibdr_lp11.vbom ibdr_lp11_buf.vbom ibdr_sdreg.vbom diff --git a/rtl/ibus/ibdr_maxisys.vhd b/rtl/ibus/ibdr_maxisys.vhd index a3410e6d..4a0e03df 100644 --- a/rtl/ibus/ibdr_maxisys.vhd +++ b/rtl/ibus/ibdr_maxisys.vhd @@ -26,6 +26,7 @@ -- ibdr_tm11 -- ibdr_dl11 -- ibdr_pc11 +-- ibdr_pc11_buf -- ibdr_lp11 -- ibdr_lp11_buf -- ibdr_sdreg @@ -53,6 +54,7 @@ -- Date Rev Version Comment -- 2019-04-23 1136 1.6.6 add CLK port to ib_intmap24 -- 2019-04-14 1131 1.6.5 ib_rlim_gen has CPUSUSP port; RLIM_CEV now slv8 +-- 2019-04-07 1129 1.6.4 add ibdr_pc11_buf -- 2019-04-07 1127 1.6.3 ibdr_dl11: use RLIM_CEV, drop CE_USEC -- 2019-03-17 1123 1.6.2 add ib_rlim_gen, use with ibdr_lp11_buf -- 2019-03-09 1121 1.6.1 add ibdr_lp11_buf @@ -416,7 +418,7 @@ begin ); end generate DL11_1; - PC11: if sys_conf_ibd_pc11 >= 0 generate + PC11: if sys_conf_ibd_pc11 = 0 generate begin PCA : ibdr_pc11 port map ( @@ -433,6 +435,26 @@ begin ); end generate PC11; + PC11BUF: if sys_conf_ibd_pc11 > 0 generate + begin + PCA : ibdr_pc11_buf + generic map ( + AWIDTH => sys_conf_ibd_pc11) + port map ( + CLK => CLK, + RESET => RESET, + BRESET => BRESET, + RLIM_CEV => RLIM_CEV, + RB_LAM => RB_LAM_PC11, + IB_MREQ => IB_MREQ, + IB_SRES => IB_SRES_PC11, + EI_REQ_PTR => EI_REQ_PC11PTR, + EI_REQ_PTP => EI_REQ_PC11PTP, + EI_ACK_PTR => EI_ACK_PC11PTR, + EI_ACK_PTP => EI_ACK_PC11PTP + ); + end generate PC11BUF; + LP11: if sys_conf_ibd_lp11 = 0 generate begin LPA : ibdr_lp11 diff --git a/rtl/ibus/ibdr_pc11.vhd b/rtl/ibus/ibdr_pc11.vhd index 7df75043..14df3c39 100644 --- a/rtl/ibus/ibdr_pc11.vhd +++ b/rtl/ibus/ibdr_pc11.vhd @@ -1,4 +1,4 @@ --- $Id: ibdr_pc11.vhd 1126 2019-04-06 17:37:40Z mueller $ +-- $Id: ibdr_pc11.vhd 1137 2019-04-24 10:49:19Z mueller $ -- -- Copyright 2009-2019 by Walter F.J. Mueller -- @@ -27,6 +27,7 @@ -- -- Revision History: -- Date Rev Version Comment +-- 2019-04-24 1137 1.4.1 add rcsr.ir,ique,iack and pcsr.ir fields (rem) -- 2019-04-06 1126 1.4 for pc11_buf compat: pbuf.pval in bit 15 and 8; -- move rbusy reporting from pbuf to rbuf register -- 2013-05-04 515 1.3 BUGFIX: r.rbuf was immediately cleared ! Was broken @@ -77,6 +78,9 @@ architecture syn of ibdr_pc11 is constant rcsr_ibf_rbusy : integer := 11; constant rcsr_ibf_rdone : integer := 7; constant rcsr_ibf_rie : integer := 6; + constant rcsr_ibf_rir : integer := 5; + constant rcsr_ibf_ique : integer := 3; + constant rcsr_ibf_iack : integer := 2; constant rcsr_ibf_renb : integer := 0; constant rbuf_ibf_rbusy : integer := 15; @@ -84,6 +88,7 @@ architecture syn of ibdr_pc11 is constant pcsr_ibf_perr : integer := 15; constant pcsr_ibf_prdy : integer := 7; constant pcsr_ibf_pie : integer := 6; + constant pcsr_ibf_pir : integer := 5; constant pbuf_ibf_pval : integer := 15; constant pbuf_ibf_pval8 : integer := 8; @@ -96,6 +101,8 @@ architecture syn of ibdr_pc11 is rie : slbit; -- rcsr: reader interrupt enable rbuf : slv8; -- rbuf: rintreq : slbit; -- ptr interrupt request + rique : slbit; -- ptr interrupt queued (req set) + riack : slbit; -- ptr interrupt acknowledged perr : slbit; -- pcsr: punch error prdy : slbit; -- pcsr: punch ready pie : slbit; -- pcsr: punch interrupt enable @@ -108,7 +115,7 @@ architecture syn of ibdr_pc11 is '1', -- rerr (init=1!) '0','0','0', -- rbusy,rdone,rie (others=>'0'), -- rbuf - '0', -- rintreq + '0','0','0', -- rintreq,rique,riack '1', -- perr (init=1!) '1', -- prdy (init=1!) '0', -- pie @@ -183,6 +190,7 @@ begin IB_MREQ.din(rcsr_ibf_renb)='0' and -- when RENB not set (r.rerr='1' or r.rdone='1') then -- but err or done set n.rintreq := '1'; -- request interrupt + n.rique := '1'; -- and set que flag end if; else -- set IE to 0 n.rintreq := '0'; -- cancel interrupts @@ -193,16 +201,23 @@ begin n.rdone := '0'; -- clear done n.rbuf := (others=>'0'); -- clear buffer n.rintreq := '0'; -- cancel interrupt - ilam := '1'; -- rri lam + n.rique := '0'; -- and que flag + n.riack := '0'; -- and ack flag + ilam := '1'; -- rri lam else -- if in error state if r.rie = '1' then -- if interrupts on n.rintreq := '1'; -- request interrupt + n.rique := '1'; -- and set que flag end if; end if; end if; end if; else -- rri --------------------- + idout(rcsr_ibf_rir) := r.rintreq; + idout(rcsr_ibf_ique) := r.rique; + idout(rcsr_ibf_iack) := r.riack; + if ibw1 = '1' then n.rerr := IB_MREQ.din(rcsr_ibf_rerr); -- set ERR bit if IB_MREQ.din(rcsr_ibf_rerr)='1' -- if 0->1 transition @@ -211,6 +226,7 @@ begin n.rdone := '0'; -- clear done if r.rie = '1' then -- if interrupts on n.rintreq := '1'; -- request interrupt + n.rique := '1'; -- and set que flag end if; end if; end if; @@ -233,8 +249,9 @@ begin n.rbuf := IB_MREQ.din(n.rbuf'range); n.rbusy := '0'; n.rdone := '1'; - if r.rie = '1' then - n.rintreq := '1'; + if r.rie = '1' then -- if interrupts on + n.rintreq := '1'; -- request interrupt + n.rique := '1'; -- and set que flag end if; end if; end if; @@ -259,6 +276,7 @@ begin end if; else -- rri --------------------- + idout(pcsr_ibf_pir) := r.pintreq; if ibw1 = '1' then n.perr := IB_MREQ.din(pcsr_ibf_perr); -- set ERR bit if IB_MREQ.din(pcsr_ibf_perr)='1' -- if 0->1 transition @@ -307,6 +325,7 @@ begin -- other state changes if EI_ACK_PTR = '1' then n.rintreq := '0'; + n.riack := '1'; end if; if EI_ACK_PTP = '1' then n.pintreq := '0'; diff --git a/rtl/ibus/ibdr_pc11_buf.vbom b/rtl/ibus/ibdr_pc11_buf.vbom new file mode 100644 index 00000000..f5397bf9 --- /dev/null +++ b/rtl/ibus/ibdr_pc11_buf.vbom @@ -0,0 +1,9 @@ +# libs +../vlib/slvtypes.vhd +../vlib/memlib/memlib.vhd +iblib.vhd +# components +../vlib/memlib/fifo_simple_dram.vbom +ib_rlim_slv.vbom +# design +ibdr_pc11_buf.vhd diff --git a/rtl/ibus/ibdr_pc11_buf.vhd b/rtl/ibus/ibdr_pc11_buf.vhd new file mode 100644 index 00000000..14393a7b --- /dev/null +++ b/rtl/ibus/ibdr_pc11_buf.vhd @@ -0,0 +1,510 @@ +-- $Id: ibdr_pc11_buf.vhd 1137 2019-04-24 10:49:19Z mueller $ +-- +-- Copyright 2019- by Walter F.J. Mueller +-- +-- This program is free software; you may redistribute and/or modify it under +-- the terms of the GNU General Public License as published by the Free +-- Software Foundation, either version 3, or (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, but +-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY +-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-- for complete details. +-- +------------------------------------------------------------------------------ +-- Module Name: ibdr_pc11_buf - syn +-- Description: ibus dev(rem): PC11 +-- +-- Dependencies: fifo_simple_dram +-- ib_rlim_slv +-- Test bench: xxdp: zpcae0 +-- Target Devices: generic +-- Tool versions: ise 8.2-14.7; 2017.2; ghdl 0.35 +-- +-- Revision History: +-- Date Rev Version Comment +-- 2019-04-24 1137 1.0 Initial version +-- 2019-04-07 1129 0.1 First draft (derived from ibdr_pc11) +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.slvtypes.all; +use work.memlib.all; +use work.iblib.all; + +-- ---------------------------------------------------------------------------- +entity ibdr_pc11_buf is -- ibus dev(rem): PC11 + -- fixed address: 177550 + generic ( + AWIDTH : natural := 5); -- fifo address width + port ( + CLK : in slbit; -- clock + RESET : in slbit; -- system reset + BRESET : in slbit; -- ibus reset + RLIM_CEV : in slv8; -- clock enable vector + RB_LAM : out slbit; -- remote attention + IB_MREQ : in ib_mreq_type; -- ibus request + IB_SRES : out ib_sres_type; -- ibus response + EI_REQ_PTR : out slbit; -- interrupt request, reader + EI_REQ_PTP : out slbit; -- interrupt request, punch + EI_ACK_PTR : in slbit; -- interrupt acknowledge, reader + EI_ACK_PTP : in slbit -- interrupt acknowledge, punch + ); +end ibdr_pc11_buf; + +architecture syn of ibdr_pc11_buf is + + constant ibaddr_pc11 : slv16 := slv(to_unsigned(8#177550#,16)); + + constant ibaddr_rcsr : slv2 := "00"; -- rcsr address offset + constant ibaddr_rbuf : slv2 := "01"; -- rbuf address offset + constant ibaddr_pcsr : slv2 := "10"; -- pcsr address offset + constant ibaddr_pbuf : slv2 := "11"; -- pbuf address offset + + constant rcsr_ibf_rerr : integer := 15; + subtype rcsr_ibf_rlim is integer range 14 downto 12; + constant rcsr_ibf_rbusy : integer := 11; + subtype rcsr_ibf_type is integer range 10 downto 8; + constant rcsr_ibf_rdone : integer := 7; + constant rcsr_ibf_rie : integer := 6; + constant rcsr_ibf_rir : integer := 5; + constant rcsr_ibf_rlb : integer := 4; + constant rcsr_ibf_ique : integer := 3; + constant rcsr_ibf_iack : integer := 2; + constant rcsr_ibf_fclr : integer := 1; + constant rcsr_ibf_renb : integer := 0; + + constant rbuf_ibf_rbusy : integer := 15; + subtype rbuf_ibf_rsize is integer range AWIDTH-1+8 downto 8; + subtype rbuf_ibf_psize is integer range AWIDTH-1 downto 0; + subtype rbuf_ibf_data is integer range 7 downto 0; + + constant pcsr_ibf_perr : integer := 15; + subtype pcsr_ibf_rlim is integer range 14 downto 12; + constant pcsr_ibf_prdy : integer := 7; + constant pcsr_ibf_pie : integer := 6; + constant pcsr_ibf_pir : integer := 5; + constant pcsr_ibf_rlb : integer := 4; + + constant pbuf_ibf_pval : integer := 15; + subtype pbuf_ibf_size is integer range AWIDTH-1+8 downto 8; + subtype pbuf_ibf_data is integer range 7 downto 0; + + type regs_type is record -- state registers + ibsel : slbit; -- ibus select + rerr : slbit; -- rcsr: reader error + rrlim : slv3; -- rcsr: reader rlim + rbusy : slbit; -- rcsr: reader busy + rdone : slbit; -- rcsr: reader done + rie : slbit; -- rcsr: reader interrupt enable + rintreq : slbit; -- ptr interrupt request + rique : slbit; -- ptr interrupt queued (req set) + riack : slbit; -- ptr interrupt acknowledged + perr : slbit; -- pcsr: punch error + prlim : slv3; -- pcsr: punch rlim + prdy : slbit; -- pcsr: punch ready + pie : slbit; -- pcsr: punch interrupt enable + pintreq : slbit; -- ptp interrupt request + end record regs_type; + + constant regs_init : regs_type := ( + '0', -- ibsel + '1', -- rerr (init=1!) + "000", -- rrlim + '0','0','0', -- rbusy,rdone,rie + '0','0','0', -- rintreq,rique,riack + '1', -- perr (init=1!) + "000", -- prlim + '1', -- prdy (init=1!) + '0', -- pie + '0' -- pintreq + ); + + constant c_size1 : slv(AWIDTH-1 downto 0) := slv(to_unsigned(1,AWIDTH)); + + signal R_REGS : regs_type := regs_init; + signal N_REGS : regs_type := regs_init; + + signal RBUF_CE : slbit := '0'; + signal RBUF_WE : slbit := '0'; + signal RBUF_DO : slv8 := (others=>'0'); + signal RBUF_RESET : slbit := '0'; + signal RBUF_EMPTY : slbit := '0'; + signal RBUF_FULL : slbit := '0'; + signal RBUF_SIZE : slv(AWIDTH-1 downto 0) := (others=>'0'); + + signal PBUF_CE : slbit := '0'; + signal PBUF_WE : slbit := '0'; + signal PBUF_DO : slv8 := (others=>'0'); + signal PBUF_RESET : slbit := '0'; + signal PBUF_EMPTY : slbit := '0'; + signal PBUF_FULL : slbit := '0'; + signal PBUF_SIZE : slv(AWIDTH-1 downto 0) := (others=>'0'); + + signal RRLIM_START : slbit := '0'; + signal RRLIM_BUSY : slbit := '0'; + signal PRLIM_START : slbit := '0'; + signal PRLIM_BUSY : slbit := '0'; + +begin + + assert AWIDTH>=4 and AWIDTH<=7 + report "assert(AWIDTH>=4 and AWIDTH<=7): unsupported AWIDTH" + severity failure; + + RBUF : fifo_simple_dram + generic map ( + AWIDTH => AWIDTH, + DWIDTH => 8) + port map ( + CLK => CLK, + RESET => RBUF_RESET, + CE => RBUF_CE, + WE => RBUF_WE, + DI => IB_MREQ.din(rbuf_ibf_data), + DO => RBUF_DO, + EMPTY => RBUF_EMPTY, + FULL => RBUF_FULL, + SIZE => RBUF_SIZE + ); + + PBUF : fifo_simple_dram + generic map ( + AWIDTH => AWIDTH, + DWIDTH => 8) + port map ( + CLK => CLK, + RESET => PBUF_RESET, + CE => PBUF_CE, + WE => PBUF_WE, + DI => IB_MREQ.din(pbuf_ibf_data), + DO => PBUF_DO, + EMPTY => PBUF_EMPTY, + FULL => PBUF_FULL, + SIZE => PBUF_SIZE + ); + + RRLIM : ib_rlim_slv + port map ( + CLK => CLK, + RESET => RESET, + RLIM_CEV => RLIM_CEV, + SEL => R_REGS.rrlim, + START => RRLIM_START, + STOP => BRESET, + DONE => open, + BUSY => RRLIM_BUSY + ); + + PRLIM : ib_rlim_slv + port map ( + CLK => CLK, + RESET => RESET, + RLIM_CEV => RLIM_CEV, + SEL => R_REGS.prlim, + START => PRLIM_START, + STOP => BRESET, + DONE => open, + BUSY => PRLIM_BUSY + ); + + proc_regs: process (CLK) + begin + if rising_edge(CLK) then + if BRESET = '1' then -- BRESET is 1 for system and ibus reset + R_REGS <= regs_init; -- + if RESET = '0' then -- if RESET=0 we do just an ibus reset + R_REGS.rerr <= N_REGS.rerr; -- keep RERR flag + R_REGS.rrlim <= N_REGS.rrlim; -- keep RRLIM flag + R_REGS.perr <= N_REGS.perr; -- keep PERR flag + R_REGS.prlim <= N_REGS.prlim; -- keep PRLIM flag + end if; + else + R_REGS <= N_REGS; + end if; + end if; + end process proc_regs; + + proc_next : process (R_REGS, IB_MREQ, EI_ACK_PTR, EI_ACK_PTP, RESET, BRESET, + RBUF_DO, RBUF_EMPTY, RBUF_FULL, RBUF_SIZE, RRLIM_BUSY, + PBUF_DO, PBUF_EMPTY, PBUF_FULL, PBUF_SIZE, PRLIM_BUSY) + variable r : regs_type := regs_init; + variable n : regs_type := regs_init; + variable idout : slv16 := (others=>'0'); + variable ibreq : slbit := '0'; + variable iback : slbit := '0'; + variable ibrd : slbit := '0'; + variable ibw0 : slbit := '0'; + variable ibw1 : slbit := '0'; + variable ilam : slbit := '0'; + variable irbufce : slbit := '0'; + variable irbufwe : slbit := '0'; + variable irbufrst : slbit := '0'; + variable irrlimsta : slbit := '0'; + variable ipbufce : slbit := '0'; + variable ipbufwe : slbit := '0'; + variable iprlimsta : slbit := '0'; + begin + + r := R_REGS; + n := R_REGS; + + idout := (others=>'0'); + ibreq := IB_MREQ.re or IB_MREQ.we; + iback := r.ibsel and ibreq; + ibrd := IB_MREQ.re; + ibw0 := IB_MREQ.we and IB_MREQ.be0; + ibw1 := IB_MREQ.we and IB_MREQ.be1; + ilam := '0'; + irbufce := '0'; + irbufwe := '0'; + irbufrst := RESET or r.rerr; + irrlimsta := '0'; + ipbufce := '0'; + ipbufwe := '0'; + iprlimsta := '0'; + + -- ibus address decoder + n.ibsel := '0'; + if IB_MREQ.aval='1' and + IB_MREQ.addr(12 downto 3)=ibaddr_pc11(12 downto 3) then + n.ibsel := '1'; + end if; + + -- ibus transactions + if r.ibsel = '1' then + case IB_MREQ.addr(2 downto 1) is + + when ibaddr_rcsr => -- RCSR -- reader control status ----- + + idout(rcsr_ibf_rerr) := r.rerr; + idout(rcsr_ibf_rbusy) := r.rbusy; + idout(rcsr_ibf_rdone) := r.rdone; + idout(rcsr_ibf_rie) := r.rie; + + if IB_MREQ.racc = '0' then -- cpu --------------------- + if ibw0 = '1' then + n.rie := IB_MREQ.din(rcsr_ibf_rie); + if IB_MREQ.din(rcsr_ibf_rie) = '1' then-- set IE to 1 + if r.rie = '0' and -- IE 0->1 transition + IB_MREQ.din(rcsr_ibf_renb)='0' and -- when RENB not set + (r.rerr='1' or r.rdone='1') then -- but err or done set + n.rintreq := '1'; -- request interrupt + n.rique := '1'; -- and set que flag + end if; + else -- set IE to 0 + n.rintreq := '0'; -- cancel interrupts + end if; + if IB_MREQ.din(rcsr_ibf_renb) = '1' then -- set RENB + if r.rerr = '0' then -- if not in error state + n.rbusy := '1'; -- set busy + n.rintreq := '0'; -- cancel interrupt + n.rique := '0'; -- and que flag + n.riack := '0'; -- and ack flag + irrlimsta := '1'; -- start reader timer + else -- if in error state + if r.rie = '1' then -- if interrupts on + n.rintreq := '1'; -- request interrupt + n.rique := '1'; -- and set que flag + end if; + end if; + end if; + end if; + + else -- rri --------------------- + idout(rcsr_ibf_rlim) := r.rrlim; + idout(rcsr_ibf_type) := slv(to_unsigned(AWIDTH,3)); + idout(rcsr_ibf_rir) := r.rintreq; + idout(rcsr_ibf_rlb) := RRLIM_BUSY; + idout(rcsr_ibf_ique) := r.rique; + idout(rcsr_ibf_iack) := r.riack; + + if ibw1 = '1' then + n.rerr := IB_MREQ.din(rcsr_ibf_rerr); -- set ERR bit + n.rrlim := IB_MREQ.din(rcsr_ibf_rlim); -- set RLIM field + if IB_MREQ.din(rcsr_ibf_rerr)='1' -- if 0->1 transition + and r.rerr='0' and r.rie = '1' then -- and interrupts on + n.rintreq := '1'; -- request interrupt + n.rique := '1'; -- and set que flag + end if; + end if; + if ibw0 = '1' then + if IB_MREQ.din(rcsr_ibf_fclr) = '1' then -- 1 written to FCLR + irbufrst := '1'; -- then reset fifo + end if; + end if; + end if; + + when ibaddr_rbuf => -- RBUF -- reader data buffer -------- + + if IB_MREQ.racc = '0' then -- cpu --------------------- + -- the PC11 clears the reader data buffer when read (unusual!!) + -- this is emulated by returning fifo data only when DONE=1 + if r.rdone = '1' then + idout(rbuf_ibf_data) := RBUF_DO; + end if; + if ibreq = '1' then -- !! PC11 is unusual !! + n.rdone := '0'; -- *any* read or write will clear done + n.rintreq := '0'; -- also interrupt is canceled + if r.rdone = '1' then -- data available + irbufce := '1'; -- read next value from fifo + irbufwe := '0'; + if RBUF_SIZE = c_size1 then -- last value (size=1) + ilam := '1'; -- rri lam + end if; + end if; + end if; + + else -- rri --------------------- + idout(rbuf_ibf_rbusy) := r.rbusy; + idout(rbuf_ibf_rsize) := RBUF_SIZE; + idout(rbuf_ibf_psize) := PBUF_SIZE; + if ibw0 = '1' then + if RBUF_FULL = '0' then -- fifo not full + irbufce := '1'; -- write to fifo + irbufwe := '1'; + else -- write to full fifo + iback := '0'; -- signal nak + end if; + end if; + end if; + + when ibaddr_pcsr => -- PCSR -- punch control status ------ + + idout(pcsr_ibf_perr) := r.perr; + idout(pcsr_ibf_prdy) := r.prdy; + idout(pcsr_ibf_pie) := r.pie; + + if IB_MREQ.racc = '0' then -- cpu --------------------- + if ibw0 = '1' then + n.pie := IB_MREQ.din(pcsr_ibf_pie); + if IB_MREQ.din(pcsr_ibf_pie) = '1' then-- set IE to 1 + if r.pie='0' and -- IE 0->1 transition + (r.perr='1' or r.prdy='1') then -- but err or done set + n.pintreq := '1'; -- request interrupt + end if; + else -- set IE to 0 + n.pintreq := '0'; -- cancel interrupts + end if; + end if; + + else -- rri --------------------- + idout(pcsr_ibf_rlim) := r.prlim; + idout(pcsr_ibf_pir) := r.pintreq; + idout(pcsr_ibf_rlb) := PRLIM_BUSY; + + if ibw1 = '1' then + n.perr := IB_MREQ.din(pcsr_ibf_perr); -- set ERR bit + n.prlim := IB_MREQ.din(pcsr_ibf_rlim); -- set RLIM field + if IB_MREQ.din(pcsr_ibf_perr)='1' -- if 0->1 transition + and r.perr='0' then + n.prdy := '1'; -- set ready + if r.pie = '1' then -- if interrupts on + n.pintreq := '1'; -- request interrupt + end if; + end if; + end if; + end if; + + when ibaddr_pbuf => -- PBUF -- punch data buffer --------- + + if IB_MREQ.racc = '0' then -- cpu --------------------- + if ibw0 = '1' then + if r.perr = '0' then -- if not in error state + iprlimsta := '1'; -- start puncher timer + if r.prdy = '1' then -- ignore buf write when rdy=0 + if PBUF_FULL = '0' then -- fifo not full + ipbufce := '1'; -- write to fifo + ipbufwe := '1'; + if PBUF_EMPTY = '1' then -- first write to empty fifo + ilam := '1'; -- request attention + end if; + end if; + end if; + else -- if in error state + if r.pie = '1' then -- if interrupts on + n.pintreq := '1'; -- request interrupt + end if; + end if; + end if; + + else -- rri --------------------- + idout(pbuf_ibf_pval) := not PBUF_EMPTY; + idout(pbuf_ibf_size) := PBUF_SIZE; + idout(pbuf_ibf_data) := PBUF_DO; + if ibrd = '1' then + if PBUF_EMPTY = '0' then -- fifo not empty + ipbufce := '1'; -- read from fifo + ipbufwe := '0'; + else -- read from empty fifo + iback := '0'; -- signal nak + end if; + end if; + end if; + + when others => null; + end case; + + end if; + + -- other state changes + if EI_ACK_PTR = '1' then + n.rintreq := '0'; + n.riack := '1'; + end if; + if EI_ACK_PTP = '1' then + n.pintreq := '0'; + end if; + + if (RRLIM_BUSY or RBUF_EMPTY) ='1' then -- timer busy or fifo empty + n.rdone := '0'; -- clear done + else -- timer not busy and fifo not empty + if r.rbusy = '1' then -- reader enabled ? + n.rbusy := '0'; -- clear busy + n.rdone := '1'; -- set done + if r.rdone='0' and -- done going 0->1 + r.rerr='0' and r.rie='1' then -- and err=0 and ie=1 + n.rintreq := '1'; -- request interrupt + n.rique := '1'; -- and set que flag + end if; + end if; + end if; + + if (PRLIM_BUSY or PBUF_FULL) ='1' then -- busy or fifo full + n.prdy := '0'; -- clear ready + n.pintreq := '0'; -- clear interrupt + else -- not busy and fifo not full + n.prdy := '1'; -- set done + if r.prdy='0' and -- done going 0->1 + r.perr='0' and r.pie='1' then -- and err=0 and interrupt enabled + n.pintreq := '1'; -- request interrupt + end if; + end if; + + N_REGS <= n; + + RBUF_RESET <= irbufrst; + RBUF_CE <= irbufce; + RBUF_WE <= irbufwe; + RRLIM_START <= irrlimsta; + + PBUF_RESET <= RESET or r.perr; + PBUF_CE <= ipbufce; + PBUF_WE <= ipbufwe; + PRLIM_START <= iprlimsta; + + IB_SRES.dout <= idout; + IB_SRES.ack <= iback; + IB_SRES.busy <= '0'; + + RB_LAM <= ilam; + EI_REQ_PTR <= r.rintreq; + EI_REQ_PTP <= r.pintreq; + + end process proc_next; + + +end syn; diff --git a/rtl/sys_gen/w11a/nexys2/sys_w11a_n2.imfset b/rtl/sys_gen/w11a/nexys2/sys_w11a_n2.imfset index 18d61183..f723ff0f 100644 --- a/rtl/sys_gen/w11a/nexys2/sys_w11a_n2.imfset +++ b/rtl/sys_gen/w11a/nexys2/sys_w11a_n2.imfset @@ -1,4 +1,4 @@ -# $Id: sys_w11a_n2.imfset 1108 2019-02-02 23:04:38Z mueller $ +# $Id: sys_w11a_n2.imfset 1136 2019-04-24 09:27:28Z mueller $ # # ---------------------------------------------------------------------------- [xst] @@ -31,6 +31,7 @@ Unconnected output port 'DOB' of component 'ram_2swsr_rfirst_gen' Unconnected output port 'BUSY' of component 'fifo_1c_dram' Unconnected output port 'SIZE' of component 'fifo_1c_dram' Unconnected output port 'ESUSP_O' of component 'pdp11_core' +Unconnected output port 'DONE' of component 'ib_rlim_slv' Input is never used Input is never used diff --git a/rtl/sys_gen/w11a/nexys3/sys_w11a_n3.vhd b/rtl/sys_gen/w11a/nexys3/sys_w11a_n3.vhd index f675067b..a8c2dc2d 100644 --- a/rtl/sys_gen/w11a/nexys3/sys_w11a_n3.vhd +++ b/rtl/sys_gen/w11a/nexys3/sys_w11a_n3.vhd @@ -1,4 +1,4 @@ --- $Id: sys_w11a_n3.vhd 1123 2019-03-17 17:55:12Z mueller $ +-- $Id: sys_w11a_n3.vhd 1137 2019-04-24 10:49:19Z mueller $ -- -- Copyright 2011-2019 by Walter F.J. Mueller -- @@ -34,6 +34,7 @@ -- -- Synthesized (xst): -- Date Rev ise Target flop lutl lutm slic t peri +-- 2019-03-24 1137 14.7 131013 xc6slx16-2 3049 5727 223 2045 ok: +pcbuf 89% -- 2019-03-17 1123 14.7 131013 xc6slx16-2 3059 5722 212 2041 ok: +lpbuf 89% -- 2019-03-02 1116 14.7 131013 xc6slx16-2 3048 5741 212 2030 ok: +ibtst 89% -- 2019-01-27 1108 14.7 131013 xc6slx16-2 2979 5542 201 2018 ok: -iist 88% diff --git a/rtl/sys_gen/w11a/nexys4/sys_w11a_n4.vhd b/rtl/sys_gen/w11a/nexys4/sys_w11a_n4.vhd index 75684701..48a9f396 100644 --- a/rtl/sys_gen/w11a/nexys4/sys_w11a_n4.vhd +++ b/rtl/sys_gen/w11a/nexys4/sys_w11a_n4.vhd @@ -1,4 +1,4 @@ --- $Id: sys_w11a_n4.vhd 1123 2019-03-17 17:55:12Z mueller $ +-- $Id: sys_w11a_n4.vhd 1137 2019-04-24 10:49:19Z mueller $ -- -- Copyright 2013-2019 by Walter F.J. Mueller -- @@ -35,6 +35,7 @@ -- -- Synthesized: -- Date Rev viv Target flop lutl lutm bram slic MHz +-- 2019-04-24 1137 2017.2 xc7a100t-1 3251 6465 228 17.0 2043 80 +pcbuf -- 2019-03-17 1123 2017.2 xc7a100t-1 3231 6403 212 17.0 2053 80 +lpbuf -- 2019-03-02 1116 2017.2 xc7a100t-1 3200 6317 198 17.0 2032 80 +ibtst -- 2019-02-02 1108 2018.3 xc7a100t-1 3165 6497 182 17.0 2054 80 diff --git a/rtl/sys_gen/w11a/s3board/sys_w11a_s3.imfset b/rtl/sys_gen/w11a/s3board/sys_w11a_s3.imfset index 5521f291..505c4376 100644 --- a/rtl/sys_gen/w11a/s3board/sys_w11a_s3.imfset +++ b/rtl/sys_gen/w11a/s3board/sys_w11a_s3.imfset @@ -1,4 +1,4 @@ -# $Id: sys_w11a_s3.imfset 1108 2019-02-02 23:04:38Z mueller $ +# $Id: sys_w11a_s3.imfset 1136 2019-04-24 09:27:28Z mueller $ # # ---------------------------------------------------------------------------- [xst] @@ -24,6 +24,7 @@ Unconnected output port 'SIZE' of component 'fifo_1c_dram' Unconnected output port 'ESUSP_O' of component 'pdp11_core' Unconnected output port 'RL_MONI' of component 'rlink_sp1c' Unconnected output port 'ACK_W' of component 's3_sram_memctl' +Unconnected output port 'DONE' of component 'ib_rlim_slv' Input is never used Input is never used diff --git a/tools/mcode/README.md b/tools/mcode/README.md index 6a58ef31..46fedaed 100644 --- a/tools/mcode/README.md +++ b/tools/mcode/README.md @@ -3,4 +3,6 @@ This directory tree contains **miscellaneous codes** and is organized in | Directory | Content | | --------- | ------- | | [dl11](dl11) | for DL11 | +| [lp11](lp11) | for LP11 | +| [pc11](pc11) | for PC11 | | [sys](sys) | for whole system | diff --git a/tools/mcode/lp11/README.md b/tools/mcode/lp11/README.md new file mode 100644 index 00000000..3c087724 --- /dev/null +++ b/tools/mcode/lp11/README.md @@ -0,0 +1,5 @@ +This directory tree contains **LP11 test codes** and contains + +| File | Docu | Comments | +| --------- | --------- | ------- | +| [lp11write.mac](lp11write.mac) | - | write test for LP11 | diff --git a/tools/mcode/lp11/lp11write.mac b/tools/mcode/lp11/lp11write.mac new file mode 100644 index 00000000..4a4fba1c --- /dev/null +++ b/tools/mcode/lp11/lp11write.mac @@ -0,0 +1,112 @@ +; $Id: lp11write.mac 1134 2019-04-21 17:18:03Z mueller $ +; Copyright 2019- by Walter F.J. Mueller +; License disclaimer see License.txt in $RETROBASE directory +; +; Revision History: +; Date Rev Version Comment +; 2019-04-21 1134 1.0 Initial version +; +; write test tape +; +; definitions ---------------------------------------------- +; + .include |lib/defs_cpu.mac| + .include |lib/defs_lp.mac| +; + lcnt = 1000. ; number of lines to print +; + CR = 015 + LF = 012 +; +; vector area ---------------------------------------------- +; + .include |lib/vec_cpucatch.mac| + .include |lib/vec_devcatch.mac| + + . = v..lp + .word vh.lp + .word cp.pr7 +; +; stack area ----------------------------------------------- +; + . = 1000 ; stack (below); code (above) +stack: +; +; code area ------------------------------------------------ +; +; gobal register usage +; r0 line count ; !! visible in wait !! +; r1 write buffer pointer +; +; start/stop area --------------------------------- +; +start: br start1 +stop: halt ; sucessfull stop + reset ; and allow re-start +; +; main program ------------------------------------ +; +start1: mov #stack,sp ; setup stack +2$: tst @#lp.csr ; wait printer online + bmi 2$ +; + clr r0 ; clear line count + mov #bnum,r1 ; write buffer pointer + clr r2 + clr r3 + clr r4 + clr r5 + mov #"00,bnum + mov #"00,bnum+2 +; + mov #lp.ie,@#lp.csr ; start printer + spl 0 ; allow interrupts +3$: wait ; and idle + br 3$ +; +; printer interrupt handler ----------------------- +; +vh.lp: tst @#lp.csr ; printer offline ? + bmi perr ; if mi yes, error halt +1$: movb (r1)+,@#lp.buf ; send byte + cmp r1,#bend ; end of buffer ? + bhis 100$ ; if his yes, handle new line + tstb @#lp.csr ; ready for next char + bmi 1$ ; if mi yes, doit + rti ; else quit irupt + +100$: mov #bnum+3,r1 ; if yes, increment number + jsr pc,incnum + inc r0 ; inc line counter + cmp r0,#lcnt ; enough lines send ? + beq 200$ + mov #bnum,r1 ; ready for next line + rti + +200$: jmp stop + +perr: halt ; printer error halt + br perr +; +; increment 4 digit decimal number --------------- +; +incnum: mov #4,r5 ; max 4 digits +1$: incb (r1) + cmpb (r1),#'9 ; went above 9 + ble 100$ ; if not, done + movb #'0,(r1) ; if yes, restore 0 + dec r1 ; and go for next digit + sob r5,1$ +100$: rts pc +; +; data area ------------------------------------------------ +; +bnum: .ascii /0000/ +btxt: .ascii /: / + .ascii /ABCDEFGHIJKLMNOPQRSTUVWXYZ/ + .ascii /abcdefghijklmnopqrstuvwxyz/ + .ascii /!@#$%^&*()/ + .byte CR,LF +bend: + + .end start diff --git a/tools/mcode/pc11/Makefile b/tools/mcode/pc11/Makefile new file mode 100644 index 00000000..50a2b9e4 --- /dev/null +++ b/tools/mcode/pc11/Makefile @@ -0,0 +1,31 @@ +# $Id: Makefile 1135 2019-04-23 12:56:23Z mueller $ +# +# Revision History: +# Date Rev Version Comment +# 2013-03-22 496 1.0 Initial version +#--- +# +MAC_all = $(wildcard *.mac) +LDA_all = $(MAC_all:.mac=.lda) +COF_all = $(MAC_all:.mac=.cof) +LST_all = $(MAC_all:.mac=.lst) +# +include ${RETROBASE}/tools/make/generic_asm11.mk +# +.PHONY : alllda allcof alllst clean +# +def : alllda +# +alllda : $(LDA_all) +# +allcof : $(COF_all) +# +alllst : $(LST_all) +# +clean : + @ rm -f $(LDA_all) + @ echo "Object files removed" + @ rm -f $(COF_all) + @ echo "Compound files removed" + @ rm -f $(LST_all) + @ echo "Listing files removed" diff --git a/tools/mcode/pc11/README.md b/tools/mcode/pc11/README.md new file mode 100644 index 00000000..be8ab623 --- /dev/null +++ b/tools/mcode/pc11/README.md @@ -0,0 +1,7 @@ +This directory tree contains **PC11 test codes** and contains + +| File | Docu | Comments | +| --------- | --------- | ------- | +| [pc11copy.mac](pc11copy.mac) | - | copy test for PC11 | +| [pc11read.mac](pc11read.mac) | - | read test for PC11 | +| [pc11write.mac](pc11write.mac) | - | write test for PC11 | diff --git a/tools/mcode/pc11/pc11copy.mac b/tools/mcode/pc11/pc11copy.mac new file mode 100644 index 00000000..bb426673 --- /dev/null +++ b/tools/mcode/pc11/pc11copy.mac @@ -0,0 +1,139 @@ +; $Id: pc11copy.mac 1136 2019-04-24 09:27:28Z mueller $ +; Copyright 2019- by Walter F.J. Mueller +; License disclaimer see License.txt in $RETROBASE directory +; +; Revision History: +; Date Rev Version Comment +; 2019-04-21 1134 1.0 Initial version +; +; copy input to output tape +; +; definitions ---------------------------------------------- +; + .include |lib/defs_cpu.mac| + .include |lib/defs_pc.mac| + + bsize = 256. +; +; vector area ---------------------------------------------- +; + .include |lib/vec_cpucatch.mac| + .include |lib/vec_devcatch.mac| + + . = v..ptr + .word vh.ptr + .word cp.pr7 + . = v..ptp + .word vh.ptp + .word cp.pr7 +; +; stack area ----------------------------------------------- +; + . = 1000 ; stack (below); code (above) +stack: +; +; code area ------------------------------------------------ +; +; all context is in 6 register +; r0 bytes read ; !! visible in wait !! +; r1 bytes written +; r2 bytes in buffer +; r3 eof seen flag +; r4 ring buffer write pointer +; r5 ring buffer read pointer +; +; start/stop area --------------------------------- +; +start: br start1 +stop: halt ; sucessfull stop + reset ; and allow re-start +; +; main program ------------------------------------ +; +start1: mov #stack,sp ; setup stack +1$: tst @#pr.csr ; wait reader online + bmi 1$ +2$: tst @#pp.csr ; wait punch online + bmi 2$ +; + mov #buf,r4 ; setup wptr + mov #buf,r5 ; setup rptr + clr r2 ; clear cnt + clr r3 ; clear eof + clr r0 ; clear rcnt + clr r1 ; clear wcnt +; + mov #,@#pr.csr ; start reader + spl 0 ; allow interrupts +3$: wait ; and idle + br 3$ +; +; reader interrupt handler ------------------------ +; +vh.ptr: tst @#pr.csr ; at eof ? + bmi 100$ ; if mi yes, stop reader + tstb @#pr.csr ; done ? + bpl rerr ; if pl no, error halt + movb @#pr.buf,(r4)+ ; write char to buffer + inc r0 ; inc rcnt + cmp r4,#bufe ; wrap ? + blo 1$ + mov #buf,r4 +1$: tst r2 ; test buffer count + bne 2$ ; was buffer empty ? + bis #pp.ie,@#pp.csr ; then start punch +2$: inc r2 ; inc cnt + cmp r2,# ; still space in buffer ? + bge 200$ ; no: stop reader + inc @#pr.csr ; yes: else request next + rti + +100$: inc r3 ; set eof flag + tst r2 ; any chars pending ? + beq 300$ ; if eq not, all done + rti + +200$: bic #pr.ie,@#pr.csr ; stop reader + rti + +300$: jmp stop + +rerr: halt ; reader error halt + br rerr +; +; puncher interrupt handler ----------------------- +; +vh.ptp: tst @#pp.csr ; punch error + bmi perr ; if mi yes, error halt + tstb @#pp.csr ; ready ? + bpl perr ; if pl no, error halt + tst r2 ; test buffer count + beq 100$ ; if eq suspend or stop + movb (r5)+,@#pp.buf ; and punch next char + inc r1 ; inc wcnt + cmp r5,#bufe ; wrap ? + blo 1$ + mov #buf,r5 +1$: dec r2 ; dec cnt + bit #pr.ie,@#pr.csr ; reader active ? + bne 2$ ; + mov #,@#pr.csr ; if not, start reader +2$: rti + +100$: bic #pp.ie,@#pp.csr ; stop punch + tstb r3 ; eof seen ? + bne 200$ ; if yes, all done + rti + +200$: jmp stop + +perr: halt ; puncher error halt + br perr + +; +; data area ------------------------------------------------ +; +buf: .blkb bsize +bufe: + + .end start diff --git a/tools/mcode/pc11/pc11read.mac b/tools/mcode/pc11/pc11read.mac new file mode 100644 index 00000000..4ab7f3c0 --- /dev/null +++ b/tools/mcode/pc11/pc11read.mac @@ -0,0 +1,118 @@ +; $Id: pc11read.mac 1134 2019-04-21 17:18:03Z mueller $ +; Copyright 2019- by Walter F.J. Mueller +; License disclaimer see License.txt in $RETROBASE directory +; +; Revision History: +; Date Rev Version Comment +; 2019-04-21 1134 1.0 Initial version +; +; write test tape +; +; definitions ---------------------------------------------- +; + .include |lib/defs_cpu.mac| + .include |lib/defs_pc.mac| +; + lcnt = 1000. ; number of lines to print +; + CR = 015 + LF = 012 +; +; vector area ---------------------------------------------- +; + .include |lib/vec_cpucatch.mac| + .include |lib/vec_devcatch.mac| + + . = v..ptr + .word vh.ptr + .word cp.pr7 +; +; stack area ----------------------------------------------- +; + . = 1000 ; stack (below); code (above) +stack: +; +; code area ------------------------------------------------ +; +; gobal register usage +; r0 line count ; !! visible in wait !! +; r1 read buffer pointer +; +; start/stop area --------------------------------- +; +start: br start1 +stop: halt ; sucessfull stop + reset ; and allow re-start +; +; main program ------------------------------------ +; +start1: mov #stack,sp ; setup stack +2$: tst @#pr.csr ; wait reader online + bmi 2$ +; + clr r0 ; clear line count + mov #bnum,r1 ; read buffer pointer + clr r2 + clr r3 + clr r4 + clr r5 + mov #"00,bnum + mov #"00,bnum+2 +; + mov #,@#pr.csr ; start reader + spl 0 ; allow interrupts +3$: wait ; and idle + br 3$ +; +; reader interrupt handler ----------------------- +; +vh.ptr: tst @#pr.csr ; reader error + bpl 10$ + cmp #bnum,r1 ; at begin of buffer ? + bne rerr ; if not, unexpected EOT + cmp r0,#lcnt ; all lines seen ? + bne rerr ; if not, unexpected EOT + br 200$ ; otherwise success halt +10$: movb @#pr.buf,r2 ; read byte + cmpb r2,(r1)+ ; check byte + bne derr + cmp r1,#bend ; end of buffer ? + blo 100$ + mov #bnum+3,r1 ; if yes, increment number + jsr pc,incnum + inc r0 ; inc line counter + mov #bnum,r1 ; ready for next line +100$: inc @#pr.csr ; go for next char + rti + +200$: jmp stop + +rerr: halt ; reader error halt + br rerr +derr: halt ; data error halt + br derr + + +; +; increment 4 digit decimal number --------------- +; +incnum: mov #4,r5 ; max 4 digits +1$: incb (r1) + cmpb (r1),#'9 ; went above 9 + ble 100$ ; if not, done + movb #'0,(r1) ; if yes, restore 0 + dec r1 ; and go for next digit + sob r5,1$ +100$: rts pc +; +; data area ------------------------------------------------ +; +bnum: .ascii /0000/ +btxt: .ascii /: / + .ascii /ABCDEFGHIJKLMNOPQRSTUVWXYZ/ + .ascii /abcdefghijklmnopqrstuvwxyz/ + .ascii /!@#$%^&*()/ + .byte CR,LF +bend: + + .end start diff --git a/tools/mcode/pc11/pc11write.mac b/tools/mcode/pc11/pc11write.mac new file mode 100644 index 00000000..35fcb704 --- /dev/null +++ b/tools/mcode/pc11/pc11write.mac @@ -0,0 +1,108 @@ +; $Id: pc11write.mac 1134 2019-04-21 17:18:03Z mueller $ +; Copyright 2019- by Walter F.J. Mueller +; License disclaimer see License.txt in $RETROBASE directory +; +; Revision History: +; Date Rev Version Comment +; 2019-04-21 1134 1.0 Initial version +; +; write test tape +; +; definitions ---------------------------------------------- +; + .include |lib/defs_cpu.mac| + .include |lib/defs_pc.mac| +; + lcnt = 1000. ; number of lines to print +; + CR = 015 + LF = 012 +; +; vector area ---------------------------------------------- +; + .include |lib/vec_cpucatch.mac| + .include |lib/vec_devcatch.mac| + + . = v..ptp + .word vh.ptp + .word cp.pr7 +; +; stack area ----------------------------------------------- +; + . = 1000 ; stack (below); code (above) +stack: +; +; code area ------------------------------------------------ +; +; gobal register usage +; r0 line count ; !! visible in wait !! +; r1 write buffer pointer +; +; start/stop area --------------------------------- +; +start: br start1 +stop: halt ; sucessfull stop + reset ; and allow re-start +; +; main program ------------------------------------ +; +start1: mov #stack,sp ; setup stack +2$: tst @#pp.csr ; wait punch online + bmi 2$ +; + clr r0 ; clear line count + mov #bnum,r1 ; write buffer pointer + clr r2 + clr r3 + clr r4 + clr r5 + mov #"00,bnum + mov #"00,bnum+2 +; + mov #pp.ie,@#pp.csr ; start puncher + spl 0 ; allow interrupts +3$: wait ; and idle + br 3$ +; +; puncher interrupt handler ----------------------- +; +vh.ptp: tst @#pp.csr ; punch error + bmi perr ; if mi yes, error halt + movb (r1)+,@#pp.buf ; send byte + cmp r1,#bend ; end of buffer ? + blo 100$ + mov #bnum+3,r1 ; if yes, increment number + jsr pc,incnum + inc r0 ; inc line counter + cmp r0,#lcnt ; enough lines send ? + beq 200$ + mov #bnum,r1 ; ready for next line +100$: rti + +200$: jmp stop + +perr: halt ; puncher error halt + br perr +; +; increment 4 digit decimal number --------------- +; +incnum: mov #4,r5 ; max 4 digits +1$: incb (r1) + cmpb (r1),#'9 ; went above 9 + ble 100$ ; if not, done + movb #'0,(r1) ; if yes, restore 0 + dec r1 ; and go for next digit + sob r5,1$ +100$: rts pc +; +; data area ------------------------------------------------ +; +bnum: .ascii /0000/ +btxt: .ascii /: / + .ascii /ABCDEFGHIJKLMNOPQRSTUVWXYZ/ + .ascii /abcdefghijklmnopqrstuvwxyz/ + .ascii /!@#$%^&*()/ + .byte CR,LF +bend: + + .end start diff --git a/tools/src/librw11/Rw11CntlPC11.cpp b/tools/src/librw11/Rw11CntlPC11.cpp index 196b6843..751ff9ec 100644 --- a/tools/src/librw11/Rw11CntlPC11.cpp +++ b/tools/src/librw11/Rw11CntlPC11.cpp @@ -1,4 +1,4 @@ -// $Id: Rw11CntlPC11.cpp 1131 2019-04-14 13:24:25Z mueller $ +// $Id: Rw11CntlPC11.cpp 1134 2019-04-21 17:18:03Z mueller $ // // Copyright 2013-2019 by Walter F.J. Mueller // @@ -13,6 +13,7 @@ // // Revision History: // Date Rev Version Comment +// 2019-04-20 1134 1.5 add pc11_buf readout // 2019-04-13 1131 1.4.1 BootCode(): boot loader rewritten // remove SetOnline(), use UnitSetup() // 2019-04-06 1126 1.4 pbuf.val in msb; rbusy in rbuf (new unbuf iface) @@ -34,6 +35,7 @@ */ #include +#include #include "librtools/RosFill.hpp" #include "librtools/RosPrintBvi.hpp" @@ -97,12 +99,23 @@ const uint16_t Rw11CntlPC11::kPBUF_M_BUF; Rw11CntlPC11::Rw11CntlPC11() : Rw11CntlBase("pc11"), fPC_pbuf(0), - fPC_rbuf(0) + fPC_rbuf(0), + fPrQlim(1), + fPrRlim(0), + fPpRlim(0), + fItype(0), + fFsize(0), + fPpRblkSize(4), + fPpQueBusy(false), + fPrDrain(kPrDrain_Idle) { // must be here because Units have a back-ptr (not available at Rw11CntlBase) for (size_t i=0; i>kRCSR_V_TYPE) & kRCSR_B_TYPE; + fFsize = (1<& code, void Rw11CntlPC11::UnitSetup(size_t ind) { Rw11UnitPC11& unit = *fspUnit[ind]; - bool online = unit.HasVirt() && ! (unit.Virt().Error() || - unit.Virt().Eof()); - Rw11Cpu& cpu = Cpu(); - RlinkCommandList clist; - if (ind == kUnit_PR) { // reader on/offline - uint16_t rcsr = online ? 0 : kRCSR_M_ERROR; - cpu.AddWibr(clist, fBase+kRCSR, rcsr); - } else { // puncher on/offline - uint16_t pcsr = online ? 0 : kPCSR_M_ERROR; - cpu.AddWibr(clist, fBase+kPCSR, pcsr); + if (ind == kUnit_PR) { // reader + // reader is online when attached but not when virt in eof or error state + // and the reader fifo has been emptied + bool online = unit.HasVirt() && ! + ( (unit.Virt().Eof() || unit.Virt().Error()) && + ! (fPrDrain == kPrDrain_Pend) ); + uint16_t rcsr = (online ? 0 : kRCSR_M_ERROR) | // err field + ((fPrRlim & kRCSR_B_RLIM) << kRCSR_V_RLIM); // rlim field + Cpu().ExecWibr(fBase+kRCSR, rcsr); + + } else { // puncher + // puncher is online when attached and virt not in error state + bool online = unit.HasVirt() && ! unit.Virt().Error(); + uint16_t pcsr = (online ? 0 : kPCSR_M_ERROR) | // err field + ((fPpRlim & kPCSR_B_RLIM) << kPCSR_V_RLIM); // rlim field + Cpu().ExecWibr(fBase+kPCSR, pcsr); } - Server().Exec(clist); + return; } //------------------------------------------+----------------------------------- //! FIXME_docs +void Rw11CntlPC11::SetPrQlim(uint16_t qlim) +{ + if (qlim == 0) qlim = fFsize; + if (qlim > fFsize) + throw Rexception("Rw11CntlPC11::SetPrQlim", + "Bad args: qlim larger than fifosize"); + + fPrQlim = qlim; + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlPC11::SetPrRlim(uint16_t rlim) +{ + if (rlim > kRCSR_B_RLIM) + throw Rexception("Rw11CntlPC11::SetPrRlim","Bad args: rlim too large"); + + fPrRlim = rlim; + UnitSetup(kUnit_PR); + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlPC11::SetPpRlim(uint16_t rlim) +{ + if (rlim > kRCSR_B_RLIM) + throw Rexception("Rw11CntlPC11::SetPpRlim","Bad args: rlim too large"); + + fPpRlim = rlim; + UnitSetup(kUnit_PP); + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlPC11::AttachDone(size_t ind) +{ + // if reader is attached pre-fill the fifo + if (ind == kUnit_PR && Buffered()) { + fPrDrain = kPrDrain_Idle; // clear drain state + PrProcessBuf(0); // and pre-fill + } + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + void Rw11CntlPC11::Dump(std::ostream& os, int ind, const char* text, int detail) const { @@ -258,7 +341,21 @@ void Rw11CntlPC11::Dump(std::ostream& os, int ind, const char* text, os << bl << (text?text:"--") << "Rw11CntlPC11 @ " << this << endl; os << bl << " fPC_pbuf: " << fPC_pbuf << endl; os << bl << " fPC_rbuf: " << fPC_rbuf << endl; - + os << bl << " fPrQlim: " << RosPrintf(fPrQlim,"d",3) << endl; + os << bl << " fPrRlim: " << RosPrintf(fPrRlim,"d",3) << endl; + os << bl << " fPpRlim: " << RosPrintf(fPpRlim,"d",3) << endl; + os << bl << " fItype: " << RosPrintf(fItype,"d",3) << endl; + os << bl << " fFsize: " << RosPrintf(fFsize,"d",3) << endl; + os << bl << " fPpRblkSize: " << RosPrintf(fPpRblkSize,"d",3) << endl; + os << bl << " fPpQueBusy: " << RosPrintf(fPpQueBusy) << endl; + os << bl << " fPrDrain: "; + switch (fPrDrain) { + case kPrDrain_Idle: os << "Idle"; break; + case kPrDrain_Pend: os << "Pend"; break; + case kPrDrain_Done: os << "Done"; break; + default: os << "????"; + }; + os << endl; Rw11CntlBase::Dump(os, ind, " ^", detail); return; } @@ -270,14 +367,29 @@ int Rw11CntlPC11::AttnHandler(RlinkServer::AttnArgs& args) { fStats.Inc(kStatNAttnHdl); Server().GetAttnInfo(args, fPrimClist); + + if (!Buffered()) { // un-buffered iface ------------- + ProcessUnbuf(fPrimClist[fPC_rbuf].Data(), + fPrimClist[fPC_pbuf].Data()); + } else { // buffered iface ---------------- + PrProcessBuf(fPrimClist[fPC_rbuf].Data()); + PpProcessBuf(fPrimClist[fPC_pbuf], true, fPrimClist[fPC_rbuf].Data()); + } + + return 0; +} - uint16_t pbuf = fPrimClist[fPC_pbuf].Data(); - uint16_t rbuf = fPrimClist[fPC_rbuf].Data(); +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlPC11::ProcessUnbuf(uint16_t rbuf, uint16_t pbuf) +{ bool rbusy = rbuf & kRBUF_M_RBUSY; bool pval = pbuf & kPBUF_M_VAL; uint8_t ochr = pbuf & kPBUF_M_BUF; if (pval) { // punch valid ------------------- + if (pval) PpWriteChar(ochr); if (fTraceLevel>0) { RlogMsg lmsg(LogFile()); lmsg << "-I " << Name() << ": pp" @@ -287,16 +399,8 @@ int Rw11CntlPC11::AttnHandler(RlinkServer::AttnArgs& args) << " char=" << RosPrintBvi(ochr,8); if (ochr>=040 && ochr<0177) lmsg << " '" << char(ochr) << "'"; } - - RerrMsg emsg; - bool rc = fspUnit[kUnit_PP]->VirtWrite(&ochr, 1, emsg); - if (!rc) { - RlogMsg lmsg(LogFile()); - lmsg << "-E " << Name() << ":" << emsg; - UnitSetup(1); - } } - + if (rbusy) { // reader busy ------------------- uint8_t ichr = 0; RerrMsg emsg; @@ -311,7 +415,7 @@ int Rw11CntlPC11::AttnHandler(RlinkServer::AttnArgs& args) RlogMsg lmsg(LogFile()); lmsg << "-I " << Name() << ": set reader offline"; } - UnitSetup(0); + UnitSetup(kUnit_PR); } else { if (fTraceLevel>0) { @@ -322,14 +426,204 @@ int Rw11CntlPC11::AttnHandler(RlinkServer::AttnArgs& args) if (ichr>=040 && ichr<0177) lmsg << " '" << char(ichr) << "'"; } - RlinkCommandList clist; - Cpu().AddWibr(clist, fBase+kRBUF, ichr); - Server().Exec(clist); + Cpu().ExecWibr(fBase+kRBUF, ichr); + } + } + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlPC11::PpWriteChar(uint8_t ochr) +{ + RerrMsg emsg; + bool rc = fspUnit[kUnit_PP]->VirtWrite(&ochr, 1, emsg); + if (!rc) { + RlogMsg lmsg(LogFile()); + lmsg << "-E " << Name() << ":" << emsg; + UnitSetup(kUnit_PP); + } + + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlPC11::PrProcessBuf(uint16_t rbuf) +{ + uint16_t rsize = (rbuf >>kRBUF_V_SIZE) & kRBUF_B_SIZE; + uint8_t ichr = 0; + RerrMsg emsg; + + if (fPrDrain == kPrDrain_Pend) { // eof/err seen and draining + if (rsize == 0) { // draining done, last char read + if (fTraceLevel>0) { + RlogMsg lmsg(LogFile()); + lmsg << "-I " << Name() << ": set reader offline after fifo drained"; + } + fPrDrain = kPrDrain_Done; + UnitSetup(kUnit_PR); + } + return; + } + + if (fPrDrain == kPrDrain_Pend || // draining ongoing or done -> quit + fPrDrain == kPrDrain_Done) return; + if (rsize >= fPrQlim) return; // no space in fifo -> quit + + uint16_t nmax = fPrQlim - rsize; + vector iblock; + iblock.reserve(nmax); + for (uint16_t i = 0; iVirtRead(&ichr, 1, emsg); + if (irc <= 0) { + if (irc < 0) { + RlogMsg lmsg(LogFile()); + lmsg << "-E " << Name() << ":" << emsg; + } + if (irc == 0 && fTraceLevel>0) { + RlogMsg lmsg(LogFile()); + lmsg << "-I " << Name() << ": eof seen on input stream"; + } + fPrDrain = kPrDrain_Pend; + break; + } else { + iblock.push_back(uint16_t(ichr)); } } + if (iblock.size() > 0) { + if (fTraceLevel > 0) { + RlogMsg lmsg(LogFile()); + lmsg << "-I " << Name() << ":" + << " rsize=" << RosPrintf(rsize,"d",3) + << " drain=" << fPrDrain + << " size=" << RosPrintf(iblock.size(),"d",3); + if (fTraceLevel > 1) { + size_t nchar = 0; + for (auto& o: iblock) { + if (nchar == 0) lmsg << "\n '"; + lmsg << ' ' << RosPrintBvi(uint8_t(o),8); + nchar += 1; + if (nchar >= 16) nchar = 0; + } + } + } + + fStats.Inc(kStatNPrBlk); + RlinkCommandList clist; + Cpu().AddWbibr(clist, fBase+kRBUF, move(iblock)); + Server().Exec(clist); + + } else { + // if no byte to send, eof seen, and fifo empty --> go offline immediately + if (rsize == 0 && fPrDrain == kPrDrain_Pend) { + if (fTraceLevel>0) { + RlogMsg lmsg(LogFile()); + lmsg << "-I " << Name() << ": set reader offline immediately"; + } + fPrDrain = kPrDrain_Done; + UnitSetup(kUnit_PR); + } + } + + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11CntlPC11::PpProcessBuf(const RlinkCommand& cmd, bool prim, + uint16_t rbuf) +{ + const uint16_t* pbuf = cmd.BlockPointer(); + size_t done = cmd.BlockDone(); + + uint16_t fbeg = 0; + uint16_t fend = 0; + uint16_t fdel = 0; + uint16_t smin = 0; + uint16_t smax = 0; + + if (done > 0) { + fbeg = (pbuf[0] >>kPBUF_V_SIZE) & kPBUF_B_SIZE; + fend = (pbuf[done-1]>>kPBUF_V_SIZE) & kPBUF_B_SIZE; + fdel = fbeg-fend+1; + smin = 128; + } + + for (size_t i=0; i < done; i++) { + uint8_t ochr = pbuf[i] & kPBUF_M_BUF; + uint16_t size = (pbuf[i]>>kPBUF_V_SIZE) & kPBUF_B_SIZE; + smin = min(smin,size); + smax = max(smax,size); + PpWriteChar(ochr); + } + + // determine next chunk size from highest fifo 'size' field, at least 4 + fPpRblkSize = max(uint16_t(4), max(uint16_t(done),smax)); + + // queue further reads when queue idle and fifo not emptied + // check for 'size==1' not seen in current read + if ((!fPpQueBusy) && smin > 1) { // if smin>1 no size==1 seen + fStats.Inc(kStatNPpQue); + fPpQueBusy = true; + Server().QueueAction(bind(&Rw11CntlPC11::PpRcvHandler, this)); + } + + if (fTraceLevel > 0) { + RlogMsg lmsg(LogFile()); + lmsg << "-I " << Name() << ":" + << " prim=" << prim + << " size=" << RosPrintf(cmd.BlockSize(),"d",3) + << " done=" << RosPrintf(done,"d",3) + << " fifo=" << RosPrintf(fbeg,"d",3) + << "," << RosPrintf(fend,"d",3) + << ";" << RosPrintf(fdel,"d",3) + << "," << RosPrintf(done-fdel,"d",3) + << ";" << RosPrintf(smax,"d",3) + << "," << RosPrintf(smin,"d",3) + << " que=" << fPpQueBusy; + if (prim) { + uint16_t rsize = (rbuf >>kRBUF_V_SIZE) & kRBUF_B_SIZE; + lmsg << " rsize=" << RosPrintf(rsize,"d",3); + } + + if (fTraceLevel > 1 && done > 0) { + size_t nchar = 0; + for (size_t i=0; i < done; i++) { + if (nchar == 0) lmsg << "\n '"; + uint8_t ochr = pbuf[i] & kPBUF_M_BUF; + lmsg << ' ' << RosPrintBvi(ochr,8); + nchar += 1; + if (nchar >= 16) nchar = 0; + } + } + } + + // re-sizing the prim rblk invalidates pbuf -> so must be done last + if (prim) { // if primary list + fPrimClist[fPC_pbuf].SetBlockRead(fPpRblkSize); // setup size for next attn + } + + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +int Rw11CntlPC11::PpRcvHandler() +{ + fPpQueBusy = false; + RlinkCommandList clist; + Cpu().AddRbibr(clist, fBase+kPBUF, fPpRblkSize); + clist[0].SetExpectStatus(0, RlinkCommand::kStat_M_RbTout | + RlinkCommand::kStat_M_RbNak); + Server().Exec(clist); + PpProcessBuf(clist[0], false, 0); return 0; } - } // end namespace Retro diff --git a/tools/src/librw11/Rw11CntlPC11.hpp b/tools/src/librw11/Rw11CntlPC11.hpp index 84a75a34..70bd97c8 100644 --- a/tools/src/librw11/Rw11CntlPC11.hpp +++ b/tools/src/librw11/Rw11CntlPC11.hpp @@ -1,4 +1,4 @@ -// $Id: Rw11CntlPC11.hpp 1131 2019-04-14 13:24:25Z mueller $ +// $Id: Rw11CntlPC11.hpp 1134 2019-04-21 17:18:03Z mueller $ // // Copyright 2013-2019 by Walter F.J. Mueller // @@ -13,6 +13,7 @@ // // Revision History: // Date Rev Version Comment +// 2019-04-20 1134 1.4 add pc11_buf readout // 2019-04-14 1131 1.3.1 remove SetOnline(), use UnitSetup() // 2019-04-06 1126 1.3 pbuf.val in msb; rbusy in rbuf (new iface) // 2017-04-02 865 1.2.1 Dump(): add detail arg @@ -47,6 +48,19 @@ namespace Retro { uint16_t& aload, uint16_t& astart); virtual void UnitSetup(size_t ind); + + void SetPrQlim(uint16_t qlim); + uint16_t PrQlim() const; + void SetPrRlim(uint16_t rlim); + uint16_t PrRlim() const; + void SetPpRlim(uint16_t rlim); + uint16_t PpRlim() const; + + uint16_t Itype() const; + bool Buffered() const; + uint16_t FifoSize() const; + + void AttachDone(size_t ind); virtual void Dump(std::ostream& os, int ind=0, const char* text=0, int detail=0) const; @@ -85,17 +99,45 @@ namespace Retro { static const uint16_t kPBUF_V_SIZE = 8; //!< pbuf.size shift static const uint16_t kPBUF_B_SIZE = 0177; //!< pbuf.size bit mask static const uint16_t kPBUF_M_BUF = 0377; //!< pbuf data mask + + // statistics counter indices + enum stats { + kStatNPrBlk= Rw11Cntl::kDimStat, //!< done wblk + kStatNPpQue, //!< queue rblk + kDimStat + }; + // PrDrain state definitions + enum prdrain { + kPrDrain_Idle = 0, //!< draining not active + kPrDrain_Pend, //!< draining pending + kPrDrain_Done //!< draining done + }; + protected: int AttnHandler(RlinkServer::AttnArgs& args); + void ProcessUnbuf(uint16_t rbuf, uint16_t pbuf); + void PpWriteChar(uint8_t ochr); + void PrProcessBuf(uint16_t rbuf); + void PpProcessBuf(const RlinkCommand& cmd, bool prim, + uint16_t rbuf); + int PpRcvHandler(); protected: size_t fPC_pbuf; //!< PrimClist: pbuf index size_t fPC_rbuf; //!< PrimClist: rbuf index + uint16_t fPrQlim; //!< reader queue limit + uint16_t fPrRlim; //!< reader interrupt rate limit + uint16_t fPpRlim; //!< puncher interrupt rate limit + uint16_t fItype; //!< interface type + uint16_t fFsize; //!< fifo size + uint16_t fPpRblkSize; //!< puncher rblk chunk size + bool fPpQueBusy; //!< puncher queue busy + int fPrDrain; //!< reader drain state }; } // end namespace Retro -//#include "Rw11CntlPC11.ipp" +#include "Rw11CntlPC11.ipp" #endif diff --git a/tools/src/librw11/Rw11CntlPC11.ipp b/tools/src/librw11/Rw11CntlPC11.ipp new file mode 100644 index 00000000..15093d36 --- /dev/null +++ b/tools/src/librw11/Rw11CntlPC11.ipp @@ -0,0 +1,75 @@ +// $Id: Rw11CntlPC11.ipp 1132 2019-04-14 20:23:40Z mueller $ +// +// Copyright 2019- by Walter F.J. Mueller +// +// This program is free software; you may redistribute and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for complete details. +// +// Revision History: +// Date Rev Version Comment +// 2019-04-14 1132 1.0 Initial version +// --------------------------------------------------------------------------- + +/*! + \brief Implemenation (inline) of Rw11CntlPC11. +*/ + + +// all method definitions in namespace Retro +namespace Retro { + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +inline uint16_t Rw11CntlPC11::PrQlim() const +{ + return fPrQlim; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +inline uint16_t Rw11CntlPC11::PrRlim() const +{ + return fPrRlim; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +inline uint16_t Rw11CntlPC11::PpRlim() const +{ + return fPpRlim; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +inline uint16_t Rw11CntlPC11::Itype() const +{ + return fItype; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +inline bool Rw11CntlPC11::Buffered() const +{ + return fFsize > 0; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +inline uint16_t Rw11CntlPC11::FifoSize() const +{ + return fFsize; +} + +} // end namespace Retro diff --git a/tools/src/librw11/Rw11UnitPC11.cpp b/tools/src/librw11/Rw11UnitPC11.cpp index 9a0750fa..0c4e73b1 100644 --- a/tools/src/librw11/Rw11UnitPC11.cpp +++ b/tools/src/librw11/Rw11UnitPC11.cpp @@ -1,6 +1,6 @@ -// $Id: Rw11UnitPC11.cpp 1081 2018-12-14 22:29:42Z mueller $ +// $Id: Rw11UnitPC11.cpp 1134 2019-04-21 17:18:03Z mueller $ // -// Copyright 2013-2017 by Walter F.J. Mueller +// Copyright 2013-2019 by Walter F.J. Mueller // // This program is free software; you may redistribute and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -13,6 +13,7 @@ // // Revision History: // Date Rev Version Comment +// 2019-04-20 1134 1.1 add AttachDone() // 2017-04-07 868 1.0.1 Dump(): add detail arg // 2013-05-03 515 1.0 Initial version // --------------------------------------------------------------------------- @@ -67,4 +68,14 @@ void Rw11UnitPC11::Dump(std::ostream& os, int ind, const char* text, return; } +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void Rw11UnitPC11::AttachDone() +{ + Cntl().UnitSetup(fIndex); + Cntl().AttachDone(fIndex); + return; +} + } // end namespace Retro diff --git a/tools/src/librw11/Rw11UnitPC11.hpp b/tools/src/librw11/Rw11UnitPC11.hpp index 60fb33e3..a7a4fad7 100644 --- a/tools/src/librw11/Rw11UnitPC11.hpp +++ b/tools/src/librw11/Rw11UnitPC11.hpp @@ -1,6 +1,6 @@ -// $Id: Rw11UnitPC11.hpp 983 2018-01-02 20:35:59Z mueller $ +// $Id: Rw11UnitPC11.hpp 1134 2019-04-21 17:18:03Z mueller $ // -// Copyright 2013-2017 by Walter F.J. Mueller +// Copyright 2013-2019 by Walter F.J. Mueller // // This program is free software; you may redistribute and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -13,6 +13,7 @@ // // Revision History: // Date Rev Version Comment +// 2019-04-20 1134 1.1 add AttachDone() // 2017-04-07 868 1.0.1 Dump(): add detail arg // 2013-05-03 515 1.0 Initial version // --------------------------------------------------------------------------- @@ -42,6 +43,7 @@ namespace Retro { int detail=0) const; protected: + virtual void AttachDone(); }; diff --git a/tools/src/librwxxtpp/RtclRw11CntlPC11.cpp b/tools/src/librwxxtpp/RtclRw11CntlPC11.cpp index 3a5fd13e..88835aa0 100644 --- a/tools/src/librwxxtpp/RtclRw11CntlPC11.cpp +++ b/tools/src/librwxxtpp/RtclRw11CntlPC11.cpp @@ -1,4 +1,4 @@ -// $Id: RtclRw11CntlPC11.cpp 983 2018-01-02 20:35:59Z mueller $ +// $Id: RtclRw11CntlPC11.cpp 1132 2019-04-14 20:23:40Z mueller $ // // Copyright 2013-2017 by Walter F.J. Mueller // @@ -13,6 +13,7 @@ // // Revision History: // Date Rev Version Comment +// 2019-04-14 1132 1.2 add getters& setters for pc11_buf readout // 2017-04-16 878 1.1 add class in ctor;derive from RtclRw11CntlStreamBase // 2013-05-03 515 1.0 Initial version // --------------------------------------------------------------------------- @@ -28,6 +29,7 @@ #include "RtclRw11UnitPC11.hpp" using namespace std; +using namespace std::placeholders; /*! \class Retro::RtclRw11CntlPC11 @@ -42,7 +44,19 @@ namespace Retro { RtclRw11CntlPC11::RtclRw11CntlPC11() : RtclRw11CntlStreamBase("Rw11CntlPC11","stream") -{} +{ + Rw11CntlPC11* pobj = &Obj(); + fGets.Add ("prqlim", bind(&Rw11CntlPC11::PrQlim, pobj)); + fGets.Add ("prrlim", bind(&Rw11CntlPC11::PrRlim, pobj)); + fGets.Add ("pprlim", bind(&Rw11CntlPC11::PpRlim, pobj)); + fGets.Add ("itype", bind(&Rw11CntlPC11::Itype, pobj)); + fGets.Add ("buffered", bind(&Rw11CntlPC11::Buffered, pobj)); + fGets.Add ("fifosize", bind(&Rw11CntlPC11::FifoSize, pobj)); + + fSets.Add ("prqlim", bind(&Rw11CntlPC11::SetPrQlim,pobj, _1)); + fSets.Add ("prrlim", bind(&Rw11CntlPC11::SetPrRlim,pobj, _1)); + fSets.Add ("pprlim", bind(&Rw11CntlPC11::SetPpRlim,pobj, _1)); +} //------------------------------------------+----------------------------------- //! Destructor diff --git a/tools/tbench/README.md b/tools/tbench/README.md index bcca953b..1cf68327 100644 --- a/tools/tbench/README.md +++ b/tools/tbench/README.md @@ -4,11 +4,13 @@ This directory tree contains the **w11 test bench** and is organized in | --------- | ------- | | [cp](cp) | test of CPU control port | | [deuna](deuna) | test of `deuna` ibus device | +| [pc11](pc11) | test of `pc11` ibus device | | [rhrp](rhrp) | test of `rhrp` ibus device | | [tm11](tm11) | test of `tm11` ibus device | | [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) | +| [w11a_ibmon](w11a_ibmon) | test of `ibd_ibmon` (ibus monitor) | | [w11a_ibtst](w11a_ibtst) | test of `ibd_ibtst` (ibus test device) | | [w11a_kw11p](w11a_kw11p) | test of `kw11p` ibus device (programmable clock) | | [w11a_pcnt](w11a_pcnt) | test of CPU `pcnt` unit (performance counters) | diff --git a/tools/tbench/dev_all.dat b/tools/tbench/dev_all.dat index dbd7389e..7682727c 100644 --- a/tools/tbench/dev_all.dat +++ b/tools/tbench/dev_all.dat @@ -1,8 +1,9 @@ -# $Id: dev_all.dat 1120 2019-03-09 18:19:31Z mueller $ +# $Id: dev_all.dat 1132 2019-04-14 20:23:40Z mueller $ # ## steering file for all devices tests # test_lp11_all.tcl +@pc11/pc11_all.dat @rhrp/rhrp_all.dat @tm11/tm11_all.dat @deuna/deuna_all.dat diff --git a/tools/tbench/pc11/pc11_all.dat b/tools/tbench/pc11/pc11_all.dat new file mode 100644 index 00000000..60597937 --- /dev/null +++ b/tools/tbench/pc11/pc11_all.dat @@ -0,0 +1,7 @@ +# $Id: pc11_all.dat 1131 2019-04-14 13:24:25Z mueller $ +# +## steering file for all pc11 tests +# +test_pc11_pp.tcl +test_pc11_pr.tcl +test_pc11_loop.tcl diff --git a/tools/tbench/pc11/test_pc11_loop.tcl b/tools/tbench/pc11/test_pc11_loop.tcl new file mode 100644 index 00000000..6779ed1e --- /dev/null +++ b/tools/tbench/pc11/test_pc11_loop.tcl @@ -0,0 +1,129 @@ +# $Id: test_pc11_loop.tcl 1134 2019-04-21 17:18:03Z mueller $ +# +# Copyright 2019- by Walter F.J. Mueller +# License disclaimer see License.txt in $RETROBASE directory +# +# Revision History: +# Date Rev Version Comment +# 2019-04-20 1134 1.0 Initial version +# 2019-04-07 1129 0.1 First draft +# +# Test paper reader + puncher response + +# ---------------------------------------------------------------------------- +rlc log "test_pc11_loop: test pc11 reader+puncher response -------------------" +package require ibd_pc11 +if {![ibd_pc11::setup]} { + rlc log " test_pc11_loop-W: device not found, test aborted" + return +} + +# obtain 'type' from rcsr +$cpu cp -ribr pca.rcsr pcrcsr +set type [regget ibd_pc11::RRCSR(type) $pcrcsr] +if {$type == 0} { + rlc log " test_pc11_loop-W: only available for buffered pc11" + return +} + +set fsize [expr {(1<<$type)-1}] +set nbyte [expr {$fsize - 3}] + +# -- Section A --------------------------------------------------------------- +rlc log " A1: loopback test: copy reader -> puncher ($nbyte bytes)---------" + +# load test code +$cpu ldasm -lst lst -sym sym { + .include |lib/defs_cpu.mac| + .include |lib/defs_pc.mac| + .include |lib/vec_cpucatch.mac| + .include |lib/vec_devcatch.mac| +; + . = v..ptr ; setup reader vector + .word vh.pr + .word cp.pr7 + + . = v..ptp ; setup puncher vector + .word vh.pp + .word cp.pr7 + +; + . = 1000 ; code area +stack: +; +; register usage: +; r4 buffer write ptr +; r5 buffer read ptr +; +start: +1$: tst @#pp.csr ; test err + bmi 1$ ; loop on err=1 +2$: tst @#pr.csr ; test err + bmi 2$ ; loop on err=1 +; + mov #buf,r4 ; setup write ptr + mov r4,r5 ; setup read ptr +; + spl 7 + bic #pp.ie,@#pp.csr ;;; disable pp irupt + bis #pr.ie,@#pr.csr ;;; enable pr irupt + bis #pr.ena,@#pr.csr ;;; reader enable (read next) + spl 0 +; +3$: wait + br 3$ +; +vh.pr: tstb @#pr.csr ;;; done set ? + bpl ehalt ;;; if pl not -> error halt + movb @#pr.buf,(r4)+ ;;; read char, to fifo + bis #pr.ena,@#pr.csr ;;; reader enable (read next) + bis #pp.ie,@#pp.csr ;;; enable pp irupt + rti +; +vh.pp: tstb @#pp.csr ;;; ready set ? + bpl ehalt ;;; if not error halt + cmp r4,r5 ;;; data in fifo ? + beq ehalt ;;; if eq not -> error halt + movb (r5)+,@#pp.buf ;;; send char to punch + beq lchar ;;; if eq last char seen + cmp r4,r5 ;;; more char in fifo + bne 1$ ;;; if ne yes, keep irupt enabled + bic #pp.ie,@#pp.csr ;;; if fifo empty, disable pp irupt +1$: rti + +ehalt: halt +lchar: halt +stop: +buf: .blkb 256. +} + +## puts $lst + +set rdata {} +set pdata {} +for {set i 0} { $i < $nbyte } {incr i} { + set v [expr {$nbyte-$i-1}] + lappend rdata $v + lappend pdata [regbldkv ibd_pc11::RPBUF val 1 size [expr {$nbyte-$i}] data $v] +} + +# ensure pr and pp err=0 +$cpu cp \ + -wibr pca.rcsr 0x0 \ + -wibr pca.pcsr 0x0 + +rw11::asmrun $cpu sym + +# fill reader fifo in two chunks +$cpu cp -wbibr pca.rbuf [lrange $rdata 0 [expr {$nbyte/2}] ] +$cpu cp -wbibr pca.rbuf [lrange $rdata [expr {$nbyte/2+1}] end ] + +rw11::asmwait $cpu sym + +# read and check puncher fifo +$cpu cp \ + -wibr pca.rcsr 0x0 \ + -wibr pca.pcsr 0x0 \ + -rbibr pca.pbuf $nbyte -edata $pdata + +#puts [rw11::cml $cpu] diff --git a/tools/tbench/pc11/test_pc11_pp.tcl b/tools/tbench/pc11/test_pc11_pp.tcl new file mode 100644 index 00000000..ce6eeb09 --- /dev/null +++ b/tools/tbench/pc11/test_pc11_pp.tcl @@ -0,0 +1,513 @@ +# $Id: test_pc11_pp.tcl 1137 2019-04-24 10:49:19Z mueller $ +# +# Copyright 2019- by Walter F.J. Mueller +# License disclaimer see License.txt in $RETROBASE directory +# +# Revision History: +# Date Rev Version Comment +# 2019-04-21 1134 1.0 Initial version +# 2019-04-07 1129 0.1 First draft +# +# Test paper puncher response +# A: register basics + +# ---------------------------------------------------------------------------- +rlc log "test_pc11_pp: test pc11 paper puncher resonse -----------------------" +package require ibd_pc11 +if {![ibd_pc11::setup]} { + rlc log " test_pc11_pp-W: device not found, test aborted" + return +} + +rlc set statmask $rw11::STAT_DEFMASK +rlc set statvalue 0 + +set attnpc [expr {1<<$ibd_pc11::ANUM}] +set attncpu [expr {1<<$rw11::ANUM}] + +# -- Section A --------------------------------------------------------------- +rlc log " A1: test csr response -------------------------------------" +rlc log " A1.1: csr err, rdy ---------------------------------" +# breset & rem ERR=0 --> test RDY=1,IE=0 +# rem ERR=1 --> test ERR=1,RDY=1,IE=0 (RDY not rem writable) +# loc ERR=0 --> test ERR=1,RDY=1,IE=0 (ERR not loc writable) +# rem ERR=0 --> test ERR=0,RDY=1,IE=0 +# breset --> test ERR=0 (not set by breset) +set rcsrmask [regbld ibd_pc11::RPCSR err rdy ie ir] + +$cpu cp \ + -breset \ + -wibr pca.pcsr 0x0 \ + -ribr pca.pcsr -edata [regbld ibd_pc11::RPCSR rdy] $rcsrmask \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -wibr pca.pcsr [regbld ibd_pc11::RPCSR err] \ + -ribr pca.pcsr -edata [regbld ibd_pc11::RPCSR err rdy] $rcsrmask \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR err rdy] \ + -wma pca.pcsr 0x0 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR err rdy] \ + -wibr pca.pcsr 0x0 \ + -ribr pca.pcsr -edata [regbld ibd_pc11::RPCSR rdy] $rcsrmask \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -breset \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] + +# remember 'type' retrieved from rcsr for later tests +$cpu cp -ribr pca.rcsr pcrcsr +set type [regget ibd_pc11::RRCSR(type) $pcrcsr] + +rlc log " A1.2: csr ie, ir -----------------------------------" +# loc IE=1 --> seen on loc and rem; rem sees IR=1 +# rem IE=0 --> stays, IE not rem writable +# loc IE=0 --> seen on loc and rem; rem sees IR=0 +$cpu cp \ + -wma pca.pcsr [regbld ibd_pc11::PCSR ie] \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy ie] \ + -ribr pca.pcsr -edata [regbld ibd_pc11::RPCSR rdy ie ir] $rcsrmask\ + -wibr pca.pcsr 0x0 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy ie] \ + -ribr pca.pcsr -edata [regbld ibd_pc11::RPCSR rdy ie ir] $rcsrmask\ + -wma pca.pcsr 0x0 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -ribr pca.pcsr -edata [regbld ibd_pc11::RPCSR rdy] $rcsrmask + +if {$type > 0} { # if buffered test rlim + rlc log " A1.3: csr rlim -----------------------------------" + # rem write rlim --> seen rem, not loc + # loc write rlim --> stays, rlim not loc writable + # breset --> rlim not cleared + set rcsrmaskbuf [regbld ibd_pc11::RPCSR err {rlim -1} rdy ie] + $cpu cp \ + -wibr pca.pcsr [regbld ibd_pc11::RPCSR {rlim 1}] \ + -ribr pca.pcsr -edata [regbld ibd_pc11::RPCSR {rlim 1} rdy] $rcsrmaskbuf \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -wibr pca.pcsr [regbld ibd_pc11::RPCSR {rlim 7}] \ + -ribr pca.pcsr -edata [regbld ibd_pc11::RPCSR {rlim 7} rdy] $rcsrmaskbuf \ + -wma pca.pcsr 0x0 \ + -ribr pca.pcsr -edata [regbld ibd_pc11::RPCSR {rlim 7} rdy] $rcsrmaskbuf \ + -breset \ + -ribr pca.pcsr -edata [regbld ibd_pc11::RPCSR {rlim 7} rdy] $rcsrmaskbuf \ + -wibr pca.pcsr [regbld ibd_pc11::RPCSR {rlim 0}] \ + -ribr pca.pcsr -edata [regbld ibd_pc11::RPCSR {rlim 0} rdy] $rcsrmaskbuf +} + +if {$type == 0} { # unbuffered -------------------------- + rlc log " A2: test data response (unbuffered) -----------------------" + rlc log " A2.1: loc write, rem read ------------------------" + # loc wr buf --> test RDY=0 + # loc rd buf --> test RDY=0 (loc read is noop); test attn send + # rem wr buf --> test RDY=1 + $cpu cp \ + -wma pca.pbuf 0107 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR] \ + -rma pca.pbuf \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR] \ + -ribr pca.pbuf -edata [regbld ibd_pc11::RPBUF val {size 1} {data 0107} ] \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] + # expect and harvest attn (drop other attn potentially triggered by breset) + rlc wtlam 1. + rlc exec -attn -edata $attnpc $attnpc + + rlc log " A2.2: csr.err=1, no attn, RDY=1, no val data -----" + $cpu cp \ + -wibr pca.pcsr [regbld ibd_pc11::RPCSR err] \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR err rdy] \ + -wma pca.pbuf 031 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR err rdy] \ + -wibr pca.pcsr 0x0 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -ribr pca.pbuf -edata [regbld ibd_pc11::RPBUF {size 0} {data 0107} ] + # test that no attn send + rlc exec -attn -edata 0x0 + + rlc log " A2.3: 8 bit data; rdy set on breset --------------" + $cpu cp \ + -wma pca.pbuf 0370 \ + -ribr pca.pbuf -edata [regbld ibd_pc11::RPBUF val {size 1} {data 0370} ] \ + -wma pca.pbuf 040 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR] \ + -breset \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] + # harvest breset/creset triggered attn's + rlc exec -attn + rlc wtlam 0. + + rlc log " A2.4: loc write, csr.err sets RDY, data invalid --" + $cpu cp \ + -wma pca.pbuf 032 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR] \ + -wibr pca.pcsr [regbld ibd_pc11::RPCSR err] \ + -wibr pca.pcsr 0x0 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -ribr pca.pbuf -edata [regbld ibd_pc11::RPBUF {size 0} {data 032} ] + # expect and harvest attn + rlc wtlam 1. + rlc exec -attn -edata $attnpc + +} else { # buffered --------------------------- + set fsize [expr {(1<<$type)-1}] + + rlc log " A2: test data response (basic fifo; AWIDTH=$type) --" + rlc log " A2.1: loc write, rem read; rbuf.psize check -------" + # loc wr buf --> test RDY=1 rbuf.psize=1 + # loc rd buf --> test RDY=1 (loc read is noop); test attn send + # loc wr buf --> test RDY=1 rbuf.psize=2 + # loc wr buf --> test RDY=1 rbuf.psize=3 + # rem wr buf --> test VAL=1,SIZE=3 rbuf.psize=2 + # rem wr buf --> test VAL=1,SIZE=2 rbuf.psize=1 + # rem wr buf --> test VAL=1,SIZE=1 rbuf.psize=0 + $cpu cp \ + -ribr pca.rbuf -edata [regbldkv ibd_pc11::RRBUF psize 0] \ + -wma pca.pbuf 031 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -ribr pca.rbuf -edata [regbldkv ibd_pc11::RRBUF psize 1] \ + -rma pca.pbuf \ + -wma pca.pbuf 032 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -ribr pca.rbuf -edata [regbldkv ibd_pc11::RRBUF psize 2] \ + -wma pca.pbuf 033 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -ribr pca.rbuf -edata [regbldkv ibd_pc11::RRBUF psize 3] \ + -ribr pca.pbuf -edata [regbldkv ibd_pc11::RPBUF val 1 size 3 data 031] \ + -ribr pca.rbuf -edata [regbldkv ibd_pc11::RRBUF psize 2] \ + -ribr pca.pbuf -edata [regbldkv ibd_pc11::RPBUF val 1 size 2 data 032] \ + -ribr pca.rbuf -edata [regbldkv ibd_pc11::RRBUF psize 1] \ + -ribr pca.pbuf -edata [regbldkv ibd_pc11::RPBUF val 1 size 1 data 033] \ + -ribr pca.rbuf -edata [regbldkv ibd_pc11::RRBUF psize 0] \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] + # expect and harvest attn (drop other attn potentially triggered by breset) + rlc wtlam 1. + rlc exec -attn -edata $attnpc $attnpc + + rlc log " A2.2: csr.err=1, loc write not stored, no attn ---" + $cpu cp \ + -wibr pca.pcsr [regbld ibd_pc11::PCSR err] \ + -wma pca.pbuf 034 \ + -wibr pca.pcsr 0x0 \ + -ribr pca.pbuf -estaterr + # test that no attn send + rlc exec -attn -edata 0x0 + + rlc log " A2.3: loc write, rem blk read abort; 8 bit data --" + # loc wr two char; rem blk rd three char --> expect 2 and error + # test 7 bit data path trunctation + $cpu cp \ + -wma pca.pbuf 0340 \ + -wma pca.pbuf 0037 \ + -rbibr pca.pbuf 4 -estaterr -edone 2 -edata \ + [list [regbldkv ibd_pc11::RPBUF val 1 size 2 data 0340] \ + [regbldkv ibd_pc11::RPBUF val 1 size 1 data 0037] ] + # expect and harvest attn + rlc wtlam 1. + rlc exec -attn -edata $attnpc + + rlc log " A2.4: loc write, breset does not clear -----------" + $cpu cp \ + -wma pca.pbuf 041 \ + -wma pca.pbuf 042 \ + -breset \ + -rbibr pca.pbuf 3 -estaterr -edata \ + [list [regbldkv ibd_pc11::RPBUF val 1 size 2 data 0041] \ + [regbldkv ibd_pc11::RPBUF val 1 size 1 data 0042] ] + # expect and harvest attn (drop other attn potentially triggered by breset) + rlc wtlam 1. + rlc exec -attn -edata $attnpc $attnpc + + rlc log " A2.5: loc write, csr.err clears fifo -------------" + $cpu cp \ + -wma pca.pbuf 043 \ + -wma pca.pbuf 044 \ + -wibr pca.pcsr [regbld ibd_pc11::RPCSR err] \ + -wibr pca.pcsr 0x0 \ + -rbibr pca.pbuf 3 -estaterr -edone 0 + # expect and harvest attn (drop other attn potentially triggered by breset) + rlc wtlam 1. + rlc exec -attn -edata $attnpc $attnpc + + rlc log " A3: test fifo logic (csr.rdy and attn) ------------------" + rlc log " A3.1: 1st loc write, get attn --------------------" + # 1 loc wr -> get attn (1 in fifo; RDY=1) + $cpu cp \ + -wma pca.pbuf 051 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] + # expect and harvest attn + rlc wtlam 1. + rlc exec -attn -edata $attnpc + + rlc log " A3.2: 2nd loc write, no attn ---------------------" + # 1 loc wr -> no attn (2 in fifo) + $cpu cp \ + -wma pca.pbuf 052 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] + rlc exec -attn -edata 0x0 + + rlc log " A3.3: write/read to non-empty fifo -> no attn ----" + # 1 rem rd (1 in fifo; RDY=1) + # 1 loc wr -> no attn (2 in fifo; RDY=1) + # 1 rem rd (1 in fifo; RDY=1) + $cpu cp \ + -ribr pca.pbuf -edata [regbldkv ibd_pc11::RPBUF val 1 size 2 data 051] \ + -wma pca.pbuf 053 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] + + rlc exec -attn -edata 0x0 + $cpu cp \ + -ribr pca.pbuf -edata [regbldkv ibd_pc11::RPBUF val 1 size 2 data 052] \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] + + rlc log " A3.4: fill fifo, RDY 1->0 on $fsize char ---------" + # x = fsize in following + # x-2 loc wr (x-1 in fifo; RDY=1) + # 1 rem rd (x-2 in fifo; RDY=1) + # 1 rem rd (x-3 in fifo; RDY=1) + $cpu ldasm -lst lst -sym sym { + .include |lib/vec_cpucatch.mac| + . = 1000 ; data area +stack: +; +start: mov r2,(r0) + sob r1,start + halt +stop: +} + # specify ps in asmrun to use -start (and avoid a creset!!) + set fs0 $fsize + set fs1 [expr {$fsize-1}] + set fs2 [expr {$fsize-2}] + set fs4 [expr {$fsize-4}] + rw11::asmrun $cpu sym r0 [$cpu imap pca.pbuf] \ + r1 $fs2 \ + r2 066 \ + ps [regbld rw11::PSW {cmode k} {pri 7}] + rw11::asmwait $cpu sym + rw11::asmtreg $cpu r1 0 + + $cpu cp \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -ribr pca.pbuf -edata [regbldkv ibd_pc11::RPBUF val 1 size $fs1 data 053] \ + -ribr pca.pbuf -edata [regbldkv ibd_pc11::RPBUF val 1 size $fs2 data 066] \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] + + # 1 loc wr -> (x-2 in fifo; RDY=1) + # 1 loc wr -> (x-1 in fifo; RDY=1) + # 1 loc wr -> (x in fifo; RDY=0) + # 1 loc wr -> (x in fifo; RDY=0) (overfill !!) + $cpu cp \ + -wma pca.pbuf 066 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -wma pca.pbuf 066 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -wma pca.pbuf 066 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR] \ + -wma pca.pbuf 066 \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR] + + rlc log " A3.5: partial fifo read, RDY goes 1 --------------" + # 1 rem rd -> (x-1 in fifo; RDY=1) + # 1 rem rd -> (x-2 in fifo; RDY=1) + $cpu cp \ + -ribr pca.pbuf -edata [regbldkv ibd_pc11::RPBUF val 1 size $fs0 data 066] \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -ribr pca.pbuf -edata [regbldkv ibd_pc11::RPBUF val 1 size $fs1 data 066] \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] + + rlc log " A3.6: full fifo read -----------------------------" + # x-4 rem rd -> ( 2 in fifo; RDY=1) + # 1 rem rd -> ( 1 in fifo; RDY=1) + # 1 rem rd -> ( 0 in fifo; RDY=1) + # 1 rem rd -> error + set edata {} + for {set i 0} { $i < $fs4 } {incr i} { + lappend edata [regbldkv ibd_pc11::RPBUF val 1 size [expr {$fs2-$i}] data 066] + } + $cpu cp \ + -rbibr pca.pbuf $fs4 -edata $edata \ + -ribr pca.pbuf -edata [regbldkv ibd_pc11::RPBUF val 1 size 2 data 066] \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -ribr pca.pbuf -edata [regbldkv ibd_pc11::RPBUF val 1 size 1 data 066] \ + -rma pca.pcsr -edata [regbld ibd_pc11::PCSR rdy] \ + -ribr pca.pbuf -estaterr +} + +# harvest triggered attn's +rlc exec -attn +rlc wtlam 0. + +# -- Section B --------------------------------------------------------------- +rlc log " B1: test csr.ie and basic interrupt response --------------" +# load test code +$cpu ldasm -lst lst -sym sym { + .include |lib/defs_cpu.mac| + .include |lib/defs_pc.mac| + . = va.ptp ; setup PC11 puncher interrupt vector + .word vh.ptp + .word cp.pr7 +; + . = 1000 ; code area +stack: +; +; use in following mov to psw instead of spl to allow immediate interrupt +; +start: spl 7 ;;; lock-out interrupts + mov #vh.ptp,@#va.ptp ;;; setup ptp handler + mov #pp.ie,@#pp.csr ;;; enable ptp interrupts + mov #cp.pr6,@#cp.psw ;;; allow pri=7 + mov #cp.pr5,@#cp.psw ;;; allow pri=6 + mov #cp.pr4,@#cp.psw ;;; allow pri=5 + mov #cp.pr3,@#cp.psw ;;; allow pri=4 + mov #cp.pr2,@#cp.psw ;;; allow pri=3 + mov #cp.pr1,@#cp.psw ;;; allow pri=2 + mov #cp.pr0,@#cp.psw ;;; allow pri=1 + halt ;;; +; +vh.ptp: halt ;;; ptp handler +stop: +; +; continue to perform err interrupt test +; + mov #vh.err,@#va.ptp ;;; setup err handler + spl 0 ; allow interrupts +1$: wait ; wait for interrupts + br 1$ + +vh.err: halt ;;; err handler +stop1: +} + +rlc log " B1.1: ie 0->1 interrupt ----------------------------" + +# check that interrupt done, and pushed psw has pri=3 (device is pri=4) +cpu0 cp -wibr pca.pcsr 0x0; # ensure err = 0 +rw11::asmrun $cpu sym +rw11::asmwait $cpu sym +rw11::asmtreg $cpu sp [expr {$sym(stack)-4}] +rw11::asmtmem $cpu [expr {$sym(stack)-2}] [list [regbld rw11::PSW {pri 3}]] + +rlc log " B1.2: err interrupt --------------------------------" + +# continue code; set err=1 -> should interrupt again +cpu0 cp \ + -start \ + -wibr pca.pcsr [regbld ibd_pc11::RPCSR err] + +rw11::asmwait $cpu sym 0. stop1 +rw11::asmtreg $cpu sp [expr {$sym(stack)-8}] + +cpu0 cp -wibr pca.pcsr 0x0; # ensure err = 0 again + +rlc log " B2: test csr.ie and cpu write -> rri read -----------------" + +# load test code +$cpu ldasm -lst lst -sym sym { + .include |lib/defs_cpu.mac| + .include |lib/defs_pc.mac| +; + .include |lib/vec_cpucatch.mac| + .include |lib/vec_devcatch.mac| +; + . = v..ptp ; setup PC11 puncher interrupt vector + .word vh.ptp + .word cp.pr7 +; + . = 1000 ; data area +stack: +; +start: ; call with r0= + spl 7 + mov #pp.ie,@#pp.csr ; enable interrupt + clr r1 ; clear out char + spl 0 +1$: wait ; wait for interrupt + br 1$ ; forever +; +vh.ptp: movb r1,@#pp.buf ;;; write char + dec r0 ;;; all done ? + beq 1$ ;;; if eq yes, quit + incb r1 ;;; + bicb #200,r1 ;;; + tstb @#pp.csr ;;; ready set ? + bmi vh.ptp ;;; if mi yes, loop + rti ;;; otherwise exit interrupt +; +1$: halt +stop: +} + +set nchar 4 +set charcur 0 +set charseen 0 +set haltseen 0 + +if {$type == 0} { # unbuffered -------------------------- + rw11::asmrun $cpu sym r0 $nchar + while {1} { + if {[rlc wtlam 1.] >= 1.} { break } + rlc exec -attn attnpat + if {$attnpat & $attncpu} { # cpu attn + set haltseen 1 + } + if {$attnpat & $attnpc} { # pc attn + $cpu cp \ + -ribr pca.pbuf -edata [regbldkv ibd_pc11::RPBUF \ + val 1 size 1 data $charcur] + set charcur [expr { ($charcur+1) & 0377 }] + incr charseen + } + if {$charseen == $nchar && $haltseen} { break } + } + +} else { # buffered ----------------------------- + # setup char count as about 1.25 of fifo size + # AWIDTH 4 15+ 3 = 18 + # AWIDTH 5 31+ 7 = 38 + # AWIDTH 6 63+15 = 78 + # AWIDTH 7 127+31 = 158 + set nchar [expr {$fsize + ($fsize>>2)}] + set rsize [expr {$fsize>>2}] + set wttout 10.; # wtlam timeout + + set fstatmsk [regbld rw11::STAT cmderr rbtout rbnak]; # don't check err !! + + # try this to verify rlim logic --> quite a slow down !! + # $cpu cp -wibr pca.pcsr [regbld ibd_pc11::RPCSR {rlim 1}] + + rw11::asmrun $cpu sym r0 $nchar + while (1) { + if {[rlc wtlam $wttout] >= $wttout} { break }; # quit on timeout + rlc exec -attn attnpat + + if {$attnpat & $attncpu} { # cpu attn + set haltseen 1 + } + if {$attnpat & $attnpc} { # pc attn + while (1) { + $cpu cp \ + -rbibr pca.pbuf $rsize fdata -estat 0x0 $fstatmsk + for {set i 0} { $i < [llength $fdata] } {incr i} { + set rbuf [lindex $fdata $i] + set val [regget ibd_pc11::RPBUF(val) $rbuf] + set size [regget ibd_pc11::RPBUF(size) $rbuf] + set data [regget ibd_pc11::RPBUF(data) $rbuf] + if {$val != 1 || $data != $charcur} { + rlc log "FAIL: bad data: val: $val; data: $data, exp: $charcur" + rlc errcnt -inc + } + if {$i == 0} { set rsize $size } + set charcur [expr { ($charcur+1) & 0177 }] + incr charseen + } + if {$size <= 1} { + rlc log " rbibr chain ends with size=1 after $charseen" + break; + } + } + } + if {$charseen == $nchar && $haltseen} { break } + } +} + +$cpu cp -rpc -edata $sym(stop); # check proper stop pc +if {$haltseen == 0} { $cpu cp -creset }; # kill rouge code + +# harvest any dangling attn +rlc exec -attn +rlc wtlam 0. diff --git a/tools/tbench/pc11/test_pc11_pr.tcl b/tools/tbench/pc11/test_pc11_pr.tcl new file mode 100644 index 00000000..1a3fd69e --- /dev/null +++ b/tools/tbench/pc11/test_pc11_pr.tcl @@ -0,0 +1,404 @@ +# $Id: test_pc11_pr.tcl 1137 2019-04-24 10:49:19Z mueller $ +# +# Copyright 2019- by Walter F.J. Mueller +# License disclaimer see License.txt in $RETROBASE directory +# +# Revision History: +# Date Rev Version Comment +# 2019-04-21 1134 1.0 Initial version +# 2019-04-12 1131 0.1 First draft +# +# Test paper reader response + +# ---------------------------------------------------------------------------- +rlc log "test_pc11_pr: test pc11 paper reader resonse ------------------------" +package require ibd_pc11 +if {![ibd_pc11::setup]} { + rlc log " test_pc11_pr-W: device not found, test aborted" + return +} + +rlc set statmask $rw11::STAT_DEFMASK +rlc set statvalue 0 + +set attnpc [expr {1<<$ibd_pc11::ANUM}] +set attncpu [expr {1<<$rw11::ANUM}] + +# -- Section A --------------------------------------------------------------- +rlc log " A1: test csr response -------------------------------------" +rlc log " A1.1: csr err --------------------------------------" +# breset & rem ERR=0 --> test DONE=0,IE=0 +# rem ERR=1 --> test ERR=1,DONE=0,IE=0 (DONE not rem writable) +# loc ERR=0 --> test ERR=1,DONE=0,IE=0 (ERR not loc writable) +# rem ERR=0 --> test ERR=0,DONE=0,IE=0 +# breset --> test ERR=0 (not set by breset) +set rcsrmask [regbld ibd_pc11::RRCSR err busy done ie ir ique iack] + +$cpu cp \ + -breset \ + -wibr pca.rcsr 0x0 \ + -ribr pca.rcsr -edata [regbld ibd_pc11::RRCSR ] $rcsrmask \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR ] \ + -wibr pca.rcsr [regbld ibd_pc11::RRCSR err] \ + -ribr pca.rcsr -edata [regbld ibd_pc11::RRCSR err ] $rcsrmask \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR err ] \ + -wma pca.rcsr 0x0 \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR err ] \ + -wibr pca.rcsr 0x0 \ + -ribr pca.rcsr -edata [regbld ibd_pc11::RRCSR ] $rcsrmask \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR ] \ + -breset \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR ] + +# remember 'type' retrieved from rcsr for later tests +$cpu cp -ribr pca.rcsr pcrcsr +set type [regget ibd_pc11::RRCSR(type) $pcrcsr] + +rlc log " A1.2: csr ie ---------------------------------------" +# loc IE=1 --> seen on loc and rem +# rem IE=0 --> stays, IE not rem writable +# loc IE=0 --> seen on loc and rem +$cpu cp \ + -wma pca.rcsr [regbld ibd_pc11::RCSR ie] \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR ie] \ + -ribr pca.rcsr -edata [regbld ibd_pc11::RRCSR ie] $rcsrmask\ + -wibr pca.rcsr 0x0 \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR ie] \ + -ribr pca.rcsr -edata [regbld ibd_pc11::RRCSR ie] $rcsrmask\ + -wma pca.rcsr 0x0 \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR ] \ + -ribr pca.rcsr -edata [regbld ibd_pc11::RRCSR ] $rcsrmask + +if {$type > 0} { # if buffered test rlim + rlc log " A1.3: csr rlim -----------------------------------" + # rem write rlim --> seen rem, not loc + # loc write rlim --> stays, rlim not loc writable + # breset --> rlim not cleared + set rcsrmaskbuf [regbld ibd_pc11::RRCSR err {rlim -1} done ie ir ique iack] + $cpu cp \ + -wibr pca.rcsr [regbld ibd_pc11::RRCSR {rlim 1}] \ + -ribr pca.rcsr -edata [regbld ibd_pc11::RRCSR {rlim 1} ] $rcsrmaskbuf \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR ] \ + -wibr pca.rcsr [regbld ibd_pc11::RRCSR {rlim 7}] \ + -ribr pca.rcsr -edata [regbld ibd_pc11::RRCSR {rlim 7} ] $rcsrmaskbuf \ + -wma pca.rcsr 0x0 \ + -ribr pca.rcsr -edata [regbld ibd_pc11::RRCSR {rlim 7} ] $rcsrmaskbuf \ + -breset \ + -ribr pca.rcsr -edata [regbld ibd_pc11::RRCSR {rlim 7} ] $rcsrmaskbuf \ + -wibr pca.rcsr [regbld ibd_pc11::RRCSR {rlim 0}] \ + -ribr pca.rcsr -edata [regbld ibd_pc11::RRCSR {rlim 0} ] $rcsrmaskbuf +} + +if {$type == 0} { # unbuffered -------------------------- + rlc log " A2: test data response (unbuffered) -----------------------" + rlc log " A2.1: rem write, loc read ------------------------" + # loc wr csr.ena --> test BUSY=1; test rem rbuf.busy; test attn send + $cpu cp \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF] \ + -wma pca.rcsr [regbld ibd_pc11::RCSR ena] \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR busy] \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF rbusy] + # expect and harvest attn (drop other attn potentially triggered by breset) + rlc wtlam 1. + rlc exec -attn -edata $attnpc $attnpc + # rem wr buf --> test DONE=1 (1 cmd delay) + # loc rd buf --> test DONE=0; test rem rbuf.busy=0 + # loc rd buf --> test that buf cleared + $cpu cp \ + -wibr pca.rbuf 0107 \ + -rma pca.rcsr \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR done] \ + -rma pca.rbuf -edata 0107 \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR ] \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF ] \ + -rma pca.rbuf -edata 0x0 + + rlc log " A2.2: rem write, loc write (discards data) -------" + # loc wr csr.ena --> test BUSY=1; test rem rbuf.busy; test attn send + $cpu cp \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF] \ + -wma pca.rcsr [regbld ibd_pc11::RCSR ena] \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR busy] \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF rbusy] + # expect and harvest attn (drop other attn potentially triggered by breset) + rlc wtlam 1. + rlc exec -attn -edata $attnpc $attnpc + # rem wr buf --> test DONE=1 (1 cmd delay) + # loc wr buf --> test DONE=0; test rem rbuf.busy=0 (do write here !!) + # loc rd buf --> test that buf cleared + $cpu cp \ + -wibr pca.rbuf 0110 \ + -rma pca.rcsr \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR done] \ + -wma pca.rbuf 0177 \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR ] \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF ] \ + -rma pca.rbuf -edata 0x0 + +} else { # buffered --------------------------- + set fsize [expr {(1<<$type)-1}] + + rlc log " A2: test data response (basic fifo; AWIDTH=$type) --------" + rlc log " A2.1: rem write, loc read ------------------------" + + # loc wr csr.ena --> test BUSY=1; test rem rbuf.busy + $cpu cp \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF] \ + -wma pca.rcsr [regbld ibd_pc11::RCSR ena] \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR busy] \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF rbusy] + # Note: pc11_buf send an attn only when reader buffer is emptied + # pc11_buf does not send an attn when ENA set 1 and not data + # test that no attn send + rlc exec -attn -edata 0x0 + # rem wr buf --> test DONE=1 + # loc rd buf --> test DONE=0; test rem rbuf.busy=0 + # loc rd buf --> test that buf cleared + $cpu cp \ + -wibr pca.rbuf 0107 \ + -rma pca.rcsr \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR done] \ + -rma pca.rbuf -edata 0107 \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR ] \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF ] \ + -rma pca.rbuf -edata 0x0 + # expect and harvest attn + rlc wtlam 1. + rlc exec -attn -edata $attnpc $attnpc + + rlc log " A2.2: rem write, loc write (discards data) -------" + # loc wr csr.ena --> test BUSY=1; test rem rbuf.busy + $cpu cp \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF] \ + -wma pca.rcsr [regbld ibd_pc11::RCSR ena] \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR busy] \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF rbusy] + # test that no attn send + rlc exec -attn -edata 0x0 + # rem wr buf --> test DONE=1 (1 cmd delay) + # loc wr buf --> test DONE=0; test rem rbuf.busy=0 (do write here !!) + # loc rd buf --> test that buf cleared + $cpu cp \ + -wibr pca.rbuf 0110 \ + -rma pca.rcsr \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR done] \ + -wma pca.rbuf 0177 \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR ] \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF ] \ + -rma pca.rbuf -edata 0x0 + # expect and harvest attn + rlc wtlam 1. + rlc exec -attn -edata $attnpc $attnpc + + rlc log " A2.3: test fifo csr.fclr clears and breset doesn't" + # rem wr buf --> test rbuf.size=1 + # rem wr buf --> test rbuf.size=2 + # 2* rem wr buf --> test rbuf.size=4 + # breset --> test rbuf.size=4 + # 2* rem wr buf --> test rbuf.size=3 + # csr.fclr --> test rbuf.size=0 + $cpu cp \ + -wibr pca.rbuf 0xaa \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF {rsize 1}] \ + -wibr pca.rbuf 0x55 \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF {rsize 2}] \ + -wbibr pca.rbuf {0x11 0x22} \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF {rsize 4}] \ + -breset \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF {rsize 4}] \ + -wbibr pca.rbuf {0x33 0x44 0x55} \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF {rsize 7}] \ + -wibr pca.rcsr [regbld ibd_pc11::RRCSR fclr] \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF {rsize 0}] + # harvest breset/creset triggered attn's + rlc exec -attn + rlc wtlam 0. + + rlc log " A2.4: test fifo clear on csr.err=1 ---------------" + # 2* rem wr buf --> test rbuf.size=2 + # csr.err=1 --> test rbuf.size=0 + # rem wr buf --> test rbuf.size=0 + # csr.err=0 + $cpu cp \ + -wbibr pca.rbuf {0x66 0x77} \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF {rsize 2}] \ + -wibr pca.rcsr [regbld ibd_pc11::RRCSR err] \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF {rsize 0}] \ + -wibr pca.rbuf 0x88 \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF {rsize 0}] \ + -wibr pca.rcsr 0x0 + + rlc log " A3: test fifo logic -------------------------------------" + rlc log " A3.1: fill and overfill fifo ---------------------" + set rdata {} + for {set i 0} { $i < $fsize } {incr i} { lappend rdata [expr {$i+0100}] } + # rem wr fsize bytes --> test rbuf.size=fsize + # rem wr buf --> test error and rbuf.size=fsize + # csr.fclr to discard data + $cpu cp \ + -wbibr pca.rbuf $rdata \ + -ribr pca.rbuf -edata [regbldkv ibd_pc11::RRBUF rsize $fsize] \ + -wibr pca.rbuf 0xff -estaterr \ + -ribr pca.rbuf -edata [regbldkv ibd_pc11::RRBUF rsize $fsize] \ + -wibr pca.rcsr [regbld ibd_pc11::RRCSR fclr] + + rlc log " A3.2: fill and empty fifo, attn on last read -----" + # rem wr 2 bytes --> test rbuf.size=2 + # loc wr csr.ena --> test DONE=1 (1 cmd delay) + # loc rd buf --> test data; test rbuf.size=1; test no attn + $cpu cp \ + -wbibr pca.rbuf {0x55 0xaa} \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF {rsize 2}] \ + -wma pca.rcsr [regbld ibd_pc11::RCSR ena] \ + -rma pca.rcsr \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR done] \ + -rma pca.rbuf -edata 0x55 \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF {rsize 1}] + # test that no attn send + rlc exec -attn -edata 0x0 + # loc wr csr.ena --> test DONE=1 (1 cmd delay) + # loc rd buf --> test data; test rbuf.size=0; test attn seen + $cpu cp \ + -wma pca.rcsr [regbld ibd_pc11::RCSR ena] \ + -rma pca.rcsr \ + -rma pca.rcsr -edata [regbld ibd_pc11::RCSR done] \ + -rma pca.rbuf -edata 0xaa \ + -ribr pca.rbuf -edata [regbld ibd_pc11::RRBUF {rsize 0}] + # expect and harvest attn + rlc wtlam 1. + rlc exec -attn -edata $attnpc $attnpc +} + +# -- Section B --------------------------------------------------------------- +rlc log " B1: test csr.ie and basic interrupt response --------------" +# load test code +$cpu ldasm -lst lst -sym sym { + .include |lib/defs_cpu.mac| + .include |lib/defs_pc.mac| + . = va.ptr ; setup PC11 reader interrupt vector + .word vh.ptr + .word cp.pr7 +; + . = 1000 ; code area +stack: +; +; use in following mov to psw instead of spl to allow immediate interrupt +; +start: spl 7 ;;; lock-out interrupts + mov #vh.ptr,@#va.ptr ;;; setup ptr handler + mov #pr.ie,@#pr.csr ;;; enable ptr interrupts + bis #pr.ena,@#pr.csr ;;; reader enable (read next) +1$: tstb @#pr.csr ;;; wait for done set + bpl 1$ ;;; + mov #cp.pr6,@#cp.psw ;;; allow pri=7 + mov #cp.pr5,@#cp.psw ;;; allow pri=6 + mov #cp.pr4,@#cp.psw ;;; allow pri=5 + mov #cp.pr3,@#cp.psw ;;; allow pri=4 + mov #cp.pr2,@#cp.psw ;;; allow pri=3 + mov #cp.pr1,@#cp.psw ;;; allow pri=2 + mov #cp.pr0,@#cp.psw ;;; allow pri=1 + halt ;;; +; +vh.ptr: mov @#pr.buf,r5 ;;; ptr handler + halt ;;; +stop: +; +; continue to perform err interrupt test +; + mov #vh.err,@#va.ptr ;;; setup err handler + spl 0 ; allow interrupts +1$: wait ; wait for interrupts + br 1$ + +vh.err: halt ;;; err handler +stop1: +} + +rlc log " B1.1: done 0->1 interrupt --------------------------" +cpu0 cp -wibr pca.rcsr 0x0; # ensure err = 0 +rw11::asmrun $cpu sym +if {$type == 0} { # unbuffered: attn at ena time + rlc wtlam 1. + rlc exec -attn -edata $attnpc $attnpc +} +$cpu cp -wibr pca.rbuf 0111 +rw11::asmwait $cpu sym +rw11::asmtreg $cpu r5 0111 \ + sp [expr {$sym(stack)-4}] +rw11::asmtmem $cpu [expr {$sym(stack)-2}] [list [regbld rw11::PSW {pri 3}]] +#puts [rw11::cml $cpu] + +rlc log " B1.2: err interrupt --------------------------------" + +# continue code; set err=1 -> should interrupt again +cpu0 cp \ + -start \ + -wibr pca.rcsr [regbld ibd_pc11::RRCSR err] + +rw11::asmwait $cpu sym 0. stop1 +rw11::asmtreg $cpu sp [expr {$sym(stack)-8}] +#puts [rw11::cml $cpu] + +cpu0 cp -wibr pca.rcsr 0x0; # ensure err = 0 again + +rlc log " B2: test csr.ie and rri write -> cpu read -----------------" +# load test code +$cpu ldasm -lst lst -sym sym { + .include |lib/defs_cpu.mac| + .include |lib/defs_pc.mac| +; + .include |lib/vec_cpucatch.mac| + .include |lib/vec_devcatch.mac| +; + . = v..ptr ; setup PC11 reader interrupt vector + .word vh.ptr + .word cp.pr7 +; + . = 1000 ; data area +stack: +; +start: mov #buf,r5 ; set output buffer + mov #pp.ie,@#pr.csr ; enable interrupt + bis #pr.ena,@#pr.csr ; reader enable (read next) +1$: wait ; wait for interrupt + br 1$ ; forever +; +vh.ptr: movb @#pr.buf,(r5)+ ;;; store char + beq 1$ ;;; last one + bis #pr.ena,@#pr.csr ;;; reader enable (read next) + rti ;;; exit interrupt +; +1$: halt +stop: +buf: .blkb 256. +} + +# harvest any dangling attn +rlc exec -attn +rlc wtlam 0. + +set nchar 4 +if {$type == 0} { # unbuffered -------------------------- + rw11::asmrun $cpu sym + while {1} { + if {[rlc wtlam 1.] >= 1.} { break } + rlc exec -attn attnpat + if {$attnpat & $attncpu} { break }; # cpu attn + if {$attnpat & $attnpc} { # pc attn + incr nchar -1 + $cpu cp -wibr pca.rbuf $nchar; # send byte + } + } + rw11::asmtreg $cpu pc $sym(stop) + rw11::asmtmem $cpu [expr {$sym(buf)}] [list [expr {3 + (2<<8)}] \ + [expr {1 + (0<<8)}]] + +} else { # buffered ----------------------------- + rw11::asmrun $cpu sym + $cpu cp -wbibr pca.rbuf {7 6 5 4 3 2 1 0} + rw11::asmwait $cpu sym + rw11::asmtmem $cpu [expr {$sym(buf)}] [list [expr {7 + (6<<8)}] \ + [expr {5 + (4<<8)}] \ + [expr {3 + (2<<8)}] \ + [expr {1 + (0<<8)}]] +} diff --git a/tools/tcl/ibd_pc11/util.tcl b/tools/tcl/ibd_pc11/util.tcl index 18e73c7b..275c2d0a 100644 --- a/tools/tcl/ibd_pc11/util.tcl +++ b/tools/tcl/ibd_pc11/util.tcl @@ -1,4 +1,4 @@ -# $Id: util.tcl 1134 2019-04-21 17:18:03Z mueller $ +# $Id: util.tcl 1135 2019-04-23 12:56:23Z mueller $ # # Copyright 2015-2019 by Walter F.J. Mueller # @@ -13,7 +13,7 @@ # # Revision History: # Date Rev Version Comment -# 2019-04-21 1134 1.1 updates for buffered pc11 +# 2019-04-22 1135 1.1 updates for buffered pc11 # 2015-12-26 719 1.0 Initial version # @@ -30,11 +30,11 @@ namespace eval ibd_pc11 { regdsc RCSR {err 15} {busy 11} {done 7} {ie 6} {ena 0} regdsc RRCSR {err 15} {rlim 14 3} {busy 11} {type 10 3} \ - {done 7} {ie 6} {fclr 5} + {done 7} {ie 6} {ir 5} {rlb 4} {ique 3} {iack 2} {fclr 1} regdsc RRBUF {rbusy 15} {rsize 14 7 "d"} {psize 6 7 "d"} regdsc PCSR {err 15} {rdy 7} {ie 6} - regdsc RPCSR {err 15} {rlim 14 3} {rdy 7} {ie 6} + regdsc RPCSR {err 15} {rlim 14 3} {rdy 7} {ie 6} {ir 5} {rlb 4} regdsc RPBUF {val 15} {size 14 7 "d"} {data 7 8 "o"} diff --git a/tools/tcl/rw11/util.tcl b/tools/tcl/rw11/util.tcl index b0f52134..df8636c9 100644 --- a/tools/tcl/rw11/util.tcl +++ b/tools/tcl/rw11/util.tcl @@ -1,4 +1,4 @@ -# $Id: util.tcl 1131 2019-04-14 13:24:25Z mueller $ +# $Id: util.tcl 1134 2019-04-21 17:18:03Z mueller $ # # Copyright 2013-2019 by Walter F.J. Mueller # @@ -13,6 +13,7 @@ # # Revision History: # Date Rev Version Comment +# 2019-04-20 1134 1.3.11 setup_pp: add {pr,pp}rlim and prqlim options # 2019-04-14 1131 1.3.10 setup_lp: add rlim option # 2019-04-07 1128 1.3.9 setup_tt: rename dlrlim to dlrrlim # 2017-04-22 883 1.3.8 move in imap_reg2addr; add imap_range2addr @@ -120,12 +121,8 @@ namespace eval rw11 { set unit "${cntl}0" ${cpu}${unit} att "tcp:?port=${port}" ${cpu}${unit} set log "tirri_${unit}.log${urlopt}" - if {$opt(dlrrlim) != 0} { - ${cpu}${cntl} set rxrlim $opt(dlrrlim) - } - if {$opt(to7bit) != 0} { - ${cpu}${unit} set to7bit 1 - } + ${cpu}${cntl} set rxrlim $opt(dlrrlim) + ${cpu}${unit} set to7bit $opt(to7bit) } return } @@ -164,9 +161,7 @@ namespace eval rw11 { args2opts opt {nlp 1 rlim 0 app 0 nbck 1} {*}$args if {$opt(nlp) != 0} { setup_ostr $cpu "lpa0" app $opt(app) nbck $opt(nbck) - if {$opt(rlim) != 0} { - ${cpu}lpa set rlim $opt(rlim) - } + ${cpu}lpa set rlim $opt(rlim) } } # @@ -174,9 +169,12 @@ namespace eval rw11 { # proc setup_pp {{cpu "cpu0"} args} { # process and check options - args2opts opt {npc 1 app 0 nbck 1} {*}$args + args2opts opt {npc 1 pprlim 0 prrlim 0 prqlim 0 app 0 nbck 1} {*}$args if {$opt(npc) != 0} { setup_ostr $cpu "pp" app $opt(app) nbck $opt(nbck) + ${cpu}pca set pprlim $opt(pprlim) + ${cpu}pca set prrlim $opt(prrlim) + ${cpu}pca set prqlim $opt(prqlim) } }