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 40

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

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

powered by: WebSVN 2.1.0

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