OpenCores
URL https://opencores.org/ocsvn/w11/w11/trunk

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.74/] [rtl/] [w11a/] [pdp11_sequencer.vhd] - Blame information for rev 34

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 34 wfjm
-- $Id: pdp11_sequencer.vhd 708 2015-08-03 06:41:43Z mueller $
2 2 wfjm
--
3 29 wfjm
-- Copyright 2006-2015 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4 2 wfjm
--
5
-- This program is free software; you may redistribute and/or modify it under
6
-- the terms of the GNU General Public License as published by the Free
7
-- Software Foundation, either version 2, or at your option any later version.
8
--
9
-- This program is distributed in the hope that it will be useful, but
10
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
11
-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
-- for complete details.
13
--
14
------------------------------------------------------------------------------
15
-- Module Name:    pdp11_sequencer - syn
16
-- Description:    pdp11: CPU sequencer
17
--
18 8 wfjm
-- Dependencies:   ib_sel
19 2 wfjm
-- Test bench:     tb/tb_pdp11_core (implicit)
20
-- Target Devices: generic
21 30 wfjm
-- Tool versions:  ise 8.2-14.7; viv 2014.4; ghdl 0.18-0.31
22 8 wfjm
--
23 2 wfjm
-- Revision History: 
24
-- Date         Rev Version  Comment
25 34 wfjm
-- 2015-08-02   708   1.6.5  BUGFIX: proper trap_mmu and trap_ysv handling
26
-- 2015-08-01   707   1.6.4  set dm_idone in s_(trap_10|op_trap); add dm_vfetch
27
-- 2015-07-19   702   1.6.3  add DM_STAT_SE, drop SNUM port
28
-- 2015-07-10   700   1.6.2  use c_cpurust_hbpt
29
-- 2015-06-26   695   1.6.1  add SNUM (state number) port
30 30 wfjm
-- 2015-05-10   678   1.6    start/stop/suspend overhaul; reset overhaul
31 29 wfjm
-- 2015-02-07   643   1.5.2  s_op_wait: load R0 in DSRC for DR emulation
32 25 wfjm
-- 2014-07-12   569   1.5.1  rename s_opg_div_zero -> s_opg_div_quit;
33
--                           use DP_STAT.div_quit; set munit_s_div_sr;
34
--                           BUGFIX: s_opg_div_sr: check for late div_quit
35 22 wfjm
-- 2014-04-20   554   1.5    now vivado compatible (add dummy assigns in procs)
36 13 wfjm
-- 2011-11-18   427   1.4.2  now numeric_std clean
37 8 wfjm
-- 2010-10-23   335   1.4.1  use ib_sel
38
-- 2010-10-17   333   1.4    use ibus V2 interface
39
-- 2010-09-18   300   1.3.2  rename (adlm)box->(oalm)unit
40 2 wfjm
-- 2010-06-20   307   1.3.1  rename cpacc to cacc in vm_cntl_type
41
-- 2010-06-13   305   1.3    remove CPDIN_WE, CPDOUT_WE out ports; set
42
--                           CNTL.cpdout_we instead of CPDOUT_WE
43
-- 2010-06-12   304   1.2.8  signal cpuwait when spinning in s_op_wait
44
-- 2009-05-30   220   1.2.7  final removal of snoopers (were already commented)
45
-- 2009-05-09   213   1.2.6  BUGFIX: use is_dstkstack1246, stklim for mode=6
46
-- 2009-05-02   211   1.2.5  BUGFIX: 11/70 spl semantics again in kernel mode
47
-- 2009-04-26   209   1.2.4  BUGFIX: give interrupts priority over trap handling
48
-- 2008-12-14   177   1.2.3  BUGFIX: use is_dstkstack124, fix stklim check bug
49
-- 2008-12-13   176   1.2.2  BUGFIX: use is_pci in s_dstw_inc if DSTDEF='1'
50
-- 2008-11-30   174   1.2.1  BUGFIX: add updt_dstadsrc; prevent stale DSRC
51
-- 2008-08-22   161   1.2    rename ubf_ -> ibf_; use iblib
52
-- 2008-05-03   143   1.1.9  rename _cpursta->_cpurust; cp reset sets now
53
--                           c_cpurust_reset; proper c_cpurust_vfail handling
54
-- 2008-04-27   140   1.1.8  BUGFIX: halt cpu in case of a vector fetch error
55
--                           use cpursta to encode why cpu halts, remove cpufail
56
-- 2008-04-27   139   1.1.7  BUGFIX: correct bytop handling for address fetches;
57
--                           BUGFIX: redo mtp flow; add fork_dsta fork and ddst
58
--                                   reload in s_opa_mtp_pop_w;
59
-- 2008-04-19   137   1.1.6  BUGFIX: fix loop state in s_rti_getpc_w
60
-- 2008-03-30   131   1.1.5  BUGFIX: inc/dec by 2 for byte mode -(sp),(sp)+
61
--                             inc/dec by 2 for @(R)+ and @-(R) also for bytop's
62
-- 2008-03-02   121   1.1.4  remove snoopers; add waitsusp, redo WAIT handling
63
-- 2008-02-24   119   1.1.3  add lah,rps,wps command; revamp cp memory access
64
--                           change WAIT logic, now also bails out on cp command
65
-- 2008-01-20   112   1.1.2  rename PRESET->BRESET
66
-- 2008-01-05   110   1.1.1  rename IB_MREQ(ena->req) SRES(sel->ack, hold->busy)
67
-- 2007-12-30   107   1.1    use IB_MREQ/IB_SRES interface now
68
-- 2007-06-14    56   1.0.1  Use slvtypes.all
69
-- 2007-05-12    26   1.0    Initial version 
70
------------------------------------------------------------------------------
71
 
72
library ieee;
73
use ieee.std_logic_1164.all;
74 13 wfjm
use ieee.numeric_std.all;
75 2 wfjm
 
76
use work.slvtypes.all;
77
use work.iblib.all;
78
use work.pdp11.all;
79
 
80
-- ----------------------------------------------------------------------------
81
 
82
entity pdp11_sequencer is               -- CPU sequencer
83
  port (
84
    CLK : in slbit;                     -- clock
85 30 wfjm
    GRESET : in slbit;                  -- general reset
86 2 wfjm
    PSW : in psw_type;                  -- processor status
87
    PC : in slv16;                      -- program counter
88
    IREG : in slv16;                    -- IREG
89
    ID_STAT : in decode_stat_type;      -- instr. decoder status
90
    DP_STAT : in dpath_stat_type;       -- data path status
91
    CP_CNTL : in cp_cntl_type;          -- console port control
92
    VM_STAT : in vm_stat_type;          -- virtual memory status port
93
    INT_PRI : in slv3;                  -- interrupt priority
94
    INT_VECT : in slv9_2;               -- interrupt vector
95 30 wfjm
    INT_ACK : out slbit;                -- interrupt acknowledge
96
    CRESET : out slbit;                 -- cpu reset
97
    BRESET : out slbit;                 -- bus reset
98 2 wfjm
    MMU_MONI : out mmu_moni_type;       -- mmu monitor port
99
    DP_CNTL : out dpath_cntl_type;      -- data path control
100
    VM_CNTL : out vm_cntl_type;         -- virtual memory control port
101
    CP_STAT : out cp_stat_type;         -- console port status
102 30 wfjm
    ESUSP_O : out slbit;                -- external suspend output
103
    ESUSP_I : in slbit;                 -- external suspend input
104
    ITIMER : out slbit;                 -- instruction timer
105 34 wfjm
    HBPT : in slbit;                    -- hardware bpt
106 2 wfjm
    IB_MREQ : in ib_mreq_type;          -- ibus request
107 34 wfjm
    IB_SRES : out ib_sres_type;         -- ibus response    
108
    DM_STAT_SE : out dm_stat_se_type    -- debug and monitor status - sequencer
109 2 wfjm
  );
110
end pdp11_sequencer;
111
 
112
architecture syn of pdp11_sequencer is
113
 
114 13 wfjm
  constant ibaddr_cpuerr : slv16 := slv(to_unsigned(8#177766#,16));
115 2 wfjm
 
116
  constant cpuerr_ibf_illhlt : integer := 7;
117
  constant cpuerr_ibf_adderr : integer := 6;
118
  constant cpuerr_ibf_nxm : integer := 5;
119
  constant cpuerr_ibf_iobto : integer := 4;
120
  constant cpuerr_ibf_ysv : integer := 3;
121
  constant cpuerr_ibf_rsv : integer := 2;
122
 
123
  type state_type is (
124
    s_idle,
125
    s_cp_regread,
126
    s_cp_rps,
127
    s_cp_memr_w,
128
    s_cp_memw_w,
129
    s_ifetch,
130
    s_ifetch_w,
131
    s_idecode,
132
 
133
    s_srcr_def,
134
    s_srcr_def_w,
135
    s_srcr_inc,
136
    s_srcr_inc_w,
137
    s_srcr_dec,
138
    s_srcr_dec1,
139
    s_srcr_ind,
140
    s_srcr_ind1_w,
141
    s_srcr_ind2,
142
    s_srcr_ind2_w,
143
 
144
    s_dstr_def,
145
    s_dstr_def_w,
146
    s_dstr_inc,
147
    s_dstr_inc_w,
148
    s_dstr_dec,
149
    s_dstr_dec1,
150
    s_dstr_ind,
151
    s_dstr_ind1_w,
152
    s_dstr_ind2,
153
    s_dstr_ind2_w,
154
 
155
    s_dstw_def,
156
    s_dstw_def_w,
157
    s_dstw_inc,
158
    s_dstw_inc_w,
159
    s_dstw_incdef_w,
160
    s_dstw_dec,
161
    s_dstw_dec1,
162
    s_dstw_ind,
163
    s_dstw_ind_w,
164
    s_dstw_def246,
165
 
166
    s_dsta_inc,
167
    s_dsta_incdef_w,
168
    s_dsta_dec,
169
    s_dsta_dec1,
170
    s_dsta_ind,
171
    s_dsta_ind_w,
172
 
173
    s_op_halt,
174
    s_op_wait,
175
    s_op_trap,
176
    s_op_reset,
177
    s_op_rts,
178
    s_op_rts_pop,
179
    s_op_rts_pop_w,
180
    s_op_spl,
181
    s_op_mcc,
182
    s_op_br,
183
    s_op_mark,
184
    s_op_mark1,
185
    s_op_mark_pop,
186
    s_op_mark_pop_w,
187
    s_op_sob,
188
    s_op_sob1,
189
 
190
    s_opg_gen,
191
    s_opg_gen_rmw_w,
192
    s_opg_mul,
193
    s_opg_mul1,
194
    s_opg_div,
195
    s_opg_div_cn,
196
    s_opg_div_cr,
197
    s_opg_div_sq,
198
    s_opg_div_sr,
199 25 wfjm
    s_opg_div_quit,
200 2 wfjm
    s_opg_ash,
201
    s_opg_ash_cn,
202
    s_opg_ashc,
203
    s_opg_ashc_cn,
204
    s_opg_ashc_wl,
205
 
206
    s_opa_jsr,
207
    s_opa_jsr1,
208
    s_opa_jsr_push,
209
    s_opa_jsr_push_w,
210
    s_opa_jsr2,
211
    s_opa_jmp,
212
    s_opa_mtp,
213
    s_opa_mtp_pop_w,
214
    s_opa_mtp_reg,
215
    s_opa_mtp_mem,
216
    s_opa_mtp_mem_w,
217
    s_opa_mfp_reg,
218
    s_opa_mfp_mem,
219
    s_opa_mfp_mem_w,
220
    s_opa_mfp_dec,
221
    s_opa_mfp_push,
222
    s_opa_mfp_push_w,
223
 
224
    s_trap_4,
225
    s_trap_10,
226
    s_trap_disp,
227
 
228
    s_int_ext,
229
 
230
    s_int_getpc,
231
    s_int_getpc_w,
232
    s_int_getps,
233
    s_int_getps_w,
234
    s_int_getsp,
235
    s_int_decsp,
236
    s_int_pushps,
237
    s_int_pushps_w,
238
    s_int_pushpc,
239
    s_int_pushpc_w,
240
 
241
    s_rti_getpc,
242
    s_rti_getpc_w,
243
    s_rti_getps,
244
    s_rti_getps_w,
245
    s_rti_newpc,
246
 
247
    s_vmerr,
248
    s_cpufail
249
  );
250
 
251
  signal R_STATE : state_type := s_idle;  -- state register
252
  signal N_STATE : state_type := s_idle;
253
 
254
  signal R_STATUS : cpustat_type := cpustat_init;
255
  signal N_STATUS : cpustat_type := cpustat_init;
256
  signal R_CPUERR : cpuerr_type := cpuerr_init;
257
  signal N_CPUERR : cpuerr_type := cpuerr_init;
258
 
259
  signal R_IDSTAT : decode_stat_type := decode_stat_init;
260
  signal N_IDSTAT : decode_stat_type := decode_stat_init;
261
 
262
  signal R_VMSTAT : vm_stat_type := vm_stat_init;
263
 
264
  signal IBSEL_CPUERR : slbit := '0';
265
 
266
begin
267
 
268 8 wfjm
  SEL : ib_sel
269
    generic map (
270
      IB_ADDR => ibaddr_cpuerr)
271
    port map (
272
      CLK     => CLK,
273
      IB_MREQ => IB_MREQ,
274
      SEL     => IBSEL_CPUERR
275
    );
276 2 wfjm
 
277 8 wfjm
  proc_ibres : process (IBSEL_CPUERR, IB_MREQ, R_CPUERR)
278
    variable idout : slv16 := (others=>'0');
279 2 wfjm
  begin
280 8 wfjm
    idout := (others=>'0');
281 2 wfjm
    if IBSEL_CPUERR = '1' then
282 8 wfjm
      idout(cpuerr_ibf_illhlt) := R_CPUERR.illhlt;
283
      idout(cpuerr_ibf_adderr) := R_CPUERR.adderr;
284
      idout(cpuerr_ibf_nxm)    := R_CPUERR.nxm;
285
      idout(cpuerr_ibf_iobto)  := R_CPUERR.iobto;
286
      idout(cpuerr_ibf_ysv)    := R_CPUERR.ysv;
287
      idout(cpuerr_ibf_rsv)    := R_CPUERR.rsv;
288 2 wfjm
    end if;
289 8 wfjm
    IB_SRES.dout <= idout;
290
    IB_SRES.ack  <= IBSEL_CPUERR and (IB_MREQ.re or IB_MREQ.we); -- ack all
291
    IB_SRES.busy <= '0';
292
  end process proc_ibres;
293 2 wfjm
 
294
  proc_status: process (CLK)
295
  begin
296 13 wfjm
    if rising_edge(CLK) then
297 2 wfjm
      if GRESET = '1' then
298
        R_STATUS <= cpustat_init;
299
        R_CPUERR <= cpuerr_init;
300
        R_IDSTAT <= decode_stat_init;
301
        R_VMSTAT <= vm_stat_init;
302
      else
303
        R_STATUS <= N_STATUS;
304
        R_CPUERR <= N_CPUERR;
305
        R_IDSTAT <= N_IDSTAT;
306
        R_VMSTAT <= VM_STAT;
307
      end if;
308
    end if;
309
  end process proc_status;
310
 
311
  proc_state: process (CLK)
312
  begin
313 13 wfjm
    if rising_edge(CLK) then
314 2 wfjm
      if GRESET = '1' then
315
        R_STATE <= s_idle;
316
      else
317
        R_STATE <= N_STATE;
318
      end if;
319
    end if;
320
  end process proc_state;
321
 
322
  proc_next: process (R_STATE, R_STATUS, PSW, PC, CP_CNTL,
323
                      ID_STAT, R_IDSTAT, IREG, VM_STAT, DP_STAT,
324
                      R_CPUERR, R_VMSTAT, IB_MREQ, IBSEL_CPUERR,
325 34 wfjm
                      INT_PRI, INT_VECT, ESUSP_I, HBPT)
326 2 wfjm
 
327
    variable nstate : state_type;
328
    variable nstatus : cpustat_type := cpustat_init;
329
    variable ncpuerr : cpuerr_type := cpuerr_init;
330
 
331
    variable ndpcntl : dpath_cntl_type := dpath_cntl_init;
332
    variable nvmcntl : vm_cntl_type := vm_cntl_init;
333
    variable nidstat : decode_stat_type := decode_stat_init;
334
    variable nmmumoni : mmu_moni_type := mmu_moni_init;
335
 
336
    variable imemok : boolean;
337
    variable bytop : slbit := '0';           -- local bytop  access flag
338
    variable macc  : slbit := '0';           -- local modify access flag
339
 
340
    variable lvector : slv9_2 := (others=>'0'); -- local trap/interrupt vector
341
 
342
    variable brcode : slv4 := (others=>'0'); -- reduced br opcode (15,10-8)
343
    variable brcond : slbit := '0';          -- br condition value
344
 
345
    variable is_kmode : slbit := '0';        -- cmode is kernel mode
346
    variable is_dstkstack1246 : slbit := '0'; -- dest is k-stack & mode= 1,2,4,6
347
 
348
    variable int_pending : slbit := '0';     -- an interrupt is pending
349 34 wfjm
 
350
    variable idm_idone   : slbit := '0';     -- idone  for dm_stat_se
351
    variable idm_vfetch  : slbit := '0';     -- vfetch for dm_stat_se
352 2 wfjm
 
353
    alias SRCMOD : slv2 is IREG(11 downto 10); -- src register mode high
354
    alias SRCDEF : slbit is IREG(9);           -- src register mode defered
355
    alias SRCREG : slv3 is IREG(8 downto 6);   -- src register number
356
    alias DSTMODF : slv3 is IREG(5 downto 3);  -- dst register full mode
357
    alias DSTMOD : slv2 is IREG(5 downto 4);   -- dst register mode high
358
    alias DSTDEF : slbit is IREG(3);           -- dst register mode defered
359
    alias DSTREG : slv3 is IREG(2 downto 0);   -- dst register number
360
 
361
    procedure do_memread_i(nstate  : inout state_type;
362
                           ndpcntl : inout dpath_cntl_type;
363
                           nvmcntl : inout vm_cntl_type;
364
                           wstate  : in state_type) is
365
    begin
366
      ndpcntl.vmaddr_sel := c_dpath_vmaddr_pc;       -- VA = PC
367
      nvmcntl.dspace := '0';
368
      nvmcntl.req := '1';
369
      ndpcntl.gpr_pcinc := '1';                      -- (pc)++
370
      nstate := wstate;
371
    end procedure do_memread_i;
372
 
373
    procedure do_memread_d(nstate  : inout state_type;
374
                           nvmcntl : inout vm_cntl_type;
375
                           wstate  : in state_type;
376
                           bytop   : in slbit := '0';
377
                           macc    : in slbit := '0';
378
                           is_pci  : in slbit := '0') is
379
    begin
380
      nvmcntl.dspace := not is_pci;        -- ispace if pc immediate modes
381
--      bytop := R_IDSTAT.is_bytop and not is_addr;
382
      nvmcntl.bytop := bytop;
383
      nvmcntl.macc  := macc;
384
      nvmcntl.req   := '1';
385
      nstate := wstate;
386
    end procedure do_memread_d;
387
 
388
    procedure do_memread_srcinc(nstate   : inout state_type;
389
                                ndpcntl  : inout dpath_cntl_type;
390
                                nvmcntl  : inout vm_cntl_type;
391
                                wstate   : in state_type;
392
                                nmmumoni : inout mmu_moni_type;
393
                                updt_sp  : in slbit := '0') is
394
    begin
395 8 wfjm
      ndpcntl.ounit_asel := c_ounit_asel_dsrc;   -- OUNIT A=DSRC
396
      ndpcntl.ounit_const := "000000010";        -- OUNIT const=2
397
      ndpcntl.ounit_bsel := c_ounit_bsel_const;  -- OUNIT B=const
398
      ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
399 2 wfjm
      ndpcntl.dsrc_sel := c_dpath_dsrc_res;      -- DSRC = DRES
400
      ndpcntl.dsrc_we := '1';                    -- update DSRC
401
      if updt_sp = '1' then
402
        nmmumoni.regmod := '1';
403
        nmmumoni.isdec := '0';
404
        ndpcntl.gpr_adst := c_gpr_sp;            -- update SP too
405
        ndpcntl.gpr_we := '1';
406
      end if;
407
      ndpcntl.vmaddr_sel := c_dpath_vmaddr_dsrc; -- VA = DSRC
408
      nvmcntl.dspace := '1';
409
      nvmcntl.req := '1';
410
      nstate := wstate;
411
    end procedure do_memread_srcinc;
412
 
413
    procedure do_memwrite(nstate  : inout state_type;
414
                          nvmcntl : inout vm_cntl_type;
415
                          wstate  : in state_type;
416
                          macc    : in slbit :='0') is
417
    begin
418
      nvmcntl.dspace := '1';
419
      nvmcntl.bytop := R_IDSTAT.is_bytop;
420
      nvmcntl.wacc := '1';
421
      nvmcntl.macc := macc;
422
      nvmcntl.req := '1';
423
      nstate := wstate;
424
    end procedure do_memwrite;
425
 
426
    procedure do_memcheck(nstate  : inout state_type;
427
                          nstatus : inout cpustat_type;
428
                          mok     : out boolean) is
429
    begin
430 22 wfjm
      nstate  := nstate;                -- dummy to add driver (vivado)
431
      nstatus := nstatus;               -- "
432 2 wfjm
      mok := false;
433
      if VM_STAT.ack = '1' then
434
        mok := true;
435 34 wfjm
        if VM_STAT.trap_mmu = '1' then  -- remember trap_mmu, may happen on any
436
          nstatus.trap_mmu := '1';      --   memory access of an instruction
437 2 wfjm
        end if;
438 34 wfjm
        if VM_STAT.trap_ysv = '1' then  -- remember trap_ysv (on any access)
439
          if R_CPUERR.ysv = '0' then      -- ysv trap when cpuerr not yet set
440
            nstatus.trap_ysv := '1';
441
          end if;
442
        end if;
443 2 wfjm
      elsif VM_STAT.err='1' or VM_STAT.fail='1' then
444
        nstate := s_vmerr;
445
      end if;
446
    end procedure do_memcheck;
447
 
448
    procedure do_const_opsize(ndpcntl : inout dpath_cntl_type;
449
                              bytop   : in slbit;
450
                              isdef   : in slbit;
451
                              regnum  : in slv3) is
452
    begin
453 22 wfjm
      ndpcntl := ndpcntl;               -- dummy to add driver (vivado)
454 2 wfjm
      if bytop='0' or isdef='1' or
455
         regnum=c_gpr_pc or regnum=c_gpr_sp then
456 8 wfjm
        ndpcntl.ounit_const := "000000010";
457 2 wfjm
      else
458 8 wfjm
        ndpcntl.ounit_const := "000000001";
459 2 wfjm
      end if;
460
    end procedure do_const_opsize;
461
 
462
    procedure do_fork_dstr(nstate : inout state_type;
463
                           idstat : in decode_stat_type) is
464
    begin
465
      case idstat.fork_dstr is
466
        when c_fork_dstr_def => nstate := s_dstr_def;
467
        when c_fork_dstr_inc => nstate := s_dstr_inc;
468
        when c_fork_dstr_dec => nstate := s_dstr_dec;
469
        when c_fork_dstr_ind => nstate := s_dstr_ind;
470
        when others => nstate := s_cpufail;
471
      end case;
472
    end procedure do_fork_dstr;
473
 
474
    procedure do_fork_opg(nstate : inout state_type;
475
                          idstat : in decode_stat_type) is
476
    begin
477
      case idstat.fork_opg is
478
        when c_fork_opg_gen  => nstate := s_opg_gen;
479
        when c_fork_opg_wdef => nstate := s_dstw_def;
480
        when c_fork_opg_winc => nstate := s_dstw_inc;
481
        when c_fork_opg_wdec => nstate := s_dstw_dec;
482
        when c_fork_opg_wind => nstate := s_dstw_ind;
483
        when c_fork_opg_mul  => nstate := s_opg_mul;
484
        when c_fork_opg_div  => nstate := s_opg_div;
485
        when c_fork_opg_ash  => nstate := s_opg_ash;
486
        when c_fork_opg_ashc => nstate := s_opg_ashc;
487
        when others => nstate := s_cpufail;
488
      end case;
489
    end procedure do_fork_opg;
490
 
491
    procedure do_fork_opa(nstate : inout state_type;
492
                          idstat : in decode_stat_type) is
493
    begin
494
      case idstat.fork_opa is
495
        when c_fork_opa_jmp => nstate := s_opa_jmp;
496
        when c_fork_opa_jsr => nstate := s_opa_jsr;
497
        when c_fork_opa_mtp => nstate := s_opa_mtp_mem;
498
        when c_fork_opa_mfp_reg => nstate := s_opa_mfp_reg;
499
        when c_fork_opa_mfp_mem => nstate := s_opa_mfp_mem;
500
        when others => nstate := s_cpufail;
501
      end case;
502
    end procedure do_fork_opa;
503
 
504
    procedure do_fork_next(nstate   : inout state_type;
505
                           nstatus  : inout cpustat_type;
506
                           nmmumoni : inout mmu_moni_type) is
507
    begin
508
      nmmumoni.idone := '1';
509
      if unsigned(INT_PRI) > unsigned(PSW.pri) then
510
        nstate := s_idle;
511
      elsif R_STATUS.trap_mmu='1' or nstatus.trap_mmu='1' or
512
            R_STATUS.trap_ysv='1' or nstatus.trap_ysv='1' or
513
            PSW.tflag='1' then
514
        nstate := s_trap_disp;
515 30 wfjm
      elsif R_STATUS.cpugo='1' and        -- running
516
            R_STATUS.cpususp='0' and      --   and not suspended
517
            not R_STATUS.cmdbusy='1' then --   and no cmd pending
518
        nstate := s_ifetch;                               -- fetch next
519 2 wfjm
      else
520 30 wfjm
        nstate := s_idle;                                 -- otherwise idle
521 2 wfjm
      end if;
522
    end procedure do_fork_next;
523
 
524
    procedure do_fork_next_pref(nstate   : inout state_type;
525
                                nstatus  : inout cpustat_type;
526
                                ndpcntl  : inout dpath_cntl_type;
527
                                nvmcntl  : inout vm_cntl_type;
528
                                nmmumoni : inout mmu_moni_type) is
529
    begin
530 22 wfjm
      ndpcntl := ndpcntl;               -- dummy to add driver (vivado)
531
      nvmcntl := nvmcntl;               -- "
532 2 wfjm
      nmmumoni.idone := '1';
533
      if unsigned(INT_PRI) > unsigned(PSW.pri) then
534
        nstate := s_idle;
535
      elsif R_STATUS.trap_mmu='1' or nstatus.trap_mmu='1' or
536
            R_STATUS.trap_ysv='1' or nstatus.trap_ysv='1' or
537
            PSW.tflag='1' then
538
        nstate := s_trap_disp;
539 30 wfjm
      elsif R_STATUS.cpugo='1' and       -- running
540
            R_STATUS.cpususp='0' and      --   and not suspended
541
            not R_STATUS.cmdbusy='1' then --   and no cmd pending
542
        nvmcntl.req := '1';                 -- read next instruction
543
        ndpcntl.gpr_pcinc := '1';           -- inc PC
544
        nmmumoni.istart := '1';             -- signal istart to MMU
545
        nstate := s_ifetch_w;               -- next: wait for fetched instruction
546 2 wfjm
      else
547 30 wfjm
        nstate := s_idle;                   -- otherwise idle
548 2 wfjm
      end if;
549
    end procedure do_fork_next_pref;
550
 
551
    procedure do_start_int(nstate  : inout state_type;
552
                           ndpcntl : inout dpath_cntl_type;
553
                           vector  : in slv9_2) is
554
    begin
555
      ndpcntl.dtmp_sel := c_dpath_dtmp_psw;    -- DTMP = PSW 
556
      ndpcntl.dtmp_we := '1';
557 8 wfjm
      ndpcntl.ounit_azero := '1';              -- OUNIT A = 0
558
      ndpcntl.ounit_const := vector & "00";    -- vector
559
      ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B=const(vector)
560
      ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
561 2 wfjm
      ndpcntl.dsrc_sel := c_dpath_dsrc_res;    -- DSRC = DRES
562
      ndpcntl.dsrc_we := '1';                  -- DSRC = vector
563
      nstate := s_int_getpc;
564
    end procedure do_start_int;
565
 
566
  begin
567
 
568
    nstate  := R_STATE;
569
    nstatus := R_STATUS;
570
    ncpuerr := R_CPUERR;
571
 
572
    nstatus.cpuwait := '0';             -- wait flag 0 unless set in s_op_wait
573 30 wfjm
 
574
    -- itimer pulse logic:
575
    --   if neither running nor suspended --> free run, set itimer = 1
576
    --   otherwise clear to ensure single cycle pulses generated by
577
    --   s_idecode or s_op_wait
578
    if R_STATUS.cpugo='0' and R_STATUS.cpususp='0' then
579
      nstatus.itimer := '1';
580
    else
581
      nstatus.itimer := '0';
582
    end if;
583 2 wfjm
 
584 30 wfjm
    nstatus.creset := '0';              -- ensure single cycle pulse
585
    nstatus.breset := '0';              -- dito
586
    nstatus.intack := '0';              -- dito
587 2 wfjm
 
588
    nidstat := R_IDSTAT;
589
 
590 8 wfjm
    if IBSEL_CPUERR='1' and IB_MREQ.we='1' then -- write to CPUERR clears it !
591 2 wfjm
      ncpuerr := cpuerr_init;
592
    end if;
593
 
594
    int_pending := '0';
595
    if unsigned(INT_PRI) > unsigned(PSW.pri) then
596
      int_pending := '1';
597
    end if;
598 34 wfjm
 
599
    idm_idone  := '0';
600
    idm_vfetch := '0';
601 2 wfjm
 
602
    imemok := false;
603
 
604
    nmmumoni := mmu_moni_init;
605
    nmmumoni.pc := PC;
606
 
607
    macc  := '0';
608
    bytop := '0';
609
    brcode := IREG(15) & IREG(10 downto 8);
610
    brcond := '1';
611
 
612
    is_kmode := '0';
613
    is_dstkstack1246 := '0';
614
 
615
    if PSW.cmode = c_psw_kmode then
616
      is_kmode := '1';
617
      if DSTREG = c_gpr_sp and
618
         (DSTMODF="001" or DSTMODF="010" or
619
          DSTMODF="100" or DSTMODF="110") then
620
        is_dstkstack1246 := '1';
621
      end if;
622
    end if;
623
 
624
    lvector := (others=>'0');
625
 
626
    nvmcntl := vm_cntl_init;
627
    nvmcntl.dspace := '1';                -- DEFAULT
628
    nvmcntl.mode := PSW.cmode;            -- DEFAULT
629
    nvmcntl.intrsv := R_STATUS.do_intrsv; -- DEFAULT
630
 
631
    ndpcntl := dpath_cntl_init;
632
    ndpcntl.gpr_asrc := SRCREG;           -- DEFAULT
633
    ndpcntl.gpr_adst := DSTREG;           -- DEFAULT
634
    ndpcntl.gpr_mode := PSW.cmode;        -- DEFAULT
635
    ndpcntl.gpr_rset := PSW.rset;         -- DEFAULT
636
    ndpcntl.gpr_we := '0';                -- DEFAULT
637
    ndpcntl.gpr_bytop := '0';             -- DEFAULT
638
    ndpcntl.gpr_pcinc := '0';             -- DEFAULT
639
 
640
    ndpcntl.psr_ccwe := '0';              -- DEFAULT
641
    ndpcntl.psr_we := '0';                -- DEFAULT
642
    ndpcntl.psr_func := "000";            -- DEFAULT
643
 
644
    ndpcntl.dsrc_sel := c_dpath_dsrc_src;
645
    ndpcntl.dsrc_we := '0';
646
    ndpcntl.ddst_sel := c_dpath_ddst_dst;
647
    ndpcntl.ddst_we := '0';
648
    ndpcntl.dtmp_sel := c_dpath_dtmp_dsrc;
649
    ndpcntl.dtmp_we := '0';
650
 
651 8 wfjm
    ndpcntl.ounit_asel  := c_ounit_asel_ddst;
652
    ndpcntl.ounit_azero := '0';            -- DEFAULT
653
    ndpcntl.ounit_const := (others=>'0');  -- DEFAULT
654
    ndpcntl.ounit_bsel  := c_ounit_bsel_const;
655
    ndpcntl.ounit_opsub := '0';            -- DEFAULT
656 2 wfjm
 
657 8 wfjm
    ndpcntl.aunit_srcmod := R_IDSTAT.aunit_srcmod; -- STATIC
658
    ndpcntl.aunit_dstmod := R_IDSTAT.aunit_dstmod; -- STATIC
659
    ndpcntl.aunit_cimod  := R_IDSTAT.aunit_cimod;  -- STATIC
660
    ndpcntl.aunit_cc1op  := R_IDSTAT.aunit_cc1op;  -- STATIC
661
    ndpcntl.aunit_ccmode := R_IDSTAT.aunit_ccmode; -- STATIC
662
    ndpcntl.aunit_bytop  := R_IDSTAT.is_bytop;     -- STATIC
663 2 wfjm
 
664 8 wfjm
    ndpcntl.lunit_func   := R_IDSTAT.lunit_func;   -- STATIC
665
    ndpcntl.lunit_bytop  := R_IDSTAT.is_bytop;     -- STATIC
666 2 wfjm
 
667 8 wfjm
    ndpcntl.munit_func := R_IDSTAT.munit_func;     -- STATIC
668 2 wfjm
 
669
    ndpcntl.ireg_we := '0';
670
 
671
    ndpcntl.cres_sel := R_IDSTAT.res_sel;        -- DEFAULT
672 8 wfjm
    ndpcntl.dres_sel := c_dpath_res_ounit;
673 2 wfjm
    ndpcntl.vmaddr_sel := c_dpath_vmaddr_dsrc;
674
 
675
    if CP_CNTL.req='1' and R_STATUS.cmdbusy='0' then
676
      nstatus.cmdbusy := '1';
677
      nstatus.cpfunc  := CP_CNTL.func;
678
      nstatus.cprnum  := CP_CNTL.rnum;
679
    end if;
680
 
681
    if R_STATUS.cmdack = '1' then
682
      nstatus.cmdack  := '0';
683
      nstatus.cmderr  := '0';
684
      nstatus.cmdmerr := '0';
685
    end if;
686
 
687
    case R_STATE is
688
 
689
  -- idle and command port states ---------------------------------------------
690
 
691
      -- Note: s_idle was entered from suspended WAIT when waitsusp='1'
692
      -- --> all exits must check this and either return to s_op_wait
693
      --     or abort the WAIT and set waitsusp='0'
694
 
695
      when s_idle =>
696
 
697
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst;   -- VA = DDST (do mux early)
698
        nstatus.cpustep := '0';
699
 
700
        if R_STATUS.cmdbusy = '1' then
701
          case R_STATUS.cpfunc is
702
 
703 30 wfjm
            when c_cpfunc_noop =>       -- noop : no operation -------
704 2 wfjm
              nstatus.cmdack   := '1';
705
              nstate := s_idle;
706
 
707 30 wfjm
            when c_cpfunc_start =>      -- start : cpu start ---------
708 2 wfjm
              nstatus.cmdack   := '1';
709 30 wfjm
              if R_STATUS.cpugo = '1' then -- if already running
710
                nstatus.cmderr := '1';       -- reject
711
              else                         -- if not running
712
                nstatus.cpugo    := '1';     -- start cpu
713
                nstatus.cpurust  := c_cpurust_runs;
714
                nstatus.waitsusp := '0';
715
              end if;
716 2 wfjm
              nstate := s_idle;
717
 
718 30 wfjm
            when c_cpfunc_stop =>       -- stop : cpu stop -----------
719 2 wfjm
              nstatus.cmdack   := '1';
720
              nstatus.cpugo    := '0';
721
              nstatus.cpurust  := c_cpurust_stop;
722
              nstatus.waitsusp := '0';
723
              nstate := s_idle;
724
 
725 30 wfjm
            when c_cpfunc_step =>       -- step : cpu step -----------
726 2 wfjm
              nstatus.cmdack   := '1';
727
              nstatus.cpustep  := '1';
728
              nstatus.cpurust  := c_cpurust_step;
729
              nstatus.waitsusp := '0';
730
              if int_pending = '1' then
731 30 wfjm
                nstatus.intack  := '1';
732 2 wfjm
                nstatus.intvect := INT_VECT;
733
                nstate := s_int_ext;
734
              else
735
                nstate := s_ifetch;
736
              end if;
737
 
738 30 wfjm
            when c_cpfunc_creset =>     -- creset : cpu reset --------
739 2 wfjm
              nstatus.cmdack   := '1';
740 30 wfjm
              if R_STATUS.cpugo = '1' then -- if already running
741
                nstatus.cmderr := '1';       -- reject
742
              else                         -- if not running
743
                nstatus.creset  := '1';      --  do cpu reset
744
                nstatus.breset  := '1';      -- and bus reset !
745
                nstatus.suspint := '0';      -- clear suspend
746
                nstatus.cpurust := c_cpurust_init;
747
              end if;
748 2 wfjm
              nstate := s_idle;
749
 
750 30 wfjm
            when c_cpfunc_breset =>     -- breset : bus reset --------
751
              nstatus.cmdack   := '1';
752
              if R_STATUS.cpugo = '1' then -- if already running
753
                nstatus.cmderr := '1';       -- reject
754
              else                         -- if not running
755
                nstatus.breset := '1';        -- do bus reset only
756
              end if;
757
              nstate := s_idle;
758
 
759
            when c_cpfunc_suspend =>    -- suspend : cpu suspend -----
760
              nstatus.cmdack   := '1';
761
              nstatus.suspint  := '1';
762
              nstatus.cpurust  := c_cpurust_susp;
763
              nstate := s_idle;
764
 
765
            when c_cpfunc_resume =>     -- resume : cpu resume -------
766
              nstatus.cmdack   := '1';
767
              nstatus.suspint  := '0';
768
              if R_STATUS.cpugo = '1' then
769
                nstatus.cpurust  := c_cpurust_runs;
770
              else
771
                nstatus.cpurust  := c_cpurust_stop;
772
              end if;
773
              nstate := s_idle;
774
 
775 2 wfjm
            when c_cpfunc_rreg =>       -- rreg : read register ------
776
              ndpcntl.gpr_adst := R_STATUS.cprnum;
777
              ndpcntl.ddst_sel := c_dpath_ddst_dst;
778
              ndpcntl.ddst_we := '1';
779
              nstate := s_cp_regread;
780
 
781
            when c_cpfunc_wreg =>       -- wreg : write register -----
782
              ndpcntl.dres_sel := c_dpath_res_cpdin;  -- DRES = CPDIN
783
              ndpcntl.gpr_adst := R_STATUS.cprnum;
784
              ndpcntl.gpr_we := '1';
785
              nstatus.cmdack := '1';
786
              nstate := s_idle;
787
 
788
            when c_cpfunc_rpsw =>       -- rpsw : read psw -----------
789
              ndpcntl.dtmp_sel := c_dpath_dtmp_psw;   -- DTMP = PSW 
790
              ndpcntl.dtmp_we := '1';
791
              nstate := s_cp_rps;
792
 
793
            when c_cpfunc_wpsw =>       -- wpsw : write psw ----------
794
              ndpcntl.dres_sel := c_dpath_res_cpdin;  -- DRES = CPDIN
795
              ndpcntl.psr_func := c_psr_func_wall;    -- write all fields
796
              ndpcntl.psr_we := '1';                  -- load new PS
797
              nstatus.cmdack := '1';
798
              nstate := s_idle;
799
 
800
            when c_cpfunc_rmem =>       -- rmem : read memory --------
801
              nvmcntl.cacc := '1';
802
              nvmcntl.req  := '1';
803
              nstate := s_cp_memr_w;
804
 
805
            when c_cpfunc_wmem =>       -- wmem : write memory -------
806
              ndpcntl.dres_sel := c_dpath_res_cpdin;     -- DRES = CPDIN
807
              nvmcntl.wacc := '1';                       -- write mem
808
              nvmcntl.cacc := '1';
809
              nvmcntl.req  := '1';
810
              nstate := s_cp_memw_w;
811
 
812
            when others =>
813
              nstatus.cmdack := '1';
814
              nstatus.cmderr := '1';
815
              nstate := s_idle;
816
 
817
          end case;
818
 
819
        elsif R_STATUS.waitsusp = '1' then
820
          nstatus.waitsusp := '0';
821
          nstate := s_op_wait;
822
 
823 30 wfjm
        elsif R_STATUS.cpugo = '1' and    -- running
824
              R_STATUS.cpususp='0' then   --   and not suspended
825
          if int_pending = '1' then         -- interrupt pending
826
            nstatus.intack  := '1';           -- acknowledle it
827
            nstatus.intvect := INT_VECT;      -- latch vector address
828
            nstate := s_int_ext;              -- and handle
829 2 wfjm
          else
830 30 wfjm
            nstate := s_ifetch;               -- otherwise fetch intruction
831 2 wfjm
          end if;
832
 
833
        end if;
834
 
835
      when s_cp_regread =>
836 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst;  -- OUNIT A = DDST
837
        ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B = const(0)
838
        ndpcntl.dres_sel  := c_dpath_res_ounit;   -- DRES = OUNIT
839 2 wfjm
        nstatus.cmdack := '1';
840
        nstate := s_idle;
841
 
842
      when s_cp_rps =>
843 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dtmp;  -- OUNIT A = DTMP
844
        ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B = const(0)
845
        ndpcntl.dres_sel  := c_dpath_res_ounit;   -- DRES = OUNIT
846 2 wfjm
        nstatus.cmdack := '1';
847
        nstate := s_idle;
848
 
849
      when s_cp_memr_w =>
850
        nstate := s_cp_memr_w;
851
        ndpcntl.dres_sel := c_dpath_res_vmdout;  -- DRES = VMDOUT
852
        if (VM_STAT.ack or VM_STAT.err or VM_STAT.fail)='1' then
853
          nstatus.cmdack   := '1';
854
          nstatus.trap_ysv := '0';               -- suppress traps on console
855
          nstatus.trap_mmu := '0';
856
          nstatus.cmdmerr  := VM_STAT.err or VM_STAT.fail;
857
          nstate := s_idle;
858
        end if;
859
 
860
      when s_cp_memw_w =>
861
        nstate := s_cp_memw_w;
862
        if (VM_STAT.ack or VM_STAT.err or VM_STAT.fail)='1' then
863
          nstatus.cmdack   := '1';
864
          nstatus.trap_ysv := '0';               -- suppress traps on console
865
          nstatus.trap_mmu := '0';
866
          nstatus.cmdmerr  := VM_STAT.err or VM_STAT.fail;
867
          nstate := s_idle;
868
        end if;
869
 
870
  -- instruction fetch and decode ---------------------------------------------
871
 
872
      when s_ifetch =>
873
        nmmumoni.istart := '1';         -- do here; memread_i inc PC ! 
874
        do_memread_i(nstate, ndpcntl, nvmcntl, s_ifetch_w);
875
 
876
      when s_ifetch_w =>
877
        nstate := s_ifetch_w;
878
        do_memcheck(nstate, nstatus, imemok);
879
        if imemok then
880
          ndpcntl.ireg_we := '1';
881
          nstate := s_idecode;
882
        end if;
883
 
884
      when s_idecode =>
885 30 wfjm
        nstatus.itimer := '1';          -- signal instruction started
886 2 wfjm
        nidstat := ID_STAT;             -- register decode status
887
        if ID_STAT.force_srcsp = '1' then
888
          ndpcntl.gpr_asrc := c_gpr_sp;
889
        end if;
890
        ndpcntl.dsrc_sel := c_dpath_dsrc_src;
891
        ndpcntl.dsrc_we := '1';
892
        ndpcntl.ddst_sel := c_dpath_ddst_dst;
893
        ndpcntl.ddst_we := '1';
894
 
895
        nvmcntl.dspace := '0';
896
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_pc;       -- VA = PC
897
 
898
        if ID_STAT.do_pref_dec='1' and PSW.tflag='0' and int_pending='0' and
899 30 wfjm
           R_STATUS.cpugo='1' and R_STATUS.cpususp='0' and
900
           not R_STATUS.cmdbusy='1'
901 2 wfjm
        then
902
          nvmcntl.req := '1';
903
          ndpcntl.gpr_pcinc := '1';                    -- (pc)++
904
          nmmumoni.istart := '1';
905
          nstatus.prefdone := '1';
906
        end if;
907
 
908
        if ID_STAT.do_fork_op = '1' then
909
          case ID_STAT.fork_op is
910
            when c_fork_op_halt => nstate := s_op_halt;
911
            when c_fork_op_wait => nstate := s_op_wait;
912
            when c_fork_op_rtti => nstate := s_rti_getpc;
913
            when c_fork_op_trap => nstate := s_op_trap;
914
            when c_fork_op_reset=> nstate := s_op_reset;
915
            when c_fork_op_rts  => nstate := s_op_rts;
916
            when c_fork_op_spl  => nstate := s_op_spl;
917
            when c_fork_op_mcc  => nstate := s_op_mcc;
918
            when c_fork_op_br   => nstate := s_op_br;
919
            when c_fork_op_mark => nstate := s_op_mark;
920
            when c_fork_op_sob  => nstate := s_op_sob;
921
            when c_fork_op_mtp  => nstate := s_opa_mtp;
922
            when others => nstate := s_cpufail;
923
          end case;
924
        elsif ID_STAT.do_fork_srcr = '1' then
925
          case ID_STAT.fork_srcr is
926
            when c_fork_srcr_def => nstate := s_srcr_def;
927
            when c_fork_srcr_inc => nstate := s_srcr_inc;
928
            when c_fork_srcr_dec => nstate := s_srcr_dec;
929
            when c_fork_srcr_ind => nstate := s_srcr_ind;
930
            when others => nstate := s_cpufail;
931
          end case;
932
        elsif ID_STAT.do_fork_dstr = '1' then
933
          do_fork_dstr(nstate, ID_STAT);
934
        elsif ID_STAT.do_fork_dsta = '1' then
935
          case ID_STAT.fork_dsta is         -- 2nd dsta fork in s_opa_mtp_pop_w
936
            when c_fork_dsta_def => do_fork_opa(nstate, ID_STAT);
937
            when c_fork_dsta_inc => nstate := s_dsta_inc;
938
            when c_fork_dsta_dec => nstate := s_dsta_dec;
939
            when c_fork_dsta_ind => nstate := s_dsta_ind;
940
            when others => nstate := s_cpufail;
941
          end case;
942
        elsif ID_STAT.do_fork_opg = '1' then
943
          do_fork_opg(nstate, ID_STAT);
944
        elsif ID_STAT.is_res = '1' then
945
          nstate := s_trap_10;           -- do trap 10;
946
        else
947
          nstate := s_cpufail;           -- catch mistakes here...
948
        end if;
949
 
950
  -- source read states -------------------------------------------------------
951
  --   flows:
952
  --     1  (r)    s_srcr_def           req (r)
953
  --               s_srcr_def_w         get (r)
954
  --               -> do_fork_dstr or do_fork_opg
955
  --              
956
  --     2  (r)+   s_srcr_inc           req (r); r+=s
957
  --               s_srcr_inc_w         get (r)
958
  --               -> do_fork_dstr or do_fork_opg
959
  --
960
  --     3  @(r)+  s_srcr_inc           req (r); r+=s
961
  --               s_srcr_inc_w         get (r)
962
  --               s_srcr_def           req @(r)
963
  --               s_srcr_def_w         get @(r)
964
  --               -> do_fork_dstr or do_fork_opg
965
  --
966
  --     4  -(r)   s_srcr_dec           r-=s
967
  --               s_srcr_dec1          req (r)
968
  --               s_srcr_inc_w         get (r)
969
  --               -> do_fork_dstr or do_fork_opg
970
  --
971
  --     5  @-(r)  s_srcr_dec           r-=s
972
  --               s_srcr_dec1          req (r)
973
  --               s_srcr_inc_w         get (r)
974
  --               s_srcr_def           req @(r)
975
  --               s_srcr_def_w         get @(r)
976
  --               -> do_fork_dstr or do_fork_opg
977
  --
978
  --     6  n(r)   s_srcr_ind           req n
979
  --               s_srcr_ind1_w        get n; ea=r+n
980
  --               s_srcr_ind2          req n(r)
981
  --               s_srcr_ind2_w        get n(r)
982
  --               -> do_fork_dstr or do_fork_opg
983
  --
984
  --     7  @n(r)  s_srcr_ind           req n
985
  --               s_srcr_ind1_w        get n; ea=r+n
986
  --               s_srcr_ind2          req n(r)
987
  --               s_srcr_ind2_w        get n(r)
988
  --               s_srcr_def           req @n(r)
989
  --               s_srcr_def_w         get @n(r)
990
  --               -> do_fork_dstr or do_fork_opg
991
 
992
      when s_srcr_def =>
993
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_dsrc; -- VA = DSRC
994
        do_memread_d(nstate, nvmcntl, s_srcr_def_w,
995
                     bytop=>R_IDSTAT.is_bytop,
996
                     is_pci=>R_IDSTAT.is_srcpcmode1);
997
 
998
      when s_srcr_def_w =>
999
        nstate := s_srcr_def_w;
1000
        do_memcheck(nstate, nstatus, imemok);
1001
        ndpcntl.dres_sel := c_dpath_res_vmdout;  -- DRES = VMDOUT
1002
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;    -- DSRC = DRES
1003
        if imemok then
1004
          ndpcntl.dsrc_we := '1';                -- update DSRC
1005
          if R_IDSTAT.do_fork_dstr = '1' then
1006
            do_fork_dstr(nstate, R_IDSTAT);
1007
          else
1008
            do_fork_opg(nstate, R_IDSTAT);
1009
          end if;
1010
        end if;
1011
 
1012
      when s_srcr_inc =>
1013 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dsrc;  -- OUNIT A=DSRC
1014 2 wfjm
        do_const_opsize(ndpcntl, R_IDSTAT.is_bytop, SRCDEF, SRCREG);
1015 8 wfjm
        ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B=const
1016
        ndpcntl.dres_sel := c_dpath_res_ounit;    -- DRES = OUNIT
1017 2 wfjm
        ndpcntl.gpr_adst := SRCREG;
1018
        ndpcntl.gpr_we := '1';
1019
        nmmumoni.regmod := '1';
1020
        nmmumoni.isdec := '0';
1021
        ndpcntl.ddst_sel := c_dpath_ddst_res;    -- DDST = DRES (for if)
1022
        if DSTREG = SRCREG then                  -- prevent stale DDST copy 
1023
          ndpcntl.ddst_we := '1';                -- update DDST
1024
        end if;
1025
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_dsrc; -- VA = DSRC
1026
        bytop := R_IDSTAT.is_bytop and not SRCDEF;
1027
        do_memread_d(nstate, nvmcntl, s_srcr_inc_w,
1028
                     bytop=>bytop, is_pci=>R_IDSTAT.is_srcpc);
1029
 
1030
      when s_srcr_inc_w =>
1031
        nstate := s_srcr_inc_w;
1032
        ndpcntl.dres_sel := c_dpath_res_vmdout;  -- DRES = VMDOUT
1033
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;    -- DSRC = DRES
1034
        do_memcheck(nstate, nstatus, imemok);
1035
        if imemok then
1036
          ndpcntl.dsrc_we := '1';                -- update DSRC
1037
          if SRCDEF = '1' then
1038
            nstate := s_srcr_def;
1039
          else
1040
            if R_IDSTAT.do_fork_dstr = '1' then
1041
              do_fork_dstr(nstate, R_IDSTAT);
1042
            else
1043
              do_fork_opg(nstate, R_IDSTAT);
1044
            end if;
1045
          end if;
1046
        end if;
1047
 
1048
      when s_srcr_dec =>
1049 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dsrc; -- OUNIT A=DSRC
1050 2 wfjm
        do_const_opsize(ndpcntl, R_IDSTAT.is_bytop, SRCDEF, SRCREG);
1051 8 wfjm
        ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B=const
1052
        ndpcntl.ounit_opsub := '1';              -- OUNIT = A-B
1053
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1054 2 wfjm
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;    -- DSRC = DRES
1055
        ndpcntl.dsrc_we := '1';                  -- update DSRC
1056
        ndpcntl.gpr_adst := SRCREG;
1057
        ndpcntl.gpr_we := '1';
1058
        nmmumoni.regmod := '1';
1059
        nmmumoni.isdec := '1';
1060
        ndpcntl.ddst_sel := c_dpath_ddst_res;    -- DDST = DRES (for if)
1061
        if DSTREG = SRCREG then                  -- prevent stale DDST copy
1062
          ndpcntl.ddst_we := '1';                -- update DDST
1063
        end if;
1064
        nstate := s_srcr_dec1;
1065
 
1066
      when s_srcr_dec1 =>
1067
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_dsrc; -- VA = DSRC
1068
        bytop := R_IDSTAT.is_bytop and not SRCDEF;
1069
        do_memread_d(nstate, nvmcntl, s_srcr_inc_w, bytop=>bytop);
1070
 
1071
      when s_srcr_ind =>
1072
        do_memread_i(nstate, ndpcntl, nvmcntl, s_srcr_ind1_w);
1073
 
1074
      when s_srcr_ind1_w =>
1075
        nstate := s_srcr_ind1_w;
1076
        if R_IDSTAT.is_srcpc = '0' then
1077 8 wfjm
          ndpcntl.ounit_asel := c_ounit_asel_dsrc; -- OUNIT A = DSRC
1078 2 wfjm
        else
1079 8 wfjm
          ndpcntl.ounit_asel := c_ounit_asel_pc;   -- OUNIT A = PC (for nn(pc))
1080 2 wfjm
        end if;
1081 8 wfjm
        ndpcntl.ounit_bsel := c_ounit_bsel_vmdout; -- OUNIT B = VMDOUT
1082
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1083 2 wfjm
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;    -- DSRC = DRES
1084
        ndpcntl.ddst_sel := c_dpath_ddst_dst;    -- DDST = R(DST)
1085
        do_memcheck(nstate, nstatus, imemok);
1086
        if imemok then
1087
          ndpcntl.dsrc_we := '1';                -- update DSRC
1088
          ndpcntl.ddst_we := '1';                -- update DDST (to reload PC)
1089
          nstate := s_srcr_ind2;
1090
        end if;
1091
 
1092
      when s_srcr_ind2 =>
1093
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_dsrc; -- VA = DSRC
1094
        bytop := R_IDSTAT.is_bytop and not SRCDEF;
1095
        do_memread_d(nstate, nvmcntl, s_srcr_ind2_w, bytop=>bytop);
1096
 
1097
      when s_srcr_ind2_w =>
1098
        nstate := s_srcr_ind2_w;
1099
        ndpcntl.dres_sel := c_dpath_res_vmdout;  -- DRES = VMDOUT
1100
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;    -- DSRC = DRES
1101
        do_memcheck(nstate, nstatus, imemok);
1102
        if imemok then
1103
          ndpcntl.dsrc_we := '1';                -- update DSRC
1104
          if SRCDEF = '1' then
1105
            nstate := s_srcr_def;
1106
          else
1107
            if R_IDSTAT.do_fork_dstr = '1' then
1108
              do_fork_dstr(nstate, R_IDSTAT);
1109
            else
1110
              do_fork_opg(nstate, R_IDSTAT);
1111
            end if;
1112
          end if;
1113
        end if;
1114
 
1115
  -- destination read states --------------------------------------------------
1116
  --   flows:
1117
  --     1  (r)    s_dstr_def           req (r) (rmw if rmw op)
1118
  --               s_dstr_def_w         get (r)
1119
  --               -> do_fork_opg
1120
  --              
1121
  --     2  (r)+   s_dstr_inc           req (r); r+=s (rmw if rmw op)
1122
  --               s_dstr_inc_w         get (r)
1123
  --               -> do_fork_opg
1124
  --
1125
  --     3  @(r)+  s_dstr_inc           req (r); r+=s
1126
  --               s_dstr_inc_w         get (r)
1127
  --               s_dstr_def           req @(r) (rmw if rmw op)
1128
  --               s_dstr_def_w         get @(r)
1129
  --               -> do_fork_opg
1130
  --
1131
  --     4  -(r)   s_dstr_dec           r-=s
1132
  --               s_dstr_dec1          req (r) (rmw if rmw op)
1133
  --               s_dstr_inc_w         get (r)
1134
  --               -> do_fork_opg
1135
  --
1136
  --     5  @-(r)  s_dstr_dec           r-=s
1137
  --               s_dstr_dec1          req (r)
1138
  --               s_dstr_inc_w         get (r)
1139
  --               s_dstr_def           req @(r) (rmw if rmw op)
1140
  --               s_dstr_def_w         get @(r)
1141
  --               -> do_fork_opg
1142
  --
1143
  --     6  n(r)   s_dstr_ind           req n
1144
  --               s_dstr_ind1_w        get n; ea=r+n
1145
  --               s_dstr_ind2          req n(r) (rmw if rmw op)
1146
  --               s_dstr_ind2_w        get n(r)
1147
  --               -> do_fork_opg
1148
  --
1149
  --     7  @n(r)  s_dstr_ind           req n
1150
  --               s_dstr_ind1_w        get n; ea=r+n
1151
  --               s_dstr_ind2          req n(r)
1152
  --               s_dstr_ind2_w        get n(r)
1153
  --               s_dstr_def           req @n(r) (rmw if rmw op)
1154
  --               s_dstr_def_w         get @n(r)
1155
  --               -> do_fork_opg
1156
 
1157
      when s_dstr_def =>
1158
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst; -- VA = DDST
1159
        do_memread_d(nstate, nvmcntl, s_dstr_def_w,
1160
                     bytop=>R_IDSTAT.is_bytop, macc=>R_IDSTAT.is_rmwop);
1161
 
1162
      when s_dstr_def_w =>
1163
        nstate := s_dstr_def_w;
1164
        do_memcheck(nstate, nstatus, imemok);
1165
        ndpcntl.dres_sel := c_dpath_res_vmdout;  -- DRES = VMDOUT
1166
        ndpcntl.ddst_sel := c_dpath_ddst_res;    -- DDST = DRES
1167
        if imemok then
1168
          ndpcntl.ddst_we := '1';                -- update DDST
1169
          do_fork_opg(nstate, R_IDSTAT);
1170
        end if;
1171
 
1172
      when s_dstr_inc =>
1173 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst; -- OUNIT A=DDST
1174 2 wfjm
        do_const_opsize(ndpcntl, R_IDSTAT.is_bytop, DSTDEF, DSTREG);
1175 8 wfjm
        ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B=const
1176
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1177 2 wfjm
        ndpcntl.gpr_adst := DSTREG;
1178
        ndpcntl.gpr_we := '1';
1179
        nmmumoni.regmod := '1';
1180
        nmmumoni.isdec := '0';
1181
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst; -- VA = DDST
1182
        macc  := R_IDSTAT.is_rmwop and not DSTDEF;
1183
        bytop := R_IDSTAT.is_bytop and not DSTDEF;
1184
        do_memread_d(nstate, nvmcntl, s_dstr_inc_w,
1185
                     bytop=>bytop, macc=>macc, is_pci=>R_IDSTAT.is_dstpc);
1186
 
1187
      when s_dstr_inc_w =>
1188
        nstate := s_dstr_inc_w;
1189
        ndpcntl.dres_sel := c_dpath_res_vmdout;  -- DRES = VMDOUT
1190
        ndpcntl.ddst_sel := c_dpath_ddst_res;    -- DDST = DRES
1191
        do_memcheck(nstate, nstatus, imemok);
1192
        if imemok then
1193
          ndpcntl.ddst_we := '1';                -- update DDST
1194
          if DSTDEF = '1' then
1195
            nstate := s_dstr_def;
1196
          else
1197
            do_fork_opg(nstate, R_IDSTAT);
1198
          end if;
1199
        end if;
1200
 
1201
      when s_dstr_dec =>
1202 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst; -- OUNIT A=DDST
1203 2 wfjm
        do_const_opsize(ndpcntl, R_IDSTAT.is_bytop, DSTDEF, DSTREG);
1204 8 wfjm
        ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B=const
1205
        ndpcntl.ounit_opsub := '1';              -- OUNIT = A-B
1206
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1207 2 wfjm
        ndpcntl.ddst_sel := c_dpath_ddst_res;    -- DDST = DRES
1208
        ndpcntl.ddst_we := '1';                  -- update DDST
1209
        ndpcntl.gpr_adst := DSTREG;
1210
        ndpcntl.gpr_we := '1';
1211
        nmmumoni.regmod := '1';
1212
        nmmumoni.isdec := '1';
1213
        nstate := s_dstr_dec1;
1214
 
1215
      when s_dstr_dec1 =>
1216
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst; -- VA = DDST
1217
        macc  := R_IDSTAT.is_rmwop and not DSTDEF;
1218
        bytop := R_IDSTAT.is_bytop and not DSTDEF;
1219
        do_memread_d(nstate, nvmcntl, s_dstr_inc_w,
1220
                     bytop=>bytop, macc=>macc);
1221
 
1222
      when s_dstr_ind =>
1223
        do_memread_i(nstate, ndpcntl, nvmcntl, s_dstr_ind1_w);
1224
 
1225
      when s_dstr_ind1_w =>
1226
        nstate := s_dstr_ind1_w;
1227
        if R_IDSTAT.is_dstpc = '0' then
1228 8 wfjm
          ndpcntl.ounit_asel := c_ounit_asel_ddst; -- OUNIT A = DDST
1229 2 wfjm
        else
1230 8 wfjm
          ndpcntl.ounit_asel := c_ounit_asel_pc;   -- OUNIT A = PC (for nn(pc))
1231 2 wfjm
        end if;
1232 8 wfjm
        ndpcntl.ounit_bsel := c_ounit_bsel_vmdout;-- OUNIT B = VMDOUT
1233
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1234 2 wfjm
        ndpcntl.ddst_sel := c_dpath_ddst_res;    -- DDST = DRES
1235
        do_memcheck(nstate, nstatus, imemok);
1236
        if imemok then
1237
          ndpcntl.ddst_we := '1';                -- update DDST
1238
          nstate := s_dstr_ind2;
1239
        end if;
1240
 
1241
      when s_dstr_ind2 =>
1242
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst; -- VA = DDST
1243
        macc  := R_IDSTAT.is_rmwop and not DSTDEF;
1244
        bytop := R_IDSTAT.is_bytop and not DSTDEF;
1245
        do_memread_d(nstate, nvmcntl, s_dstr_ind2_w,
1246
                     bytop=>bytop, macc=>macc);
1247
 
1248
      when s_dstr_ind2_w =>
1249
        nstate := s_dstr_ind2_w;
1250
        ndpcntl.dres_sel := c_dpath_res_vmdout;  -- DRES = VMDOUT
1251
        ndpcntl.ddst_sel := c_dpath_ddst_res;    -- DDST = DRES
1252
        do_memcheck(nstate, nstatus, imemok);
1253
        if imemok then
1254
          ndpcntl.ddst_we := '1';                -- update DDST
1255
          if DSTDEF = '1' then
1256
            nstate := s_dstr_def;
1257
          else
1258
            do_fork_opg(nstate, R_IDSTAT);
1259
          end if;
1260
        end if;
1261
 
1262
  -- destination write states -------------------------------------------------
1263
  --   flows:
1264
  --     1  (r)    s_dstw_def           wreq (r)            check kstack
1265
  --               s_dstw_def_w         ack  (r)
1266
  --               -> do_fork_next
1267
  --              
1268
  --     2  (r)+   s_dstw_inc           wreq (r)            check kstack
1269
  --               s_dstw_inc_w         ack  (r); r+=s
1270
  --               -> do_fork_next
1271
  --
1272
  --     3  @(r)+  s_dstw_inc           rreq (r); r+=s
1273
  --               s_dstw_incdef_w      get  (r)
1274
  --               s_dstw_def246        wreq @(r)
1275
  --               s_dstw_def_w         ack  @(r)
1276
  --               -> do_fork_next
1277
  --
1278
  --     4  -(r)   s_dstw_dec           r-=s
1279
  --               s_dstw_dec1          wreq (r)            check kstack
1280
  --               s_dstw_def_w         ack  (r)
1281
  --               -> do_fork_next
1282
  --
1283
  --     5  @-(r)  s_dstw_dec           r-=s
1284
  --               s_dstw_dec1          rreq (r)
1285
  --               s_dstw_incdef_w      get  (r)
1286
  --               s_dstw_def246        wreq @(r)
1287
  --               s_dstw_def_w         ack  @(r)
1288
  --               -> do_fork_next
1289
  --
1290
  --     6  n(r)   s_dstw_ind           rreq n
1291
  --               s_dstw_ind_w         get  n; ea=r+n
1292
  --               s_dstw_dec1          wreq n(r)           check kstack
1293
  --               s_dstw_def_w         ack  n(r)
1294
  --               -> do_fork_next
1295
  --
1296
  --     7  @n(r)  s_dstw_ind           rreq n
1297
  --               s_dstw_ind_w         get  n; ea=r+n
1298
  --               s_dstw_dec1          rreq n(r)
1299
  --               s_dstw_incdef_w      get  n(r)
1300
  --               s_dstw_def246        wreq @n(r)
1301
  --               s_dstw_def_w         ack  @n(r)
1302
  --               -> do_fork_next
1303
 
1304
      when s_dstw_def =>
1305
        ndpcntl.psr_ccwe := '1';
1306
        ndpcntl.dres_sel := R_IDSTAT.res_sel;      -- DRES = choice of idec
1307
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst; -- VA = DDST
1308
        nvmcntl.kstack := is_dstkstack1246;
1309
        do_memwrite(nstate, nvmcntl, s_dstw_def_w);
1310
 
1311
      when s_dstw_def_w =>
1312
        nstate := s_dstw_def_w;
1313
        do_memcheck(nstate, nstatus, imemok);
1314
        if imemok then
1315 34 wfjm
          idm_idone := '1';                        -- instruction done
1316
          do_fork_next(nstate, nstatus, nmmumoni);  -- fetch next
1317 2 wfjm
        end if;
1318
 
1319
      when s_dstw_inc =>
1320
        ndpcntl.psr_ccwe := '1';
1321
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst;   -- VA = DDST
1322 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst;     -- OUNIT A=DDST  (for else)
1323 2 wfjm
        do_const_opsize(ndpcntl, R_IDSTAT.is_bytop, DSTDEF, DSTREG);  --(...)
1324 8 wfjm
        ndpcntl.ounit_bsel := c_ounit_bsel_const;    -- OUNIT B=const (for else)
1325 2 wfjm
        if DSTDEF = '0' then
1326
          ndpcntl.dres_sel := R_IDSTAT.res_sel;      -- DRES = choice of idec
1327
          nvmcntl.kstack := is_dstkstack1246;
1328
          do_memwrite(nstate, nvmcntl, s_dstw_inc_w);
1329
          nstatus.do_gprwe := '1';
1330
        else
1331 8 wfjm
          ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
1332 2 wfjm
          ndpcntl.gpr_adst := DSTREG;
1333
          ndpcntl.gpr_we := '1';
1334
          nmmumoni.regmod := '1';
1335
          nmmumoni.isdec := '0';
1336
          do_memread_d(nstate, nvmcntl, s_dstw_incdef_w,
1337
                       is_pci=>R_IDSTAT.is_dstpc);
1338
        end if;
1339
 
1340
      when s_dstw_inc_w =>
1341
        nstate := s_dstw_inc_w;
1342 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst;   -- OUNIT A=DDST
1343 2 wfjm
        do_const_opsize(ndpcntl, R_IDSTAT.is_bytop, DSTDEF, DSTREG);
1344 8 wfjm
        ndpcntl.ounit_bsel := c_ounit_bsel_const;  -- OUNIT B=const
1345
        ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
1346 2 wfjm
        ndpcntl.gpr_adst := DSTREG;
1347
        if R_STATUS.do_gprwe = '1' then
1348
          nmmumoni.regmod := '1';
1349
          nmmumoni.isdec := '0';
1350
          nmmumoni.trace_prev := '1';              -- ssr freeze of prev state
1351
          ndpcntl.gpr_we := '1';                   -- update DST reg
1352
        end if;
1353
        nstatus.do_gprwe := '0';
1354
        do_memcheck(nstate, nstatus, imemok);
1355
        if imemok then
1356 34 wfjm
          idm_idone := '1';                        -- instruction done
1357
          do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
1358 2 wfjm
        end if;
1359
 
1360
      when s_dstw_incdef_w =>
1361
        nstate := s_dstw_incdef_w;
1362
        ndpcntl.dres_sel := c_dpath_res_vmdout;  -- DRES = VMDOUT
1363
        ndpcntl.ddst_sel := c_dpath_ddst_res;    -- DDST = DRES
1364
        do_memcheck(nstate, nstatus, imemok);
1365
        if imemok then
1366
          ndpcntl.ddst_we := '1';                -- update DDST
1367
          nstate := s_dstw_def246;
1368
        end if;
1369
 
1370
      when s_dstw_dec =>
1371
        ndpcntl.psr_ccwe := '1';
1372 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst; -- OUNIT A=DDST
1373 2 wfjm
        do_const_opsize(ndpcntl, R_IDSTAT.is_bytop, DSTDEF, DSTREG);
1374 8 wfjm
        ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B=const
1375
        ndpcntl.ounit_opsub := '1';              -- OUNIT = A-B
1376
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1377 2 wfjm
        ndpcntl.ddst_sel := c_dpath_ddst_res;    -- DDST = DRES
1378
        ndpcntl.ddst_we := '1';                  -- update DDST
1379
        ndpcntl.gpr_adst := DSTREG;
1380
        ndpcntl.gpr_we := '1';
1381
        nmmumoni.regmod := '1';
1382
        nmmumoni.isdec := '1';
1383
        nstate := s_dstw_dec1;
1384
 
1385
      when s_dstw_dec1 =>
1386
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst; -- VA = DDST
1387
        ndpcntl.dres_sel := R_IDSTAT.res_sel;      -- DRES = from idec (for if)
1388
        if DSTDEF = '0' then
1389
          nvmcntl.kstack := is_dstkstack1246;
1390
          do_memwrite(nstate, nvmcntl, s_dstw_def_w);
1391
        else
1392
          do_memread_d(nstate, nvmcntl, s_dstw_incdef_w);
1393
        end if;
1394
 
1395
      when s_dstw_ind =>
1396
        ndpcntl.psr_ccwe := '1';
1397
        do_memread_i(nstate, ndpcntl, nvmcntl, s_dstw_ind_w);
1398
 
1399
      when s_dstw_ind_w =>
1400
        nstate := s_dstw_ind_w;
1401
        if R_IDSTAT.is_dstpc = '0' then
1402 8 wfjm
          ndpcntl.ounit_asel := c_ounit_asel_ddst; -- OUNIT A = DDST
1403 2 wfjm
        else
1404 8 wfjm
          ndpcntl.ounit_asel := c_ounit_asel_pc;   -- OUNIT A = PC (for nn(pc))
1405 2 wfjm
        end if;
1406 8 wfjm
        ndpcntl.ounit_bsel := c_ounit_bsel_vmdout;-- OUNIT B = VMDOUT
1407
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1408 2 wfjm
        ndpcntl.ddst_sel := c_dpath_ddst_res;    -- DDST = DRES
1409
        do_memcheck(nstate, nstatus, imemok);
1410
        if imemok then
1411
          ndpcntl.ddst_we := '1';                -- update DDST
1412
          nstate := s_dstw_dec1;
1413
        end if;
1414
 
1415
      when s_dstw_def246 =>
1416
        ndpcntl.dres_sel := R_IDSTAT.res_sel;      -- DRES = choice of idec
1417
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst; -- VA = DDST
1418
        do_memwrite(nstate, nvmcntl, s_dstw_def_w);
1419
 
1420
  -- destination address states -----------------------------------------------
1421
  --   flows:
1422
  --     1  (r)    -> do_fork_opa
1423
  --              
1424
  --     2  (r)+   s_dsta_inc           r+=2
1425
  --               -> do_fork_opa
1426
  --
1427
  --     3  @(r)+  s_dsta_inc           req (r); r+=s
1428
  --               s_dsta_incdef_w      get (r)
1429
  --               -> do_fork_opa
1430
  --
1431
  --     4  -(r)   s_dsta_dec           r-=s
1432
  --               s_dsta_dec1          ?? FIXME ?? what is done here ??
1433
  --               -> do_fork_opa
1434
  --
1435
  --     5  @-(r)  s_dsta_dec           r-=s
1436
  --               s_dsta_dec1          req (r)
1437
  --               s_dsta_incdef_w      get (r)
1438
  --               -> do_fork_opa
1439
  --
1440
  --     6  n(r)   s_dsta_ind           req n
1441
  --               s_dsta_ind_w         get n; ea=r+n
1442
  --               s_dsta_dec1          ?? FIXME ?? what is done here ??
1443
  --               -> do_fork_opa
1444
  --
1445
  --     7  @n(r)  s_dsta_ind           req n
1446
  --               s_dsta_ind_w         get n; ea=r+n
1447
  --               s_dsta_dec1          req n(r)
1448
  --               s_dsta_incdef_w      get n(r)
1449
  --               -> do_fork_opa
1450
 
1451
      when s_dsta_inc =>
1452 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst;   -- OUNIT A=DDST
1453
        ndpcntl.ounit_const := "000000010";
1454
        ndpcntl.ounit_bsel := c_ounit_bsel_const;  -- OUNIT B=const(2)
1455
        ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
1456 2 wfjm
        ndpcntl.gpr_adst := DSTREG;
1457
        ndpcntl.gpr_we := '1';
1458
        nmmumoni.regmod := '1';
1459
        nmmumoni.isdec := '0';
1460
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;      -- DSRC = DRES (for if)
1461
        if R_IDSTAT.updt_dstadsrc = '1' then       -- prevent stale DSRC copy 
1462
          ndpcntl.dsrc_we := '1';                    -- update DSRC
1463
        end if;
1464
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst; -- VA = DDST
1465
        if DSTDEF = '0' then
1466
          do_fork_opa(nstate, R_IDSTAT);
1467
        else
1468
          do_memread_d(nstate, nvmcntl, s_dsta_incdef_w,
1469
                       is_pci=>R_IDSTAT.is_dstpc);
1470
        end if;
1471
 
1472
      when s_dsta_incdef_w =>
1473
        nstate := s_dsta_incdef_w;
1474
        ndpcntl.dres_sel := c_dpath_res_vmdout;  -- DRES = VMDOUT
1475
        ndpcntl.ddst_sel := c_dpath_ddst_res;    -- DDST = DRES
1476
        do_memcheck(nstate, nstatus, imemok);
1477
        if imemok then
1478
          ndpcntl.ddst_we := '1';                -- update DDST
1479
          do_fork_opa(nstate, R_IDSTAT);
1480
        end if;
1481
 
1482
      when s_dsta_dec =>
1483 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst; -- OUNIT A=DDST
1484
        ndpcntl.ounit_const := "000000010";
1485
        ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B=const(2)
1486
        ndpcntl.ounit_opsub := '1';              -- OUNIT = A-B
1487
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1488 2 wfjm
        ndpcntl.ddst_sel := c_dpath_ddst_res;    -- DDST = DRES
1489
        ndpcntl.ddst_we := '1';                  -- update DDST
1490
        ndpcntl.gpr_adst := DSTREG;
1491
        ndpcntl.gpr_we := '1';
1492
        nmmumoni.regmod := '1';
1493
        nmmumoni.isdec := '1';
1494
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;    -- DSRC = DRES (for if)
1495
        if R_IDSTAT.updt_dstadsrc = '1' then     -- prevent stale DSRC copy 
1496
          ndpcntl.dsrc_we := '1';                -- update DSRC
1497
        end if;
1498
        nstate := s_dsta_dec1;
1499
 
1500
      when s_dsta_dec1 =>
1501
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst; -- VA = DDST
1502
        if DSTDEF = '0' then                       -- check here used also by
1503
          do_fork_opa(nstate, R_IDSTAT);           -- s_dsta_ind flow !!
1504
        else
1505
          do_memread_d(nstate, nvmcntl, s_dsta_incdef_w);
1506
        end if;
1507
 
1508
      when s_dsta_ind =>
1509
        do_memread_i(nstate, ndpcntl, nvmcntl, s_dsta_ind_w);
1510
 
1511
      when s_dsta_ind_w =>
1512
        nstate := s_dsta_ind_w;
1513
        if R_IDSTAT.is_dstpc = '0' then
1514 8 wfjm
          ndpcntl.ounit_asel := c_ounit_asel_ddst; -- OUNIT A = DDST
1515 2 wfjm
        else
1516 8 wfjm
          ndpcntl.ounit_asel := c_ounit_asel_pc;   -- OUNIT A = PC (for nn(pc))
1517 2 wfjm
        end if;
1518 8 wfjm
        ndpcntl.ounit_bsel := c_ounit_bsel_vmdout;-- OUNIT B = VMDOUT
1519
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1520 2 wfjm
        ndpcntl.ddst_sel := c_dpath_ddst_res;    -- DDST = DRES
1521
        do_memcheck(nstate, nstatus, imemok);
1522
        if imemok then
1523
          ndpcntl.ddst_we := '1';                -- update DDST
1524
          nstate := s_dsta_dec1;
1525
        end if;
1526
 
1527
  -- instruction operate states -----------------------------------------------
1528
 
1529
      when s_op_halt =>                 -- HALT
1530 34 wfjm
        idm_idone := '1';               -- instruction done
1531 2 wfjm
        if is_kmode = '1' then          -- if in kernel mode execute
1532
          nmmumoni.idone := '1';
1533
          nstatus.cpugo := '0';
1534
          nstatus.cpurust := c_cpurust_halt;
1535
          nstate := s_idle;
1536
        else                            -- otherwise trap
1537
          ncpuerr.illhlt := '1';
1538
          nstate := s_trap_4;           -- trap 4 like 11/70
1539
        end if;
1540
 
1541
      when s_op_wait =>                 -- WAIT
1542 29 wfjm
        ndpcntl.gpr_asrc := "000";      -- load R0 in DSRC for DR emulation
1543
        ndpcntl.dsrc_sel := c_dpath_dsrc_src;
1544
        ndpcntl.dsrc_we := '1';
1545 30 wfjm
 
1546 2 wfjm
        nstate := s_op_wait;            -- spin here
1547
        if is_kmode = '0' then          -- but act as nop if not in kernel
1548
          nstate := s_idle;
1549
        elsif int_pending = '1' or      -- bail out if pending interrupt
1550
          R_STATUS.cpustep='1' then     --  or the instruction is only stepped
1551
          nstate := s_idle;
1552
        elsif R_STATUS.cmdbusy = '1' then -- suspend if a cp command is pending
1553
          nstatus.waitsusp := '1';
1554
          nstate := s_idle;
1555
        else
1556
          nstatus.cpuwait := '1';       -- if spinning here, signal with cpuwait
1557 30 wfjm
          nstatus.itimer  := '1';       -- itimer will stay 1 during a WAIT
1558
       end if;
1559 2 wfjm
 
1560
      when s_op_trap =>                 -- traps
1561 34 wfjm
        idm_idone := '1';                      -- instruction done
1562 2 wfjm
        lvector := "0000" & R_IDSTAT.trap_vec; -- vector
1563
        do_start_int(nstate, ndpcntl, lvector);
1564
 
1565
      when s_op_reset =>                -- RESET
1566
        if is_kmode = '1' then          -- if in kernel mode execute
1567 30 wfjm
          nstatus.breset := '1';          -- issue bus reset
1568 2 wfjm
        end if;
1569
        nstate := s_idle;
1570
 
1571
      when s_op_rts =>                  -- RTS
1572 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst;   -- OUNIT A=DDST
1573
        ndpcntl.ounit_bsel := c_ounit_bsel_const;  -- OUNIT B=const(0)
1574
        ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
1575 2 wfjm
        ndpcntl.gpr_adst := c_gpr_pc;
1576
        ndpcntl.gpr_we := '1';                     -- load PC with reg(dst)
1577
        nstate := s_op_rts_pop;
1578
 
1579
      when s_op_rts_pop =>
1580
        do_memread_srcinc(nstate, ndpcntl, nvmcntl, s_op_rts_pop_w,
1581
                          nmmumoni, updt_sp=>'1');
1582
 
1583
      when s_op_rts_pop_w =>
1584
        nstate := s_op_rts_pop_w;
1585
        ndpcntl.dres_sel := c_dpath_res_vmdout;   -- DRES = VMDOUT
1586
        ndpcntl.gpr_adst := DSTREG;
1587
        do_memcheck(nstate, nstatus, imemok);
1588
        if imemok then
1589
          ndpcntl.gpr_we := '1';                  -- load R with (SP)+
1590 34 wfjm
          idm_idone := '1';                       -- instruction done
1591
          do_fork_next(nstate, nstatus, nmmumoni);  -- fetch next
1592 2 wfjm
        end if;
1593
 
1594
      when s_op_spl =>                  -- SPL
1595
        ndpcntl.dres_sel := c_dpath_res_ireg;    -- DRES = IREG
1596
        ndpcntl.psr_func := c_psr_func_wspl;
1597 34 wfjm
        idm_idone := '1';                        -- instruction done
1598 2 wfjm
        if is_kmode = '1' then                   -- active only in kernel mode
1599
          ndpcntl.psr_we := '1';
1600
          nstate := s_ifetch;                    -- unconditionally fetch next
1601
                                                 -- instruction like a 11/70
1602
                                                 -- no interrupt recognition !
1603
        else
1604
          do_fork_next(nstate, nstatus, nmmumoni);  -- in non-kernel, noop
1605
        end if;
1606
 
1607
      when s_op_mcc =>                  -- CLx/SEx
1608
        ndpcntl.dres_sel := c_dpath_res_ireg;    -- DRES = IREG
1609
        ndpcntl.psr_func := c_psr_func_wcc;
1610
        ndpcntl.psr_we := '1';
1611 34 wfjm
        idm_idone := '1';                        -- instruction done
1612
        do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
1613 2 wfjm
 
1614
      when s_op_br =>                   -- BR
1615
        nvmcntl.dspace := '0';                   -- prepare do_fork_next_pref
1616
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_pc; -- VA = PC
1617 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_pc;   -- OUNIT A = PC
1618
        ndpcntl.ounit_bsel := c_ounit_bsel_ireg8;-- OUNIT B = IREG8
1619
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1620 2 wfjm
        -- note: cc are NZVC
1621
        case brcode(3 downto 1) is
1622
          when "000" =>                 -- BR
1623
            brcond := '1';
1624
          when "001" =>                 -- BNE/BEQ: if Z = x
1625
            brcond := PSW.cc(2);
1626
          when "010" =>                 -- BGE/BLT: if N xor V = x
1627
            brcond := PSW.cc(3) xor PSW.cc(1);
1628
          when "011" =>                 -- BGT/BLE: if Z or (N xor V) = x
1629
            brcond := PSW.cc(2) or (PSW.cc(3) xor PSW.cc(1));
1630
          when "100" =>                 -- BPL/BMI: if N = x
1631
            brcond := PSW.cc(3);
1632
          when "101" =>                 -- BHI/BLOS:if C or Z = x
1633
            brcond := PSW.cc(2) or PSW.cc(0);
1634
          when "110" =>                 -- BVC/BVS: if V = x
1635
            brcond := PSW.cc(1);
1636
          when "111" =>                 -- BCC/BCS: if C = x
1637
            brcond := PSW.cc(0);
1638
          when others => null;
1639
        end case;
1640
 
1641
        ndpcntl.gpr_adst := c_gpr_pc;
1642 34 wfjm
        idm_idone := '1';               -- instruction done
1643 2 wfjm
        if brcond = brcode(0) then      -- this coding creates redundant code
1644
          ndpcntl.gpr_we := '1';        --   but synthesis optimizes this way !
1645
          do_fork_next(nstate, nstatus, nmmumoni);
1646
        else
1647
          do_fork_next_pref(nstate, nstatus, ndpcntl, nvmcntl, nmmumoni);
1648
        end if;
1649
 
1650
      when s_op_mark =>                 -- MARK 
1651 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_pc;   -- OUNIT A = PC
1652
        ndpcntl.ounit_bsel := c_ounit_bsel_ireg6;-- OUNIT B = IREG6
1653
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1654 2 wfjm
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;    -- DSRC = DRES
1655
        ndpcntl.dsrc_we := '1';                  -- update DSRC (with PC+2*nn)
1656
        ndpcntl.gpr_adst := c_gpr_r5;            -- fetch r5
1657
        ndpcntl.ddst_sel := c_dpath_ddst_dst;
1658
        ndpcntl.ddst_we := '1';
1659
        nstate := s_op_mark1;
1660
 
1661
      when s_op_mark1 =>
1662 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst; -- OUNIT A = DDST
1663
        ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B = const(0)
1664
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1665 2 wfjm
        ndpcntl.gpr_adst := c_gpr_pc;
1666
        ndpcntl.gpr_we := '1';                   -- load PC with r5
1667
        nstate := s_op_mark_pop;
1668
 
1669
      when s_op_mark_pop =>
1670
        do_memread_srcinc(nstate, ndpcntl, nvmcntl, s_op_mark_pop_w,
1671
                          nmmumoni, updt_sp=>'1');
1672
 
1673
      when s_op_mark_pop_w =>
1674
        nstate := s_op_mark_pop_w;
1675
        ndpcntl.dres_sel := c_dpath_res_vmdout;  -- DRES = VMDOUT
1676
        ndpcntl.gpr_adst := c_gpr_r5;
1677
        do_memcheck(nstate, nstatus, imemok);
1678
        if imemok then
1679
          ndpcntl.gpr_we := '1';                 -- load R5 with (sp)+
1680 34 wfjm
          idm_idone := '1';                      -- instruction done
1681
          do_fork_next(nstate, nstatus, nmmumoni);  -- fetch next
1682 2 wfjm
        end if;
1683
 
1684
      when s_op_sob =>                  -- SOB (dec)
1685
        -- comment fork_next_pref out (blog 2006-10-02) due to synthesis impact
1686
        --nvmcntl.dspace := '0';                   -- prepare do_fork_next_pref
1687
        --ndpcntl.vmaddr_sel := c_dpath_vmaddr_pc; -- VA = PC
1688
        ndpcntl.dres_sel := R_IDSTAT.res_sel;
1689
        ndpcntl.gpr_adst := SRCREG;
1690
        ndpcntl.gpr_we := '1';
1691
 
1692 34 wfjm
        if DP_STAT.ccout_z = '0' then        -- if z=0 branch, if z=1 fall thru
1693 2 wfjm
          nstate := s_op_sob1;
1694
        else
1695
          --do_fork_next_pref(nstate, ndpcntl, nvmcntl, nmmumoni);
1696 34 wfjm
          idm_idone := '1';                  -- instruction done
1697
          do_fork_next(nstate, nstatus, nmmumoni);  -- fetch next
1698 2 wfjm
        end if;
1699
 
1700
      when s_op_sob1 =>                 -- SOB (br) 
1701 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_pc;   -- OUNIT A = PC
1702
        ndpcntl.ounit_bsel := c_ounit_bsel_ireg6;-- OUNIT B = IREG6
1703
        ndpcntl.ounit_opsub := '1';              -- OUNIT = A - B
1704
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1705 2 wfjm
        ndpcntl.gpr_adst := c_gpr_pc;
1706
        ndpcntl.gpr_we := '1';
1707 34 wfjm
        idm_idone := '1';                        -- instruction done
1708
        do_fork_next(nstate, nstatus, nmmumoni);  -- fetch next
1709 2 wfjm
 
1710
      when s_opg_gen =>
1711
        nvmcntl.dspace := '0';                   -- prepare do_fork_next_pref
1712
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_pc; -- VA = PC
1713
        ndpcntl.gpr_bytop := R_IDSTAT.is_bytop;
1714
        ndpcntl.dres_sel := R_IDSTAT.res_sel;    -- DRES = choice of idec
1715
 
1716
        if R_IDSTAT.op_mov = '1' then            -- in case of MOV xx,R
1717
          ndpcntl.gpr_bytop := '0';              --  no bytop, do sign extend
1718
        end if;
1719
 
1720
        ndpcntl.psr_ccwe := '1';
1721
 
1722
        if R_IDSTAT.is_dstw_reg = '1' then
1723
          ndpcntl.gpr_we := '1';
1724
        end if;
1725
 
1726
        if R_IDSTAT.is_rmwop = '1' then
1727
          do_memwrite(nstate, nvmcntl, s_opg_gen_rmw_w, macc=>'1');
1728
        else
1729 34 wfjm
          idm_idone := '1';                      -- instruction done
1730 2 wfjm
          if R_STATUS.prefdone = '1' then
1731
            nstatus.prefdone :='0';
1732
            nstate := s_ifetch_w;
1733
            do_memcheck(nstate, nstatus, imemok);
1734
            if imemok then
1735
              ndpcntl.ireg_we := '1';
1736
              nstate := s_idecode;
1737
            end if;
1738
          else
1739
            if R_IDSTAT.is_dstw_pc = '1' then
1740
              nstate := s_idle;
1741
            else
1742
              do_fork_next_pref(nstate, nstatus, ndpcntl, nvmcntl, nmmumoni);
1743
            end if;
1744
          end if;
1745
        end if;
1746
 
1747
      when s_opg_gen_rmw_w =>
1748
        nstate := s_opg_gen_rmw_w;
1749
        do_memcheck(nstate, nstatus, imemok);
1750
        if imemok then
1751 34 wfjm
          idm_idone := '1';                      -- instruction done
1752
          do_fork_next(nstate, nstatus, nmmumoni); -- fetch next
1753 2 wfjm
        end if;
1754
 
1755
      when s_opg_mul =>                 -- MUL (oper)
1756
        ndpcntl.dres_sel := R_IDSTAT.res_sel;   -- DRES = choice of idec
1757
        ndpcntl.gpr_adst := SRCREG;             -- write high order result
1758
        ndpcntl.gpr_we := '1';
1759
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;   -- DSRC = DRES
1760
        ndpcntl.dsrc_we := '1';                 -- capture high order part
1761
        ndpcntl.dtmp_sel := c_dpath_dtmp_drese; -- DTMP = DRESE
1762
        ndpcntl.dtmp_we := '1';                 -- capture low order part
1763
        nstate := s_opg_mul1;
1764
 
1765
      when s_opg_mul1 =>                -- MUL (write odd reg)
1766 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dtmp; -- OUNIT A = DTMP
1767
        ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B = const(0)
1768
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1769 2 wfjm
        ndpcntl.gpr_adst := SRCREG(2 downto 1) & "1";-- write odd reg !
1770
        ndpcntl.gpr_we := '1';
1771
        ndpcntl.psr_ccwe := '1';
1772 34 wfjm
        idm_idone := '1';                        -- instruction done
1773
        do_fork_next(nstate, nstatus, nmmumoni);  -- fetch next
1774 2 wfjm
 
1775
      when s_opg_div =>                 -- DIV (load dd_low)
1776 8 wfjm
        ndpcntl.munit_s_div := '1';
1777 2 wfjm
        ndpcntl.gpr_asrc := SRCREG(2 downto 1) & "1";-- read odd reg !
1778
        ndpcntl.dtmp_sel := c_dpath_dtmp_dsrc;
1779
        ndpcntl.dtmp_we := '1';
1780
        nstate := s_opg_div_cn;
1781
 
1782
      when s_opg_div_cn =>              -- DIV (1st...16th cycle)
1783 8 wfjm
        ndpcntl.munit_s_div_cn := '1';
1784 2 wfjm
        ndpcntl.dres_sel := R_IDSTAT.res_sel;     -- DRES = choice of idec
1785
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;     -- DSRC = DRES
1786
        ndpcntl.dtmp_sel := c_dpath_dtmp_drese;   -- DTMP = DRESE
1787
        nstate := s_opg_div_cn;
1788 25 wfjm
        if DP_STAT.div_quit = '1' then
1789
          nstate := s_opg_div_quit;
1790 2 wfjm
        else
1791
          ndpcntl.dsrc_we := '1';                 -- update DSRC
1792
          ndpcntl.dtmp_we := '1';                 -- update DTMP
1793
        end if;
1794
        if DP_STAT.shc_tc = '1' then
1795
          nstate := s_opg_div_cr;
1796
        end if;
1797
 
1798 25 wfjm
      when s_opg_div_cr =>              -- DIV (remainder correction)
1799 8 wfjm
        ndpcntl.munit_s_div_cr := '1';
1800 2 wfjm
        ndpcntl.dres_sel := R_IDSTAT.res_sel;     -- DRES = choice of idec
1801
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;     -- DSRC = DRES
1802
        ndpcntl.dsrc_we := DP_STAT.div_cr;        -- update DSRC
1803
        nstate := s_opg_div_sq;
1804
 
1805 25 wfjm
      when s_opg_div_sq =>              -- DIV (correct and store quotient)
1806 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dtmp;  -- OUNIT A=DTMP
1807
        ndpcntl.ounit_const := "00000000"&DP_STAT.div_cq;-- OUNIT const = Q corr.
1808
        ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B=const (q cor)
1809
        ndpcntl.dres_sel := c_dpath_res_ounit;    -- DRES = OUNIT
1810 2 wfjm
        ndpcntl.gpr_adst := SRCREG;               -- write result
1811
        ndpcntl.gpr_we := '1';
1812
        ndpcntl.dtmp_sel := c_dpath_dtmp_dres;    -- DTMP = DRES
1813
        ndpcntl.dtmp_we := '1';                   -- update DTMP (Q)
1814
        nstate := s_opg_div_sr;
1815
 
1816 25 wfjm
      when s_opg_div_sr =>              -- DIV (store remainder)
1817
        ndpcntl.munit_s_div_sr := '1';
1818 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dsrc;  -- OUNIT A=DSRC
1819
        ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B=const (0)
1820
        ndpcntl.dres_sel := c_dpath_res_ounit;    -- DRES = OUNIT
1821 2 wfjm
        ndpcntl.gpr_adst := SRCREG(2 downto 1) & "1";-- write odd reg !
1822
        ndpcntl.gpr_we := '1';
1823
        ndpcntl.psr_ccwe := '1';
1824 25 wfjm
        if DP_STAT.div_quit = '1' then
1825
          nstate := s_opg_div_quit;
1826
        else
1827 34 wfjm
          idm_idone := '1';                       -- instruction done
1828
          do_fork_next(nstate, nstatus, nmmumoni);  -- fetch next
1829 25 wfjm
        end if;
1830
 
1831
      when s_opg_div_quit =>            -- DIV (0/ or /0 or V=1 aborts)
1832 2 wfjm
        ndpcntl.psr_ccwe := '1';
1833 34 wfjm
        idm_idone := '1';               -- instruction done
1834
        do_fork_next(nstate, nstatus, nmmumoni);  -- fetch next
1835 2 wfjm
 
1836
      when s_opg_ash =>                 -- ASH (load shc)
1837 8 wfjm
        ndpcntl.munit_s_ash := '1';
1838 2 wfjm
        nstate := s_opg_ash_cn;
1839
 
1840
      when s_opg_ash_cn =>              -- ASH (shift cycles)
1841
        nvmcntl.dspace := '0';                    -- prepare do_fork_next_pref
1842
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;     -- DSRC = DRES
1843 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dsrc;  -- OUNIT A=DSRC
1844
        ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B=const(0)
1845 2 wfjm
        ndpcntl.gpr_adst := SRCREG;               -- write result
1846 8 wfjm
        ndpcntl.munit_s_ash_cn := '1';
1847 2 wfjm
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_pc;  -- VA = PC
1848
        nstate := s_opg_ash_cn;
1849
        if DP_STAT.shc_tc = '0' then
1850
          ndpcntl.dres_sel := R_IDSTAT.res_sel;   -- DRES = choice of idec
1851
          ndpcntl.dsrc_we := '1';                 -- update DSRC
1852
        else
1853 8 wfjm
          ndpcntl.dres_sel := c_dpath_res_ounit;  -- DRES = OUNIT
1854 2 wfjm
          ndpcntl.gpr_we := '1';
1855
          ndpcntl.psr_ccwe := '1';
1856 34 wfjm
          idm_idone := '1';                       -- instruction done
1857 2 wfjm
          do_fork_next_pref(nstate, nstatus, ndpcntl, nvmcntl, nmmumoni);
1858
        end if;
1859
 
1860
      when s_opg_ashc =>                -- ASHC (load low, load shc)
1861
        ndpcntl.gpr_asrc := SRCREG(2 downto 1) & "1";-- read odd reg !
1862
        ndpcntl.dtmp_sel := c_dpath_dtmp_dsrc;
1863
        ndpcntl.dtmp_we := '1';
1864 8 wfjm
        ndpcntl.munit_s_ashc := '1';
1865 2 wfjm
        nstate := s_opg_ashc_cn;
1866
 
1867
      when s_opg_ashc_cn =>             -- ASHC (shift cycles)
1868
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;     -- DSRC = DRES
1869
        ndpcntl.dtmp_sel := c_dpath_dtmp_drese;   -- DTMP = DRESE
1870 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dsrc;  -- OUNIT A=DSRC
1871
        ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B=const(0)
1872 2 wfjm
        ndpcntl.gpr_adst := SRCREG;               -- write result
1873 8 wfjm
        ndpcntl.munit_s_ashc_cn := '1';
1874 2 wfjm
        nstate := s_opg_ashc_cn;
1875
        if DP_STAT.shc_tc = '0' then
1876
          ndpcntl.dres_sel := R_IDSTAT.res_sel;   -- DRES = choice of idec
1877
          ndpcntl.dsrc_we := '1';                 -- update DSRC
1878
          ndpcntl.dtmp_we := '1';                 -- update DTMP
1879
        else
1880 8 wfjm
          ndpcntl.dres_sel := c_dpath_res_ounit;  -- DRES = OUNIT
1881 2 wfjm
          ndpcntl.gpr_we := '1';
1882
          ndpcntl.psr_ccwe := '1';
1883
          nstate := s_opg_ashc_wl;
1884
        end if;
1885
 
1886
      when s_opg_ashc_wl =>             -- ASHC (write low)
1887 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dtmp; -- OUNIT A = DTMP
1888
        ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B = const(0)
1889
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
1890 2 wfjm
        ndpcntl.gpr_adst := SRCREG(2 downto 1) & "1";-- write odd reg !
1891
        ndpcntl.gpr_we := '1';
1892 34 wfjm
        idm_idone := '1';                        -- instruction done
1893
        do_fork_next(nstate, nstatus, nmmumoni);  -- fetch next
1894 2 wfjm
 
1895
  -- dsta mode operations -----------------------------------------------------
1896
 
1897
      when s_opa_jsr =>
1898
        ndpcntl.gpr_asrc := c_gpr_sp;              --                (for else)
1899
        ndpcntl.dsrc_sel := c_dpath_dsrc_src;      -- DSRC = regfile (for else)
1900
        if R_IDSTAT.is_dstmode0 = '1' then
1901
          nstate := s_trap_10;                     -- trap 10 like 11/70
1902
        else
1903
          ndpcntl.dsrc_we := '1';
1904
          nstate := s_opa_jsr1;
1905
        end if;
1906
 
1907
      when s_opa_jsr1 =>
1908
        ndpcntl.gpr_asrc := SRCREG;
1909
        ndpcntl.dtmp_sel := c_dpath_dtmp_dsrc;     -- DTMP = regfile
1910
        ndpcntl.dtmp_we := '1';
1911
 
1912 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dsrc;   -- OUNIT A=DSRC
1913
        ndpcntl.ounit_const := "000000010";
1914
        ndpcntl.ounit_bsel := c_ounit_bsel_const;  -- OUNIT B=const(2)
1915
        ndpcntl.ounit_opsub := '1';                -- OUNIT = A-B
1916
        ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
1917 2 wfjm
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;      -- DDST = DRES
1918
        ndpcntl.dsrc_we := '1';                    -- update DDST
1919
        ndpcntl.gpr_adst := c_gpr_sp;
1920
        ndpcntl.gpr_we := '1';                     -- update SP
1921
        nmmumoni.regmod := '1';
1922
        nmmumoni.isdec := '1';
1923
        nstate := s_opa_jsr_push;
1924
 
1925
      when s_opa_jsr_push =>
1926 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dtmp;   -- OUNIT A=DTMP
1927
        ndpcntl.ounit_bsel := c_ounit_bsel_const;  -- OUNIT B=const(0)
1928
        ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
1929 2 wfjm
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_dsrc; -- VA = DSRC
1930
        nvmcntl.dspace := '1';
1931
        nvmcntl.kstack := is_kmode;
1932
        nvmcntl.wacc := '1';
1933
        nvmcntl.req := '1';
1934
        nstate := s_opa_jsr_push_w;
1935
 
1936
      when s_opa_jsr_push_w =>
1937
        nstate := s_opa_jsr_push_w;
1938 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_pc;     -- OUNIT A=PC
1939
        ndpcntl.ounit_bsel := c_ounit_bsel_const;  -- OUNIT B=const(0)
1940
        ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
1941 2 wfjm
        ndpcntl.gpr_adst := SRCREG;
1942
        do_memcheck(nstate, nstatus, imemok);
1943
        if imemok then
1944
          ndpcntl.gpr_we := '1';                   -- load R with PC
1945
          nstate := s_opa_jsr2;
1946
        end if;
1947
 
1948
      when s_opa_jsr2 =>
1949 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst;   -- OUNIT A=DDST
1950
        ndpcntl.ounit_bsel := c_ounit_bsel_const;  -- OUNIT B=const(0)
1951
        ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
1952 2 wfjm
        ndpcntl.gpr_adst := c_gpr_pc;
1953
        ndpcntl.gpr_we := '1';                     -- load PC with dsta
1954 34 wfjm
        idm_idone := '1';                          -- instruction done
1955
        do_fork_next(nstate, nstatus, nmmumoni);   -- fetch next
1956 2 wfjm
 
1957
      when s_opa_jmp =>
1958 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst;   -- OUNIT A=DDST
1959
        ndpcntl.ounit_bsel := c_ounit_bsel_const;  -- OUNIT B=const(0)
1960
        ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
1961 2 wfjm
        ndpcntl.gpr_adst := c_gpr_pc;
1962
        if R_IDSTAT.is_dstmode0 = '1' then
1963
          nstate := s_trap_10;                     -- trap 10 like 11/70
1964
        else
1965
          ndpcntl.gpr_we := '1';                   -- load PC with dsta
1966 34 wfjm
          idm_idone := '1';                        -- instruction done
1967
          do_fork_next(nstate, nstatus, nmmumoni);  -- fetch next
1968 2 wfjm
        end if;
1969
 
1970
      when s_opa_mtp =>
1971
        do_memread_srcinc(nstate, ndpcntl, nvmcntl, s_opa_mtp_pop_w,
1972
                          nmmumoni, updt_sp=>'1');
1973
 
1974
      when s_opa_mtp_pop_w =>
1975
        nstate := s_opa_mtp_pop_w;
1976
        ndpcntl.dres_sel := c_dpath_res_vmdout;   -- DRES = VMDOUT
1977
        ndpcntl.dtmp_sel := c_dpath_dtmp_dres;    -- DTMP = DRES
1978
        do_memcheck(nstate, nstatus, imemok);
1979
        if imemok then
1980
          ndpcntl.dtmp_we := '1';                 -- load DTMP
1981
          if R_IDSTAT.is_dstmode0 = '1' then      -- handle register access
1982
            nstate := s_opa_mtp_reg;
1983
          else
1984
            case R_IDSTAT.fork_dsta is            -- 2nd dsta fork in s_idecode
1985
              when c_fork_dsta_def => nstate := s_opa_mtp_mem;
1986
              when c_fork_dsta_inc => nstate := s_dsta_inc;
1987
              when c_fork_dsta_dec => nstate := s_dsta_dec;
1988
              when c_fork_dsta_ind => nstate := s_dsta_ind;
1989
              when others => nstate := s_cpufail;
1990
            end case;
1991
          end if;
1992
        end if;
1993
        ndpcntl.ddst_sel := c_dpath_ddst_dst;     -- DDST = R(DST)
1994
        ndpcntl.ddst_we  := '1';                  -- update DDST (needed for sp)
1995
 
1996
      when s_opa_mtp_reg =>
1997 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dtmp;  -- OUNIT A = DTMP
1998
        ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B = const(0)
1999
        ndpcntl.dres_sel := c_dpath_res_ounit;    -- DRES = OUNIT
2000
        ndpcntl.psr_ccwe := '1';                  -- set cc (from ounit too)
2001 2 wfjm
        ndpcntl.gpr_mode := PSW.pmode;            -- load reg in pmode
2002
        ndpcntl.gpr_we := '1';
2003 34 wfjm
        idm_idone := '1';                         -- instruction done
2004
        do_fork_next(nstate, nstatus, nmmumoni);  -- fetch next
2005 2 wfjm
 
2006
      when s_opa_mtp_mem =>
2007 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dtmp;  -- OUNIT A = DTMP
2008
        ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B = const(0)
2009
        ndpcntl.dres_sel := c_dpath_res_ounit;    -- DRES = OUNIT
2010
        ndpcntl.psr_ccwe := '1';                  -- set cc (from ounit too)
2011 2 wfjm
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst;-- VA = DDST
2012
        nvmcntl.dspace := IREG(15);            -- msb indicates I/D: 0->I, 1->D
2013
        nvmcntl.mode := PSW.pmode;
2014
        nvmcntl.wacc := '1';
2015
        nvmcntl.req := '1';
2016
        nstate := s_opa_mtp_mem_w;
2017
 
2018
      when s_opa_mtp_mem_w =>
2019
        nstate := s_opa_mtp_mem_w;
2020
        do_memcheck(nstate, nstatus, imemok);
2021
        if imemok then
2022 34 wfjm
          idm_idone := '1';                       -- instruction done
2023
          do_fork_next(nstate, nstatus, nmmumoni);  -- fetch next
2024 2 wfjm
        end if;
2025
 
2026
      when s_opa_mfp_reg =>
2027
        ndpcntl.gpr_mode := PSW.pmode;           -- fetch reg in pmode
2028
        ndpcntl.ddst_sel := c_dpath_ddst_dst;    -- DDST = reg(dst)
2029
        ndpcntl.ddst_we := '1';
2030
        nstate := s_opa_mfp_dec;
2031
 
2032
      when s_opa_mfp_mem =>
2033
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_ddst;   -- VA = DDST
2034
        if PSW.cmode=c_psw_umode and                 -- if cm=pm=user then
2035
           PSW.cmode=c_psw_umode then                -- MFPI works like it
2036
          nvmcntl.dspace := '1';                     -- were MFPD
2037
        else
2038
          nvmcntl.dspace := IREG(15);          -- msb indicates I/D: 0->I, 1->D
2039
        end if;
2040
        nvmcntl.mode := PSW.pmode;
2041
        nvmcntl.req := '1';
2042
        nstate := s_opa_mfp_mem_w;
2043
 
2044
      when s_opa_mfp_mem_w =>
2045
        nstate := s_opa_mfp_mem_w;
2046
        do_memcheck(nstate, nstatus, imemok);
2047
        ndpcntl.dres_sel := c_dpath_res_vmdout;  -- DRES = VMDOUT
2048
        ndpcntl.ddst_sel := c_dpath_ddst_res;    -- DDST = DRES
2049
        if imemok then
2050
          ndpcntl.ddst_we := '1';
2051
          nstate := s_opa_mfp_dec;
2052
        end if;
2053
 
2054
      when s_opa_mfp_dec =>
2055 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dsrc;   -- OUNIT A=DSRC
2056
        ndpcntl.ounit_const := "000000010";
2057
        ndpcntl.ounit_bsel := c_ounit_bsel_const;  -- OUNIT B=const(2)
2058
        ndpcntl.ounit_opsub := '1';                -- OUNIT = A-B
2059
        ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
2060 2 wfjm
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;      -- DSRC = DRES
2061
        ndpcntl.dsrc_we := '1';                    -- update DSRC
2062
        ndpcntl.gpr_adst := c_gpr_sp;
2063
        ndpcntl.gpr_we := '1';                     -- update SP
2064
        nmmumoni.regmod := '1';
2065
        nmmumoni.isdec := '1';
2066
        nstate := s_opa_mfp_push;
2067
 
2068
      when s_opa_mfp_push =>
2069 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst;   -- OUNIT A=DDST
2070
        ndpcntl.ounit_bsel := c_ounit_bsel_const;  -- OUNIT B=const(0)
2071
        ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
2072
        ndpcntl.psr_ccwe := '1';                   -- set cc (from ounit too)
2073 2 wfjm
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_dsrc; -- VA = DSRC
2074
        nvmcntl.dspace := '1';
2075
        nvmcntl.kstack := is_kmode;
2076
        nvmcntl.wacc := '1';
2077
        nvmcntl.req := '1';
2078
        nstate := s_opa_mfp_push_w;
2079
 
2080
      when s_opa_mfp_push_w =>
2081
        nstate := s_opa_mfp_push_w;
2082
        do_memcheck(nstate, nstatus, imemok);
2083
        if imemok then
2084 34 wfjm
          idm_idone := '1';                       -- instruction done
2085
          do_fork_next(nstate, nstatus, nmmumoni);  -- fetch next
2086 2 wfjm
        end if;
2087
 
2088
  -- trap and interrupt handling states ---------------------------------------
2089
 
2090
      when s_trap_4 =>
2091
        lvector := "0000001";           -- vector (4)
2092
        do_start_int(nstate, ndpcntl, lvector);
2093
 
2094
      when s_trap_10 =>
2095 34 wfjm
        idm_idone := '1';               -- instruction done
2096 2 wfjm
        lvector := "0000010";           -- vector (10)
2097
        do_start_int(nstate, ndpcntl, lvector);
2098
 
2099
      when s_trap_disp =>
2100
        if R_STATUS.trap_mmu = '1' then
2101
          nvmcntl.trap_done := '1';     -- mmu trap taken: set ssr0 trap bit
2102
          lvector := "0101010";         -- mmu trap: vector (250)
2103
        elsif R_STATUS.trap_ysv = '1' then
2104
          lvector := "0000001";         -- ysv trap: vector (4)          
2105
          ncpuerr.ysv := '1';
2106
        else
2107
          lvector := "0000011";         -- trace trap: vector (14)
2108
        end if;
2109
        nstatus.trap_mmu := '0';        -- clear pending trap flags
2110
        nstatus.trap_ysv := '0';        -- 
2111
        do_start_int(nstate, ndpcntl, lvector);
2112
 
2113
      when s_int_ext =>
2114
        lvector := R_STATUS.intvect;    -- external vector
2115
        do_start_int(nstate, ndpcntl, lvector);
2116
 
2117
      when s_int_getpc =>
2118 34 wfjm
        idm_vfetch := '1';              -- signal vfetch
2119 2 wfjm
        nvmcntl.mode := c_psw_kmode;    -- fetch PC from kernel D space
2120
        do_memread_srcinc(nstate, ndpcntl, nvmcntl, s_int_getpc_w, nmmumoni);
2121
 
2122
      when s_int_getpc_w =>
2123
        nstate := s_int_getpc_w;
2124
        ndpcntl.dres_sel := c_dpath_res_vmdout;   -- DRES = VMDOUT
2125
        ndpcntl.ddst_sel := c_dpath_ddst_res;     -- DDST = DRES
2126
        do_memcheck(nstate, nstatus, imemok);
2127
        if VM_STAT.err = '1' then                 -- in case of vm-err
2128
          nstatus.cpugo   := '0';                 -- non-recoverable error
2129
          nstatus.cpurust := c_cpurust_vecfet;    -- halt CPU
2130
          nstate := s_idle;
2131
        end if;
2132
        if imemok then
2133
          ndpcntl.ddst_we := '1';                 -- DDST = new PC
2134
          nstate := s_int_getps;
2135
        end if;
2136
 
2137
      when s_int_getps =>
2138
        nvmcntl.mode := c_psw_kmode;    -- fetch PS from kernel D space
2139
        do_memread_srcinc(nstate, ndpcntl, nvmcntl, s_int_getps_w, nmmumoni);
2140
 
2141
      when s_int_getps_w =>
2142
        nstate := s_int_getps_w;
2143
        ndpcntl.dres_sel := c_dpath_res_vmdout;   -- DRES = VMDOUT
2144
        ndpcntl.psr_func := c_psr_func_wint;      -- interupt mode write
2145
        do_memcheck(nstate, nstatus, imemok);
2146
        if VM_STAT.err = '1' then                 -- in case of vm-err
2147
          nstatus.cpugo   := '0';                 -- non-recoverable error
2148
          nstatus.cpurust := c_cpurust_vecfet;    -- halt CPU
2149
          nstate := s_idle;
2150
        end if;
2151
        if imemok then
2152
          ndpcntl.psr_we := '1';                  -- store new PS
2153
          nstate := s_int_getsp;
2154
        end if;
2155
 
2156
      when s_int_getsp =>
2157
        ndpcntl.gpr_asrc := c_gpr_sp;
2158
        ndpcntl.dsrc_we := '1';                  -- DSRC = SP (in new mode)
2159
        nstate := s_int_decsp;
2160
 
2161
      when s_int_decsp =>
2162 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dsrc; -- OUNIT A=DSRC
2163
        ndpcntl.ounit_const := "000000010";      -- OUNIT const=2
2164
        ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B=const
2165
        ndpcntl.ounit_opsub := '1';              -- OUNIT = A-B
2166
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
2167 2 wfjm
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;    -- DSRC = DRES
2168
        ndpcntl.dsrc_we := '1';                  -- update DSRC
2169
        ndpcntl.gpr_adst := c_gpr_sp;
2170
        ndpcntl.gpr_we := '1';                   -- update SP too
2171
        nstate := s_int_pushps;
2172
 
2173
      when s_int_pushps =>
2174 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dtmp;   -- OUNIT A=DTMP (old PS)
2175
        ndpcntl.ounit_bsel := c_ounit_bsel_const;  -- OUNIT B=const (0)
2176
        ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
2177 2 wfjm
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_dsrc; -- VA = DSRC
2178
        nvmcntl.wacc := '1';                       -- write mem
2179
        nvmcntl.dspace := '1';
2180
        nvmcntl.kstack := is_kmode;
2181
        nvmcntl.req := '1';
2182
        nstate := s_int_pushps_w;
2183
 
2184
      when s_int_pushps_w =>
2185 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_dsrc; -- OUNIT A=DSRC
2186
        ndpcntl.ounit_const := "000000010";      -- OUNIT const=2
2187
        ndpcntl.ounit_bsel := c_ounit_bsel_const;-- OUNIT B=const
2188
        ndpcntl.ounit_opsub := '1';              -- OUNIT = A-B
2189
        ndpcntl.dres_sel := c_dpath_res_ounit;   -- DRES = OUNIT
2190 2 wfjm
        ndpcntl.dsrc_sel := c_dpath_dsrc_res;    -- DSRC = DRES
2191
        ndpcntl.gpr_adst := c_gpr_sp;
2192
 
2193
        nstate := s_int_pushps_w;
2194
        do_memcheck(nstate, nstatus, imemok);
2195
        if imemok then
2196
          ndpcntl.dsrc_we := '1';                -- update DSRC
2197
          ndpcntl.gpr_we := '1';                 -- update SP too
2198
          nstate := s_int_pushpc;
2199
        end if;
2200
 
2201
      when s_int_pushpc =>
2202 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_pc;     -- OUNIT A=PC
2203
        ndpcntl.ounit_bsel := c_ounit_bsel_const;  -- OUNIT B=const (0)
2204
        ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
2205 2 wfjm
        ndpcntl.vmaddr_sel := c_dpath_vmaddr_dsrc; -- VA = DSRC
2206
        nvmcntl.wacc := '1';                       -- write mem
2207
        nvmcntl.dspace := '1';
2208
        nvmcntl.kstack := is_kmode;
2209
        nvmcntl.req := '1';
2210
        nstate := s_int_pushpc_w;
2211
 
2212
      when s_int_pushpc_w =>
2213 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst;   -- OUNIT A=DDST
2214
        ndpcntl.ounit_bsel := c_ounit_bsel_const;  -- OUNIT B=const (0)
2215
        ndpcntl.dres_sel := c_dpath_res_ounit;     -- DRES = OUNIT
2216 2 wfjm
        ndpcntl.gpr_adst := c_gpr_pc;
2217
 
2218
        nstate := s_int_pushpc_w;
2219
        do_memcheck(nstate, nstatus, imemok);
2220
        if imemok then
2221
          nstatus.do_intrsv := '0';                -- signal end of rsv
2222
          ndpcntl.gpr_we := '1';                   -- load new PC
2223
          do_fork_next(nstate, nstatus, nmmumoni);         -- ???
2224
        end if;
2225
 
2226
  -- return from trap or interrupt handling states ----------------------------
2227
 
2228
      when s_rti_getpc =>
2229
        do_memread_srcinc(nstate, ndpcntl, nvmcntl, s_rti_getpc_w,
2230
                          nmmumoni, updt_sp=>'1');
2231
 
2232
      when s_rti_getpc_w =>
2233
        nstate := s_rti_getpc_w;
2234
        ndpcntl.dres_sel := c_dpath_res_vmdout;   -- DRES = VMDOUT
2235
        ndpcntl.ddst_sel := c_dpath_ddst_res;     -- DDST = DRES
2236
        do_memcheck(nstate, nstatus, imemok);
2237
        if imemok then
2238
          ndpcntl.ddst_we := '1';                 -- DDST = new PC
2239
          nstate := s_rti_getps;
2240
        end if;
2241
 
2242
      when s_rti_getps =>
2243
        do_memread_srcinc(nstate, ndpcntl, nvmcntl, s_rti_getps_w,
2244
                          nmmumoni, updt_sp=>'1');
2245
 
2246
      when s_rti_getps_w =>
2247
        nstate := s_rti_getps_w;
2248
        do_memcheck(nstate, nstatus, imemok);
2249
        ndpcntl.dres_sel := c_dpath_res_vmdout;   -- DRES = VMDOUT
2250
        if is_kmode = '1' then                    -- if in kernel mode
2251
          ndpcntl.psr_func := c_psr_func_wall;    --   write all fields
2252
        else
2253
          ndpcntl.psr_func := c_psr_func_wrti;    --   otherwise filter
2254
        end if;
2255
        if imemok then
2256
          ndpcntl.psr_we := '1';                  -- load new PS
2257
          nstate := s_rti_newpc;
2258
        end if;
2259
 
2260
      when s_rti_newpc =>
2261 8 wfjm
        ndpcntl.ounit_asel := c_ounit_asel_ddst;  -- OUNIT A=DDST
2262
        ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B=const (0)
2263
        ndpcntl.dres_sel := c_dpath_res_ounit;    -- DRES = OUNIT
2264 2 wfjm
        ndpcntl.gpr_adst := c_gpr_pc;
2265 8 wfjm
        ndpcntl.gpr_we := '1';                    -- load new PC
2266 34 wfjm
        idm_idone := '1';                         -- instruction done
2267 8 wfjm
        if R_IDSTAT.op_rtt = '1' then             -- if RTT instruction
2268 34 wfjm
          nstate := s_ifetch;                       -- force fetch
2269 8 wfjm
        else                                      -- otherwise RTI
2270 2 wfjm
          do_fork_next(nstate, nstatus, nmmumoni);
2271
        end if;
2272
 
2273
  -- exception abort states ---------------------------------------------------
2274
 
2275
      when s_vmerr =>
2276
        nstate := s_cpufail;
2277
 
2278
                                            -- setup for R_VMSTAT.err_rsv='1'
2279 8 wfjm
        ndpcntl.ounit_azero := '1';               -- OUNIT A = 0
2280
        ndpcntl.ounit_const := "000000100";       -- emergency stack pointer
2281
        ndpcntl.ounit_bsel := c_ounit_bsel_const; -- OUNIT B=const(vector)
2282
        ndpcntl.dres_sel := c_dpath_res_ounit;    -- DRES = OUNIT
2283
        ndpcntl.gpr_mode := c_psw_kmode;          -- set kmode SP to 4
2284 2 wfjm
        ndpcntl.gpr_adst := c_gpr_sp;
2285
 
2286 8 wfjm
        nstatus.trap_mmu :='0';                   -- drop pending mmu trap
2287 2 wfjm
 
2288 8 wfjm
        if R_VMSTAT.fail = '1' then               -- vmbox failure
2289
          nstatus.cpugo   := '0';                   -- halt cpu
2290 2 wfjm
          nstatus.cpurust := c_cpurust_vfail;
2291
          nstate := s_idle;
2292
 
2293 8 wfjm
        elsif R_STATUS.do_intrsv = '1' then       -- double error
2294
          nstatus.cpugo := '0';                     -- give up, HALT cpu
2295 2 wfjm
          nstatus.cpurust := c_cpurust_recrsv;
2296
          nstate := s_idle;
2297
 
2298
        elsif R_VMSTAT.err = '1' then            -- normal vm errors
2299
          if R_VMSTAT.err_rsv = '1' then
2300
            nstatus.do_intrsv := '1';              -- signal start of rsv
2301
            ndpcntl.gpr_we := '1';
2302
 
2303
            if R_VMSTAT.err_odd='1' or R_VMSTAT.err_mmu='1' then
2304
              ncpuerr.adderr := '1';
2305
            elsif R_VMSTAT.err_nxm = '1' then
2306
              ncpuerr.nxm := '1';
2307
            elsif R_VMSTAT.err_iobto = '1' then
2308
              ncpuerr.iobto := '1';
2309
            end if;
2310
            ncpuerr.rsv := '1';
2311
            nstate := s_trap_4;
2312
 
2313
          elsif R_VMSTAT.err_odd = '1' then
2314
            ncpuerr.adderr := '1';
2315
            nstate := s_trap_4;
2316
          elsif R_VMSTAT.err_nxm = '1' then
2317
            ncpuerr.nxm := '1';
2318
            nstate := s_trap_4;
2319
          elsif R_VMSTAT.err_iobto = '1' then
2320
            ncpuerr.iobto := '1';
2321
            nstate := s_trap_4;
2322
 
2323
          elsif R_VMSTAT.err_mmu = '1' then
2324
            lvector := "0101010";                    -- vector (250)
2325
            do_start_int(nstate, ndpcntl, lvector);
2326
          end if;
2327
        end if;
2328
 
2329
      when s_cpufail =>
2330
        nstatus.cpugo   := '0';
2331
        nstatus.cpurust := c_cpurust_sfail;
2332
        nstate := s_idle;
2333
 
2334
      when others =>
2335
        nstate := s_cpufail;             --!!! catch undefined states !!!
2336
 
2337
    end case;
2338
 
2339 34 wfjm
    if HBPT = '1' then                  -- handle hardware bpt
2340
      nstatus.cpurust := c_cpurust_hbpt;
2341 30 wfjm
      nstatus.suspint :='1';
2342
    end if;
2343
    nstatus.suspext := ESUSP_I;
2344
 
2345
    -- handle cpususp transitions 
2346
    if nstatus.suspint='1' or nstatus.suspext='1' then
2347
      nstatus.cpususp := '1';
2348
    elsif R_STATUS.suspint='0' and R_STATUS.suspext='0' then
2349
      nstatus.cpususp := '0';
2350
    end if;
2351
 
2352 2 wfjm
    if nstatus.cmdack = '1' then        -- cmdack in next cycle ? Yes we test
2353
                                           -- nstatus here !!
2354
      nstatus.cmdbusy := '0';
2355
      ndpcntl.cpdout_we := '1';
2356
    end if;
2357
 
2358
    N_STATE  <= nstate;
2359
    N_STATUS <= nstatus;
2360
    N_CPUERR <= ncpuerr;
2361
    N_IDSTAT <= nidstat;
2362
 
2363 30 wfjm
    INT_ACK <= R_STATUS.intack;
2364
    CRESET  <= R_STATUS.creset;
2365
    BRESET  <= R_STATUS.breset;
2366
    ESUSP_O <= R_STATUS.suspint;     -- FIXME_code: handle masking later
2367
    ITIMER  <= R_STATUS.itimer;
2368 2 wfjm
 
2369
    DP_CNTL <= ndpcntl;
2370
    VM_CNTL <= nvmcntl;
2371
 
2372
    nmmumoni.regnum := ndpcntl.gpr_adst;
2373 8 wfjm
    nmmumoni.delta  := ndpcntl.ounit_const(3 downto 0);
2374 2 wfjm
    MMU_MONI <= nmmumoni;
2375 34 wfjm
 
2376
    DM_STAT_SE.istart <= nmmumoni.istart;
2377
    DM_STAT_SE.idone  <= idm_idone;
2378
    DM_STAT_SE.vfetch <= idm_vfetch;
2379
 
2380 2 wfjm
  end process proc_next;
2381
 
2382
  proc_cpstat : process (R_STATUS)
2383
  begin
2384
    CP_STAT         <= cp_stat_init;
2385
    CP_STAT.cmdbusy <= R_STATUS.cmdbusy;
2386
    CP_STAT.cmdack  <= R_STATUS.cmdack;
2387
    CP_STAT.cmderr  <= R_STATUS.cmderr;
2388
    CP_STAT.cmdmerr <= R_STATUS.cmdmerr;
2389
    CP_STAT.cpugo   <= R_STATUS.cpugo;
2390
    CP_STAT.cpustep <= R_STATUS.cpustep;
2391
    CP_STAT.cpuwait <= R_STATUS.cpuwait;
2392 30 wfjm
    CP_STAT.cpususp <= R_STATUS.cpususp;
2393 2 wfjm
    CP_STAT.cpurust <= R_STATUS.cpurust;
2394 30 wfjm
    CP_STAT.suspint <= R_STATUS.suspint;
2395
    CP_STAT.suspext <= R_STATUS.suspext;
2396 2 wfjm
  end process proc_cpstat;
2397 34 wfjm
 
2398
  proc_snum : process (R_STATE)
2399
    variable isnum : slv8 := (others=>'0');
2400
  begin
2401
    isnum := (others=>'0');
2402
    case R_STATE is
2403
      -- STATE2SNUM mapper begin
2404
      when s_idle           => isnum := x"00";
2405
      when s_cp_regread     => isnum := x"01";
2406
      when s_cp_rps         => isnum := x"02";
2407
      when s_cp_memr_w      => isnum := x"03";
2408
      when s_cp_memw_w      => isnum := x"04";
2409
      when s_ifetch         => isnum := x"05";
2410
      when s_ifetch_w       => isnum := x"06";
2411
      when s_idecode        => isnum := x"07";
2412
 
2413
      when s_srcr_def       => isnum := x"08";
2414
      when s_srcr_def_w     => isnum := x"09";
2415
      when s_srcr_inc       => isnum := x"0a";
2416
      when s_srcr_inc_w     => isnum := x"0b";
2417
      when s_srcr_dec       => isnum := x"0c";
2418
      when s_srcr_dec1      => isnum := x"0d";
2419
      when s_srcr_ind       => isnum := x"0e";
2420
      when s_srcr_ind1_w    => isnum := x"0f";
2421
      when s_srcr_ind2      => isnum := x"10";
2422
      when s_srcr_ind2_w    => isnum := x"11";
2423
 
2424
      when s_dstr_def       => isnum := x"12";
2425
      when s_dstr_def_w     => isnum := x"13";
2426
      when s_dstr_inc       => isnum := x"14";
2427
      when s_dstr_inc_w     => isnum := x"15";
2428
      when s_dstr_dec       => isnum := x"16";
2429
      when s_dstr_dec1      => isnum := x"17";
2430
      when s_dstr_ind       => isnum := x"18";
2431
      when s_dstr_ind1_w    => isnum := x"19";
2432
      when s_dstr_ind2      => isnum := x"1a";
2433
      when s_dstr_ind2_w    => isnum := x"1b";
2434
 
2435
      when s_dstw_def       => isnum := x"1c";
2436
      when s_dstw_def_w     => isnum := x"1d";
2437
      when s_dstw_inc       => isnum := x"1e";
2438
      when s_dstw_inc_w     => isnum := x"1f";
2439
      when s_dstw_incdef_w  => isnum := x"20";
2440
      when s_dstw_dec       => isnum := x"21";
2441
      when s_dstw_dec1      => isnum := x"22";
2442
      when s_dstw_ind       => isnum := x"23";
2443
      when s_dstw_ind_w     => isnum := x"24";
2444
      when s_dstw_def246    => isnum := x"25";
2445
 
2446
      when s_dsta_inc       => isnum := x"26";
2447
      when s_dsta_incdef_w  => isnum := x"27";
2448
      when s_dsta_dec       => isnum := x"28";
2449
      when s_dsta_dec1      => isnum := x"29";
2450
      when s_dsta_ind       => isnum := x"2a";
2451
      when s_dsta_ind_w     => isnum := x"2b";
2452
 
2453
      when s_op_halt        => isnum := x"2c";
2454
      when s_op_wait        => isnum := x"2d";
2455
      when s_op_trap        => isnum := x"2e";
2456
      when s_op_reset       => isnum := x"2f";
2457
      when s_op_rts         => isnum := x"30";
2458
      when s_op_rts_pop     => isnum := x"31";
2459
      when s_op_rts_pop_w   => isnum := x"32";
2460
      when s_op_spl         => isnum := x"33";
2461
      when s_op_mcc         => isnum := x"34";
2462
      when s_op_br          => isnum := x"35";
2463
      when s_op_mark        => isnum := x"36";
2464
      when s_op_mark1       => isnum := x"37";
2465
      when s_op_mark_pop    => isnum := x"38";
2466
      when s_op_mark_pop_w  => isnum := x"39";
2467
      when s_op_sob         => isnum := x"3a";
2468
      when s_op_sob1        => isnum := x"3b";
2469
 
2470
      when s_opg_gen        => isnum := x"3c";
2471
      when s_opg_gen_rmw_w  => isnum := x"3d";
2472
      when s_opg_mul        => isnum := x"3e";
2473
      when s_opg_mul1       => isnum := x"3f";
2474
      when s_opg_div        => isnum := x"40";
2475
      when s_opg_div_cn     => isnum := x"41";
2476
      when s_opg_div_cr     => isnum := x"42";
2477
      when s_opg_div_sq     => isnum := x"43";
2478
      when s_opg_div_sr     => isnum := x"44";
2479
      when s_opg_div_quit   => isnum := x"45";
2480
      when s_opg_ash        => isnum := x"46";
2481
      when s_opg_ash_cn     => isnum := x"47";
2482
      when s_opg_ashc       => isnum := x"48";
2483
      when s_opg_ashc_cn    => isnum := x"49";
2484
      when s_opg_ashc_wl    => isnum := x"4a";
2485
 
2486
      when s_opa_jsr        => isnum := x"4b";
2487
      when s_opa_jsr1       => isnum := x"4c";
2488
      when s_opa_jsr_push   => isnum := x"4d";
2489
      when s_opa_jsr_push_w => isnum := x"4e";
2490
      when s_opa_jsr2       => isnum := x"4f";
2491
      when s_opa_jmp        => isnum := x"50";
2492
      when s_opa_mtp        => isnum := x"51";
2493
      when s_opa_mtp_pop_w  => isnum := x"52";
2494
      when s_opa_mtp_reg    => isnum := x"53";
2495
      when s_opa_mtp_mem    => isnum := x"54";
2496
      when s_opa_mtp_mem_w  => isnum := x"55";
2497
      when s_opa_mfp_reg    => isnum := x"56";
2498
      when s_opa_mfp_mem    => isnum := x"57";
2499
      when s_opa_mfp_mem_w  => isnum := x"58";
2500
      when s_opa_mfp_dec    => isnum := x"59";
2501
      when s_opa_mfp_push   => isnum := x"5a";
2502
      when s_opa_mfp_push_w => isnum := x"5b";
2503
 
2504
      when s_trap_4         => isnum := x"5c";
2505
      when s_trap_10        => isnum := x"5d";
2506
      when s_trap_disp      => isnum := x"5e";
2507
 
2508
      when s_int_ext        => isnum := x"5f";
2509
 
2510
      when s_int_getpc      => isnum := x"60";
2511
      when s_int_getpc_w    => isnum := x"61";
2512
      when s_int_getps      => isnum := x"62";
2513
      when s_int_getps_w    => isnum := x"63";
2514
      when s_int_getsp      => isnum := x"64";
2515
      when s_int_decsp      => isnum := x"65";
2516
      when s_int_pushps     => isnum := x"66";
2517
      when s_int_pushps_w   => isnum := x"67";
2518
      when s_int_pushpc     => isnum := x"68";
2519
      when s_int_pushpc_w   => isnum := x"69";
2520
 
2521
      when s_rti_getpc      => isnum := x"6a";
2522
      when s_rti_getpc_w    => isnum := x"6b";
2523
      when s_rti_getps      => isnum := x"6c";
2524
      when s_rti_getps_w    => isnum := x"6d";
2525
      when s_rti_newpc      => isnum := x"6e";
2526
 
2527
      when s_vmerr          => isnum := x"6f";
2528
      when s_cpufail        => isnum := x"70";
2529
 
2530
      -- STATE2SNUM mapper end
2531
      when others           => isnum := x"ff";
2532
    end case;
2533
    DM_STAT_SE.snum   <= isnum;
2534
  end process proc_snum;
2535
 
2536 2 wfjm
end syn;
2537
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.