Line 1... |
Line 1... |
-- $Id: pdp11_sequencer.vhd 679 2015-05-13 17:38:46Z mueller $
|
-- $Id: pdp11_sequencer.vhd 708 2015-08-03 06:41:43Z mueller $
|
--
|
--
|
-- Copyright 2006-2015 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
-- Copyright 2006-2015 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
--
|
--
|
-- This program is free software; you may redistribute and/or modify it under
|
-- 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
|
-- the terms of the GNU General Public License as published by the Free
|
Line 20... |
Line 20... |
-- Target Devices: generic
|
-- Target Devices: generic
|
-- Tool versions: ise 8.2-14.7; viv 2014.4; ghdl 0.18-0.31
|
-- Tool versions: ise 8.2-14.7; viv 2014.4; ghdl 0.18-0.31
|
--
|
--
|
-- Revision History:
|
-- Revision History:
|
-- Date Rev Version Comment
|
-- Date Rev Version Comment
|
|
-- 2015-08-02 708 1.6.5 BUGFIX: proper trap_mmu and trap_ysv handling
|
|
-- 2015-08-01 707 1.6.4 set dm_idone in s_(trap_10|op_trap); add dm_vfetch
|
|
-- 2015-07-19 702 1.6.3 add DM_STAT_SE, drop SNUM port
|
|
-- 2015-07-10 700 1.6.2 use c_cpurust_hbpt
|
|
-- 2015-06-26 695 1.6.1 add SNUM (state number) port
|
-- 2015-05-10 678 1.6 start/stop/suspend overhaul; reset overhaul
|
-- 2015-05-10 678 1.6 start/stop/suspend overhaul; reset overhaul
|
-- 2015-02-07 643 1.5.2 s_op_wait: load R0 in DSRC for DR emulation
|
-- 2015-02-07 643 1.5.2 s_op_wait: load R0 in DSRC for DR emulation
|
-- 2014-07-12 569 1.5.1 rename s_opg_div_zero -> s_opg_div_quit;
|
-- 2014-07-12 569 1.5.1 rename s_opg_div_zero -> s_opg_div_quit;
|
-- use DP_STAT.div_quit; set munit_s_div_sr;
|
-- use DP_STAT.div_quit; set munit_s_div_sr;
|
-- BUGFIX: s_opg_div_sr: check for late div_quit
|
-- BUGFIX: s_opg_div_sr: check for late div_quit
|
Line 95... |
Line 100... |
VM_CNTL : out vm_cntl_type; -- virtual memory control port
|
VM_CNTL : out vm_cntl_type; -- virtual memory control port
|
CP_STAT : out cp_stat_type; -- console port status
|
CP_STAT : out cp_stat_type; -- console port status
|
ESUSP_O : out slbit; -- external suspend output
|
ESUSP_O : out slbit; -- external suspend output
|
ESUSP_I : in slbit; -- external suspend input
|
ESUSP_I : in slbit; -- external suspend input
|
ITIMER : out slbit; -- instruction timer
|
ITIMER : out slbit; -- instruction timer
|
EBREAK : in slbit; -- execution break
|
HBPT : in slbit; -- hardware bpt
|
DBREAK : in slbit; -- data break
|
|
IB_MREQ : in ib_mreq_type; -- ibus request
|
IB_MREQ : in ib_mreq_type; -- ibus request
|
IB_SRES : out ib_sres_type -- ibus response
|
IB_SRES : out ib_sres_type; -- ibus response
|
|
DM_STAT_SE : out dm_stat_se_type -- debug and monitor status - sequencer
|
);
|
);
|
end pdp11_sequencer;
|
end pdp11_sequencer;
|
|
|
architecture syn of pdp11_sequencer is
|
architecture syn of pdp11_sequencer is
|
|
|
Line 315... |
Line 320... |
end process proc_state;
|
end process proc_state;
|
|
|
proc_next: process (R_STATE, R_STATUS, PSW, PC, CP_CNTL,
|
proc_next: process (R_STATE, R_STATUS, PSW, PC, CP_CNTL,
|
ID_STAT, R_IDSTAT, IREG, VM_STAT, DP_STAT,
|
ID_STAT, R_IDSTAT, IREG, VM_STAT, DP_STAT,
|
R_CPUERR, R_VMSTAT, IB_MREQ, IBSEL_CPUERR,
|
R_CPUERR, R_VMSTAT, IB_MREQ, IBSEL_CPUERR,
|
INT_PRI, INT_VECT, ESUSP_I, EBREAK, DBREAK)
|
INT_PRI, INT_VECT, ESUSP_I, HBPT)
|
|
|
variable nstate : state_type;
|
variable nstate : state_type;
|
variable nstatus : cpustat_type := cpustat_init;
|
variable nstatus : cpustat_type := cpustat_init;
|
variable ncpuerr : cpuerr_type := cpuerr_init;
|
variable ncpuerr : cpuerr_type := cpuerr_init;
|
|
|
Line 340... |
Line 345... |
variable is_kmode : slbit := '0'; -- cmode is kernel mode
|
variable is_kmode : slbit := '0'; -- cmode is kernel mode
|
variable is_dstkstack1246 : slbit := '0'; -- dest is k-stack & mode= 1,2,4,6
|
variable is_dstkstack1246 : slbit := '0'; -- dest is k-stack & mode= 1,2,4,6
|
|
|
variable int_pending : slbit := '0'; -- an interrupt is pending
|
variable int_pending : slbit := '0'; -- an interrupt is pending
|
|
|
|
variable idm_idone : slbit := '0'; -- idone for dm_stat_se
|
|
variable idm_vfetch : slbit := '0'; -- vfetch for dm_stat_se
|
|
|
alias SRCMOD : slv2 is IREG(11 downto 10); -- src register mode high
|
alias SRCMOD : slv2 is IREG(11 downto 10); -- src register mode high
|
alias SRCDEF : slbit is IREG(9); -- src register mode defered
|
alias SRCDEF : slbit is IREG(9); -- src register mode defered
|
alias SRCREG : slv3 is IREG(8 downto 6); -- src register number
|
alias SRCREG : slv3 is IREG(8 downto 6); -- src register number
|
alias DSTMODF : slv3 is IREG(5 downto 3); -- dst register full mode
|
alias DSTMODF : slv3 is IREG(5 downto 3); -- dst register full mode
|
alias DSTMOD : slv2 is IREG(5 downto 4); -- dst register mode high
|
alias DSTMOD : slv2 is IREG(5 downto 4); -- dst register mode high
|
Line 422... |
Line 430... |
nstate := nstate; -- dummy to add driver (vivado)
|
nstate := nstate; -- dummy to add driver (vivado)
|
nstatus := nstatus; -- "
|
nstatus := nstatus; -- "
|
mok := false;
|
mok := false;
|
if VM_STAT.ack = '1' then
|
if VM_STAT.ack = '1' then
|
mok := true;
|
mok := true;
|
nstatus.trap_mmu := VM_STAT.trap_mmu;
|
if VM_STAT.trap_mmu = '1' then -- remember trap_mmu, may happen on any
|
|
nstatus.trap_mmu := '1'; -- memory access of an instruction
|
|
end if;
|
|
if VM_STAT.trap_ysv = '1' then -- remember trap_ysv (on any access)
|
if R_CPUERR.ysv = '0' then -- ysv trap when cpuerr not yet set
|
if R_CPUERR.ysv = '0' then -- ysv trap when cpuerr not yet set
|
nstatus.trap_ysv := VM_STAT.trap_ysv;
|
nstatus.trap_ysv := '1';
|
|
end if;
|
end if;
|
end if;
|
elsif VM_STAT.err='1' or VM_STAT.fail='1' then
|
elsif VM_STAT.err='1' or VM_STAT.fail='1' then
|
nstate := s_vmerr;
|
nstate := s_vmerr;
|
end if;
|
end if;
|
end procedure do_memcheck;
|
end procedure do_memcheck;
|
Line 582... |
Line 594... |
int_pending := '0';
|
int_pending := '0';
|
if unsigned(INT_PRI) > unsigned(PSW.pri) then
|
if unsigned(INT_PRI) > unsigned(PSW.pri) then
|
int_pending := '1';
|
int_pending := '1';
|
end if;
|
end if;
|
|
|
|
idm_idone := '0';
|
|
idm_vfetch := '0';
|
|
|
imemok := false;
|
imemok := false;
|
|
|
nmmumoni := mmu_moni_init;
|
nmmumoni := mmu_moni_init;
|
nmmumoni.pc := PC;
|
nmmumoni.pc := PC;
|
|
|
Line 1295... |
Line 1310... |
|
|
when s_dstw_def_w =>
|
when s_dstw_def_w =>
|
nstate := s_dstw_def_w;
|
nstate := s_dstw_def_w;
|
do_memcheck(nstate, nstatus, imemok);
|
do_memcheck(nstate, nstatus, imemok);
|
if imemok then
|
if imemok then
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
end if;
|
end if;
|
|
|
when s_dstw_inc =>
|
when s_dstw_inc =>
|
ndpcntl.psr_ccwe := '1';
|
ndpcntl.psr_ccwe := '1';
|
ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst; -- VA = DDST
|
ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst; -- VA = DDST
|
Line 1335... |
Line 1351... |
ndpcntl.gpr_we := '1'; -- update DST reg
|
ndpcntl.gpr_we := '1'; -- update DST reg
|
end if;
|
end if;
|
nstatus.do_gprwe := '0';
|
nstatus.do_gprwe := '0';
|
do_memcheck(nstate, nstatus, imemok);
|
do_memcheck(nstate, nstatus, imemok);
|
if imemok then
|
if imemok then
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
end if;
|
end if;
|
|
|
when s_dstw_incdef_w =>
|
when s_dstw_incdef_w =>
|
nstate := s_dstw_incdef_w;
|
nstate := s_dstw_incdef_w;
|
ndpcntl.dres_sel := c_dpath_res_vmdout; -- DRES = VMDOUT
|
ndpcntl.dres_sel := c_dpath_res_vmdout; -- DRES = VMDOUT
|
Line 1508... |
Line 1525... |
end if;
|
end if;
|
|
|
-- instruction operate states -----------------------------------------------
|
-- instruction operate states -----------------------------------------------
|
|
|
when s_op_halt => -- HALT
|
when s_op_halt => -- HALT
|
|
idm_idone := '1'; -- instruction done
|
if is_kmode = '1' then -- if in kernel mode execute
|
if is_kmode = '1' then -- if in kernel mode execute
|
nmmumoni.idone := '1';
|
nmmumoni.idone := '1';
|
nstatus.cpugo := '0';
|
nstatus.cpugo := '0';
|
nstatus.cpurust := c_cpurust_halt;
|
nstatus.cpurust := c_cpurust_halt;
|
nstate := s_idle;
|
nstate := s_idle;
|
Line 1538... |
Line 1556... |
nstatus.cpuwait := '1'; -- if spinning here, signal with cpuwait
|
nstatus.cpuwait := '1'; -- if spinning here, signal with cpuwait
|
nstatus.itimer := '1'; -- itimer will stay 1 during a WAIT
|
nstatus.itimer := '1'; -- itimer will stay 1 during a WAIT
|
end if;
|
end if;
|
|
|
when s_op_trap => -- traps
|
when s_op_trap => -- traps
|
|
idm_idone := '1'; -- instruction done
|
lvector := "0000" & R_IDSTAT.trap_vec; -- vector
|
lvector := "0000" & R_IDSTAT.trap_vec; -- vector
|
do_start_int(nstate, ndpcntl, lvector);
|
do_start_int(nstate, ndpcntl, lvector);
|
|
|
when s_op_reset => -- RESET
|
when s_op_reset => -- RESET
|
if is_kmode = '1' then -- if in kernel mode execute
|
if is_kmode = '1' then -- if in kernel mode execute
|
Line 1566... |
Line 1585... |
ndpcntl.dres_sel := c_dpath_res_vmdout; -- DRES = VMDOUT
|
ndpcntl.dres_sel := c_dpath_res_vmdout; -- DRES = VMDOUT
|
ndpcntl.gpr_adst := DSTREG;
|
ndpcntl.gpr_adst := DSTREG;
|
do_memcheck(nstate, nstatus, imemok);
|
do_memcheck(nstate, nstatus, imemok);
|
if imemok then
|
if imemok then
|
ndpcntl.gpr_we := '1'; -- load R with (SP)+
|
ndpcntl.gpr_we := '1'; -- load R with (SP)+
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
end if;
|
end if;
|
|
|
when s_op_spl => -- SPL
|
when s_op_spl => -- SPL
|
ndpcntl.dres_sel := c_dpath_res_ireg; -- DRES = IREG
|
ndpcntl.dres_sel := c_dpath_res_ireg; -- DRES = IREG
|
ndpcntl.psr_func := c_psr_func_wspl;
|
ndpcntl.psr_func := c_psr_func_wspl;
|
|
idm_idone := '1'; -- instruction done
|
if is_kmode = '1' then -- active only in kernel mode
|
if is_kmode = '1' then -- active only in kernel mode
|
ndpcntl.psr_we := '1';
|
ndpcntl.psr_we := '1';
|
nstate := s_ifetch; -- unconditionally fetch next
|
nstate := s_ifetch; -- unconditionally fetch next
|
-- instruction like a 11/70
|
-- instruction like a 11/70
|
-- no interrupt recognition !
|
-- no interrupt recognition !
|
Line 1585... |
Line 1606... |
|
|
when s_op_mcc => -- CLx/SEx
|
when s_op_mcc => -- CLx/SEx
|
ndpcntl.dres_sel := c_dpath_res_ireg; -- DRES = IREG
|
ndpcntl.dres_sel := c_dpath_res_ireg; -- DRES = IREG
|
ndpcntl.psr_func := c_psr_func_wcc;
|
ndpcntl.psr_func := c_psr_func_wcc;
|
ndpcntl.psr_we := '1';
|
ndpcntl.psr_we := '1';
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
|
|
when s_op_br => -- BR
|
when s_op_br => -- BR
|
nvmcntl.dspace := '0'; -- prepare do_fork_next_pref
|
nvmcntl.dspace := '0'; -- prepare do_fork_next_pref
|
ndpcntl.vmaddr_sel := c_dpath_vmaddr_pc; -- VA = PC
|
ndpcntl.vmaddr_sel := c_dpath_vmaddr_pc; -- VA = PC
|
ndpcntl.ounit_asel := c_ounit_asel_pc; -- OUNIT A = PC
|
ndpcntl.ounit_asel := c_ounit_asel_pc; -- OUNIT A = PC
|
Line 1615... |
Line 1637... |
brcond := PSW.cc(0);
|
brcond := PSW.cc(0);
|
when others => null;
|
when others => null;
|
end case;
|
end case;
|
|
|
ndpcntl.gpr_adst := c_gpr_pc;
|
ndpcntl.gpr_adst := c_gpr_pc;
|
|
idm_idone := '1'; -- instruction done
|
if brcond = brcode(0) then -- this coding creates redundant code
|
if brcond = brcode(0) then -- this coding creates redundant code
|
ndpcntl.gpr_we := '1'; -- but synthesis optimizes this way !
|
ndpcntl.gpr_we := '1'; -- but synthesis optimizes this way !
|
do_fork_next(nstate, nstatus, nmmumoni);
|
do_fork_next(nstate, nstatus, nmmumoni);
|
else
|
else
|
do_fork_next_pref(nstate, nstatus, ndpcntl, nvmcntl, nmmumoni);
|
do_fork_next_pref(nstate, nstatus, ndpcntl, nvmcntl, nmmumoni);
|
Line 1652... |
Line 1675... |
ndpcntl.dres_sel := c_dpath_res_vmdout; -- DRES = VMDOUT
|
ndpcntl.dres_sel := c_dpath_res_vmdout; -- DRES = VMDOUT
|
ndpcntl.gpr_adst := c_gpr_r5;
|
ndpcntl.gpr_adst := c_gpr_r5;
|
do_memcheck(nstate, nstatus, imemok);
|
do_memcheck(nstate, nstatus, imemok);
|
if imemok then
|
if imemok then
|
ndpcntl.gpr_we := '1'; -- load R5 with (sp)+
|
ndpcntl.gpr_we := '1'; -- load R5 with (sp)+
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
end if;
|
end if;
|
|
|
when s_op_sob => -- SOB (dec)
|
when s_op_sob => -- SOB (dec)
|
-- comment fork_next_pref out (blog 2006-10-02) due to synthesis impact
|
-- comment fork_next_pref out (blog 2006-10-02) due to synthesis impact
|
--nvmcntl.dspace := '0'; -- prepare do_fork_next_pref
|
--nvmcntl.dspace := '0'; -- prepare do_fork_next_pref
|
Line 1667... |
Line 1691... |
|
|
if DP_STAT.ccout_z = '0' then -- if z=0 branch, if z=1 fall thru
|
if DP_STAT.ccout_z = '0' then -- if z=0 branch, if z=1 fall thru
|
nstate := s_op_sob1;
|
nstate := s_op_sob1;
|
else
|
else
|
--do_fork_next_pref(nstate, ndpcntl, nvmcntl, nmmumoni);
|
--do_fork_next_pref(nstate, ndpcntl, nvmcntl, nmmumoni);
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
end if;
|
end if;
|
|
|
when s_op_sob1 => -- SOB (br)
|
when s_op_sob1 => -- SOB (br)
|
ndpcntl.ounit_asel := c_ounit_asel_pc; -- OUNIT A = PC
|
ndpcntl.ounit_asel := c_ounit_asel_pc; -- OUNIT A = PC
|
ndpcntl.ounit_bsel := c_ounit_bsel_ireg6;-- OUNIT B = IREG6
|
ndpcntl.ounit_bsel := c_ounit_bsel_ireg6;-- OUNIT B = IREG6
|
ndpcntl.ounit_opsub := '1'; -- OUNIT = A - B
|
ndpcntl.ounit_opsub := '1'; -- OUNIT = A - B
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.gpr_adst := c_gpr_pc;
|
ndpcntl.gpr_adst := c_gpr_pc;
|
ndpcntl.gpr_we := '1';
|
ndpcntl.gpr_we := '1';
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
|
|
when s_opg_gen =>
|
when s_opg_gen =>
|
nvmcntl.dspace := '0'; -- prepare do_fork_next_pref
|
nvmcntl.dspace := '0'; -- prepare do_fork_next_pref
|
ndpcntl.vmaddr_sel := c_dpath_vmaddr_pc; -- VA = PC
|
ndpcntl.vmaddr_sel := c_dpath_vmaddr_pc; -- VA = PC
|
ndpcntl.gpr_bytop := R_IDSTAT.is_bytop;
|
ndpcntl.gpr_bytop := R_IDSTAT.is_bytop;
|
Line 1698... |
Line 1724... |
end if;
|
end if;
|
|
|
if R_IDSTAT.is_rmwop = '1' then
|
if R_IDSTAT.is_rmwop = '1' then
|
do_memwrite(nstate, nvmcntl, s_opg_gen_rmw_w, macc=>'1');
|
do_memwrite(nstate, nvmcntl, s_opg_gen_rmw_w, macc=>'1');
|
else
|
else
|
|
idm_idone := '1'; -- instruction done
|
if R_STATUS.prefdone = '1' then
|
if R_STATUS.prefdone = '1' then
|
nstatus.prefdone :='0';
|
nstatus.prefdone :='0';
|
nstate := s_ifetch_w;
|
nstate := s_ifetch_w;
|
do_memcheck(nstate, nstatus, imemok);
|
do_memcheck(nstate, nstatus, imemok);
|
if imemok then
|
if imemok then
|
Line 1719... |
Line 1746... |
|
|
when s_opg_gen_rmw_w =>
|
when s_opg_gen_rmw_w =>
|
nstate := s_opg_gen_rmw_w;
|
nstate := s_opg_gen_rmw_w;
|
do_memcheck(nstate, nstatus, imemok);
|
do_memcheck(nstate, nstatus, imemok);
|
if imemok then
|
if imemok then
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
end if;
|
end if;
|
|
|
when s_opg_mul => -- MUL (oper)
|
when s_opg_mul => -- MUL (oper)
|
ndpcntl.dres_sel := R_IDSTAT.res_sel; -- DRES = choice of idec
|
ndpcntl.dres_sel := R_IDSTAT.res_sel; -- DRES = choice of idec
|
ndpcntl.gpr_adst := SRCREG; -- write high order result
|
ndpcntl.gpr_adst := SRCREG; -- write high order result
|
Line 1739... |
Line 1767... |
ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B = const(0)
|
ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B = const(0)
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.gpr_adst := SRCREG(2 downto 1) & "1";-- write odd reg !
|
ndpcntl.gpr_adst := SRCREG(2 downto 1) & "1";-- write odd reg !
|
ndpcntl.gpr_we := '1';
|
ndpcntl.gpr_we := '1';
|
ndpcntl.psr_ccwe := '1';
|
ndpcntl.psr_ccwe := '1';
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
|
|
when s_opg_div => -- DIV (load dd_low)
|
when s_opg_div => -- DIV (load dd_low)
|
ndpcntl.munit_s_div := '1';
|
ndpcntl.munit_s_div := '1';
|
ndpcntl.gpr_asrc := SRCREG(2 downto 1) & "1";-- read odd reg !
|
ndpcntl.gpr_asrc := SRCREG(2 downto 1) & "1";-- read odd reg !
|
ndpcntl.dtmp_sel := c_dpath_dtmp_dsrc;
|
ndpcntl.dtmp_sel := c_dpath_dtmp_dsrc;
|
Line 1793... |
Line 1822... |
ndpcntl.gpr_we := '1';
|
ndpcntl.gpr_we := '1';
|
ndpcntl.psr_ccwe := '1';
|
ndpcntl.psr_ccwe := '1';
|
if DP_STAT.div_quit = '1' then
|
if DP_STAT.div_quit = '1' then
|
nstate := s_opg_div_quit;
|
nstate := s_opg_div_quit;
|
else
|
else
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
end if;
|
end if;
|
|
|
when s_opg_div_quit => -- DIV (0/ or /0 or V=1 aborts)
|
when s_opg_div_quit => -- DIV (0/ or /0 or V=1 aborts)
|
ndpcntl.psr_ccwe := '1';
|
ndpcntl.psr_ccwe := '1';
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
|
|
when s_opg_ash => -- ASH (load shc)
|
when s_opg_ash => -- ASH (load shc)
|
ndpcntl.munit_s_ash := '1';
|
ndpcntl.munit_s_ash := '1';
|
nstate := s_opg_ash_cn;
|
nstate := s_opg_ash_cn;
|
|
|
Line 1820... |
Line 1851... |
ndpcntl.dsrc_we := '1'; -- update DSRC
|
ndpcntl.dsrc_we := '1'; -- update DSRC
|
else
|
else
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.gpr_we := '1';
|
ndpcntl.gpr_we := '1';
|
ndpcntl.psr_ccwe := '1';
|
ndpcntl.psr_ccwe := '1';
|
|
idm_idone := '1'; -- instruction done
|
do_fork_next_pref(nstate, nstatus, ndpcntl, nvmcntl, nmmumoni);
|
do_fork_next_pref(nstate, nstatus, ndpcntl, nvmcntl, nmmumoni);
|
end if;
|
end if;
|
|
|
when s_opg_ashc => -- ASHC (load low, load shc)
|
when s_opg_ashc => -- ASHC (load low, load shc)
|
ndpcntl.gpr_asrc := SRCREG(2 downto 1) & "1";-- read odd reg !
|
ndpcntl.gpr_asrc := SRCREG(2 downto 1) & "1";-- read odd reg !
|
Line 1855... |
Line 1887... |
ndpcntl.ounit_asel := c_ounit_asel_dtmp; -- OUNIT A = DTMP
|
ndpcntl.ounit_asel := c_ounit_asel_dtmp; -- OUNIT A = DTMP
|
ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B = const(0)
|
ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B = const(0)
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.gpr_adst := SRCREG(2 downto 1) & "1";-- write odd reg !
|
ndpcntl.gpr_adst := SRCREG(2 downto 1) & "1";-- write odd reg !
|
ndpcntl.gpr_we := '1';
|
ndpcntl.gpr_we := '1';
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
|
|
-- dsta mode operations -----------------------------------------------------
|
-- dsta mode operations -----------------------------------------------------
|
|
|
when s_opa_jsr =>
|
when s_opa_jsr =>
|
ndpcntl.gpr_asrc := c_gpr_sp; -- (for else)
|
ndpcntl.gpr_asrc := c_gpr_sp; -- (for else)
|
Line 1916... |
Line 1949... |
ndpcntl.ounit_asel := c_ounit_asel_ddst; -- OUNIT A=DDST
|
ndpcntl.ounit_asel := c_ounit_asel_ddst; -- OUNIT A=DDST
|
ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B=const(0)
|
ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B=const(0)
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.gpr_adst := c_gpr_pc;
|
ndpcntl.gpr_adst := c_gpr_pc;
|
ndpcntl.gpr_we := '1'; -- load PC with dsta
|
ndpcntl.gpr_we := '1'; -- load PC with dsta
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
|
|
when s_opa_jmp =>
|
when s_opa_jmp =>
|
ndpcntl.ounit_asel := c_ounit_asel_ddst; -- OUNIT A=DDST
|
ndpcntl.ounit_asel := c_ounit_asel_ddst; -- OUNIT A=DDST
|
ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B=const(0)
|
ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B=const(0)
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.gpr_adst := c_gpr_pc;
|
ndpcntl.gpr_adst := c_gpr_pc;
|
if R_IDSTAT.is_dstmode0 = '1' then
|
if R_IDSTAT.is_dstmode0 = '1' then
|
nstate := s_trap_10; -- trap 10 like 11/70
|
nstate := s_trap_10; -- trap 10 like 11/70
|
else
|
else
|
ndpcntl.gpr_we := '1'; -- load PC with dsta
|
ndpcntl.gpr_we := '1'; -- load PC with dsta
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
end if;
|
end if;
|
|
|
when s_opa_mtp =>
|
when s_opa_mtp =>
|
do_memread_srcinc(nstate, ndpcntl, nvmcntl, s_opa_mtp_pop_w,
|
do_memread_srcinc(nstate, ndpcntl, nvmcntl, s_opa_mtp_pop_w,
|
nmmumoni, updt_sp=>'1');
|
nmmumoni, updt_sp=>'1');
|
Line 1963... |
Line 1998... |
ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B = const(0)
|
ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B = const(0)
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.psr_ccwe := '1'; -- set cc (from ounit too)
|
ndpcntl.psr_ccwe := '1'; -- set cc (from ounit too)
|
ndpcntl.gpr_mode := PSW.pmode; -- load reg in pmode
|
ndpcntl.gpr_mode := PSW.pmode; -- load reg in pmode
|
ndpcntl.gpr_we := '1';
|
ndpcntl.gpr_we := '1';
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
|
|
when s_opa_mtp_mem =>
|
when s_opa_mtp_mem =>
|
ndpcntl.ounit_asel := c_ounit_asel_dtmp; -- OUNIT A = DTMP
|
ndpcntl.ounit_asel := c_ounit_asel_dtmp; -- OUNIT A = DTMP
|
ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B = const(0)
|
ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B = const(0)
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
Line 1981... |
Line 2017... |
|
|
when s_opa_mtp_mem_w =>
|
when s_opa_mtp_mem_w =>
|
nstate := s_opa_mtp_mem_w;
|
nstate := s_opa_mtp_mem_w;
|
do_memcheck(nstate, nstatus, imemok);
|
do_memcheck(nstate, nstatus, imemok);
|
if imemok then
|
if imemok then
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
end if;
|
end if;
|
|
|
when s_opa_mfp_reg =>
|
when s_opa_mfp_reg =>
|
ndpcntl.gpr_mode := PSW.pmode; -- fetch reg in pmode
|
ndpcntl.gpr_mode := PSW.pmode; -- fetch reg in pmode
|
ndpcntl.ddst_sel := c_dpath_ddst_dst; -- DDST = reg(dst)
|
ndpcntl.ddst_sel := c_dpath_ddst_dst; -- DDST = reg(dst)
|
Line 2042... |
Line 2079... |
|
|
when s_opa_mfp_push_w =>
|
when s_opa_mfp_push_w =>
|
nstate := s_opa_mfp_push_w;
|
nstate := s_opa_mfp_push_w;
|
do_memcheck(nstate, nstatus, imemok);
|
do_memcheck(nstate, nstatus, imemok);
|
if imemok then
|
if imemok then
|
do_fork_next(nstate, nstatus, nmmumoni);
|
idm_idone := '1'; -- instruction done
|
|
do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
|
end if;
|
end if;
|
|
|
-- trap and interrupt handling states ---------------------------------------
|
-- trap and interrupt handling states ---------------------------------------
|
|
|
when s_trap_4 =>
|
when s_trap_4 =>
|
lvector := "0000001"; -- vector (4)
|
lvector := "0000001"; -- vector (4)
|
do_start_int(nstate, ndpcntl, lvector);
|
do_start_int(nstate, ndpcntl, lvector);
|
|
|
when s_trap_10 =>
|
when s_trap_10 =>
|
|
idm_idone := '1'; -- instruction done
|
lvector := "0000010"; -- vector (10)
|
lvector := "0000010"; -- vector (10)
|
do_start_int(nstate, ndpcntl, lvector);
|
do_start_int(nstate, ndpcntl, lvector);
|
|
|
when s_trap_disp =>
|
when s_trap_disp =>
|
if R_STATUS.trap_mmu = '1' then
|
if R_STATUS.trap_mmu = '1' then
|
Line 2074... |
Line 2113... |
when s_int_ext =>
|
when s_int_ext =>
|
lvector := R_STATUS.intvect; -- external vector
|
lvector := R_STATUS.intvect; -- external vector
|
do_start_int(nstate, ndpcntl, lvector);
|
do_start_int(nstate, ndpcntl, lvector);
|
|
|
when s_int_getpc =>
|
when s_int_getpc =>
|
|
idm_vfetch := '1'; -- signal vfetch
|
nvmcntl.mode := c_psw_kmode; -- fetch PC from kernel D space
|
nvmcntl.mode := c_psw_kmode; -- fetch PC from kernel D space
|
do_memread_srcinc(nstate, ndpcntl, nvmcntl, s_int_getpc_w, nmmumoni);
|
do_memread_srcinc(nstate, ndpcntl, nvmcntl, s_int_getpc_w, nmmumoni);
|
|
|
when s_int_getpc_w =>
|
when s_int_getpc_w =>
|
nstate := s_int_getpc_w;
|
nstate := s_int_getpc_w;
|
Line 2221... |
Line 2261... |
ndpcntl.ounit_asel := c_ounit_asel_ddst; -- OUNIT A=DDST
|
ndpcntl.ounit_asel := c_ounit_asel_ddst; -- OUNIT A=DDST
|
ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B=const (0)
|
ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B=const (0)
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.dres_sel := c_dpath_res_ounit; -- DRES = OUNIT
|
ndpcntl.gpr_adst := c_gpr_pc;
|
ndpcntl.gpr_adst := c_gpr_pc;
|
ndpcntl.gpr_we := '1'; -- load new PC
|
ndpcntl.gpr_we := '1'; -- load new PC
|
|
idm_idone := '1'; -- instruction done
|
if R_IDSTAT.op_rtt = '1' then -- if RTT instruction
|
if R_IDSTAT.op_rtt = '1' then -- if RTT instruction
|
nstate := s_ifetch; -- force fetch
|
nstate := s_ifetch; -- force fetch
|
else -- otherwise RTI
|
else -- otherwise RTI
|
do_fork_next(nstate, nstatus, nmmumoni);
|
do_fork_next(nstate, nstatus, nmmumoni);
|
end if;
|
end if;
|
Line 2293... |
Line 2334... |
when others =>
|
when others =>
|
nstate := s_cpufail; --!!! catch undefined states !!!
|
nstate := s_cpufail; --!!! catch undefined states !!!
|
|
|
end case;
|
end case;
|
|
|
if DBREAK = '1' then -- handle BREAK
|
if HBPT = '1' then -- handle hardware bpt
|
|
nstatus.cpurust := c_cpurust_hbpt;
|
nstatus.suspint :='1';
|
nstatus.suspint :='1';
|
end if;
|
end if;
|
nstatus.suspext := ESUSP_I;
|
nstatus.suspext := ESUSP_I;
|
|
|
-- handle cpususp transitions
|
-- handle cpususp transitions
|
Line 2329... |
Line 2371... |
|
|
nmmumoni.regnum := ndpcntl.gpr_adst;
|
nmmumoni.regnum := ndpcntl.gpr_adst;
|
nmmumoni.delta := ndpcntl.ounit_const(3 downto 0);
|
nmmumoni.delta := ndpcntl.ounit_const(3 downto 0);
|
MMU_MONI <= nmmumoni;
|
MMU_MONI <= nmmumoni;
|
|
|
|
DM_STAT_SE.istart <= nmmumoni.istart;
|
|
DM_STAT_SE.idone <= idm_idone;
|
|
DM_STAT_SE.vfetch <= idm_vfetch;
|
|
|
end process proc_next;
|
end process proc_next;
|
|
|
proc_cpstat : process (R_STATUS)
|
proc_cpstat : process (R_STATUS)
|
begin
|
begin
|
CP_STAT <= cp_stat_init;
|
CP_STAT <= cp_stat_init;
|
Line 2347... |
Line 2393... |
CP_STAT.cpurust <= R_STATUS.cpurust;
|
CP_STAT.cpurust <= R_STATUS.cpurust;
|
CP_STAT.suspint <= R_STATUS.suspint;
|
CP_STAT.suspint <= R_STATUS.suspint;
|
CP_STAT.suspext <= R_STATUS.suspext;
|
CP_STAT.suspext <= R_STATUS.suspext;
|
end process proc_cpstat;
|
end process proc_cpstat;
|
|
|
|
proc_snum : process (R_STATE)
|
|
variable isnum : slv8 := (others=>'0');
|
|
begin
|
|
isnum := (others=>'0');
|
|
case R_STATE is
|
|
-- STATE2SNUM mapper begin
|
|
when s_idle => isnum := x"00";
|
|
when s_cp_regread => isnum := x"01";
|
|
when s_cp_rps => isnum := x"02";
|
|
when s_cp_memr_w => isnum := x"03";
|
|
when s_cp_memw_w => isnum := x"04";
|
|
when s_ifetch => isnum := x"05";
|
|
when s_ifetch_w => isnum := x"06";
|
|
when s_idecode => isnum := x"07";
|
|
|
|
when s_srcr_def => isnum := x"08";
|
|
when s_srcr_def_w => isnum := x"09";
|
|
when s_srcr_inc => isnum := x"0a";
|
|
when s_srcr_inc_w => isnum := x"0b";
|
|
when s_srcr_dec => isnum := x"0c";
|
|
when s_srcr_dec1 => isnum := x"0d";
|
|
when s_srcr_ind => isnum := x"0e";
|
|
when s_srcr_ind1_w => isnum := x"0f";
|
|
when s_srcr_ind2 => isnum := x"10";
|
|
when s_srcr_ind2_w => isnum := x"11";
|
|
|
|
when s_dstr_def => isnum := x"12";
|
|
when s_dstr_def_w => isnum := x"13";
|
|
when s_dstr_inc => isnum := x"14";
|
|
when s_dstr_inc_w => isnum := x"15";
|
|
when s_dstr_dec => isnum := x"16";
|
|
when s_dstr_dec1 => isnum := x"17";
|
|
when s_dstr_ind => isnum := x"18";
|
|
when s_dstr_ind1_w => isnum := x"19";
|
|
when s_dstr_ind2 => isnum := x"1a";
|
|
when s_dstr_ind2_w => isnum := x"1b";
|
|
|
|
when s_dstw_def => isnum := x"1c";
|
|
when s_dstw_def_w => isnum := x"1d";
|
|
when s_dstw_inc => isnum := x"1e";
|
|
when s_dstw_inc_w => isnum := x"1f";
|
|
when s_dstw_incdef_w => isnum := x"20";
|
|
when s_dstw_dec => isnum := x"21";
|
|
when s_dstw_dec1 => isnum := x"22";
|
|
when s_dstw_ind => isnum := x"23";
|
|
when s_dstw_ind_w => isnum := x"24";
|
|
when s_dstw_def246 => isnum := x"25";
|
|
|
|
when s_dsta_inc => isnum := x"26";
|
|
when s_dsta_incdef_w => isnum := x"27";
|
|
when s_dsta_dec => isnum := x"28";
|
|
when s_dsta_dec1 => isnum := x"29";
|
|
when s_dsta_ind => isnum := x"2a";
|
|
when s_dsta_ind_w => isnum := x"2b";
|
|
|
|
when s_op_halt => isnum := x"2c";
|
|
when s_op_wait => isnum := x"2d";
|
|
when s_op_trap => isnum := x"2e";
|
|
when s_op_reset => isnum := x"2f";
|
|
when s_op_rts => isnum := x"30";
|
|
when s_op_rts_pop => isnum := x"31";
|
|
when s_op_rts_pop_w => isnum := x"32";
|
|
when s_op_spl => isnum := x"33";
|
|
when s_op_mcc => isnum := x"34";
|
|
when s_op_br => isnum := x"35";
|
|
when s_op_mark => isnum := x"36";
|
|
when s_op_mark1 => isnum := x"37";
|
|
when s_op_mark_pop => isnum := x"38";
|
|
when s_op_mark_pop_w => isnum := x"39";
|
|
when s_op_sob => isnum := x"3a";
|
|
when s_op_sob1 => isnum := x"3b";
|
|
|
|
when s_opg_gen => isnum := x"3c";
|
|
when s_opg_gen_rmw_w => isnum := x"3d";
|
|
when s_opg_mul => isnum := x"3e";
|
|
when s_opg_mul1 => isnum := x"3f";
|
|
when s_opg_div => isnum := x"40";
|
|
when s_opg_div_cn => isnum := x"41";
|
|
when s_opg_div_cr => isnum := x"42";
|
|
when s_opg_div_sq => isnum := x"43";
|
|
when s_opg_div_sr => isnum := x"44";
|
|
when s_opg_div_quit => isnum := x"45";
|
|
when s_opg_ash => isnum := x"46";
|
|
when s_opg_ash_cn => isnum := x"47";
|
|
when s_opg_ashc => isnum := x"48";
|
|
when s_opg_ashc_cn => isnum := x"49";
|
|
when s_opg_ashc_wl => isnum := x"4a";
|
|
|
|
when s_opa_jsr => isnum := x"4b";
|
|
when s_opa_jsr1 => isnum := x"4c";
|
|
when s_opa_jsr_push => isnum := x"4d";
|
|
when s_opa_jsr_push_w => isnum := x"4e";
|
|
when s_opa_jsr2 => isnum := x"4f";
|
|
when s_opa_jmp => isnum := x"50";
|
|
when s_opa_mtp => isnum := x"51";
|
|
when s_opa_mtp_pop_w => isnum := x"52";
|
|
when s_opa_mtp_reg => isnum := x"53";
|
|
when s_opa_mtp_mem => isnum := x"54";
|
|
when s_opa_mtp_mem_w => isnum := x"55";
|
|
when s_opa_mfp_reg => isnum := x"56";
|
|
when s_opa_mfp_mem => isnum := x"57";
|
|
when s_opa_mfp_mem_w => isnum := x"58";
|
|
when s_opa_mfp_dec => isnum := x"59";
|
|
when s_opa_mfp_push => isnum := x"5a";
|
|
when s_opa_mfp_push_w => isnum := x"5b";
|
|
|
|
when s_trap_4 => isnum := x"5c";
|
|
when s_trap_10 => isnum := x"5d";
|
|
when s_trap_disp => isnum := x"5e";
|
|
|
|
when s_int_ext => isnum := x"5f";
|
|
|
|
when s_int_getpc => isnum := x"60";
|
|
when s_int_getpc_w => isnum := x"61";
|
|
when s_int_getps => isnum := x"62";
|
|
when s_int_getps_w => isnum := x"63";
|
|
when s_int_getsp => isnum := x"64";
|
|
when s_int_decsp => isnum := x"65";
|
|
when s_int_pushps => isnum := x"66";
|
|
when s_int_pushps_w => isnum := x"67";
|
|
when s_int_pushpc => isnum := x"68";
|
|
when s_int_pushpc_w => isnum := x"69";
|
|
|
|
when s_rti_getpc => isnum := x"6a";
|
|
when s_rti_getpc_w => isnum := x"6b";
|
|
when s_rti_getps => isnum := x"6c";
|
|
when s_rti_getps_w => isnum := x"6d";
|
|
when s_rti_newpc => isnum := x"6e";
|
|
|
|
when s_vmerr => isnum := x"6f";
|
|
when s_cpufail => isnum := x"70";
|
|
|
|
-- STATE2SNUM mapper end
|
|
when others => isnum := x"ff";
|
|
end case;
|
|
DM_STAT_SE.snum <= isnum;
|
|
end process proc_snum;
|
|
|
end syn;
|
end syn;
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|