w11 - vhd 0.794
W11 CPU core and support modules
Loading...
Searching...
No Matches
pdp11_mmu.vhd
Go to the documentation of this file.
1-- $Id: pdp11_mmu.vhd 1331 2022-12-18 11:55:47Z mueller $
2-- SPDX-License-Identifier: GPL-3.0-or-later
3-- Copyright 2006-2022 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4--
5------------------------------------------------------------------------------
6-- Module Name: pdp11_mmu - syn
7-- Description: pdp11: mmu - memory management unit
8--
9-- Dependencies: pdp11_mmu_padr
10-- pdp11_mmu_mmr12
11-- ibus/ib_sres_or_3
12-- ibus/ib_sel
13--
14-- Test bench: tb/tb_pdp11_core (implicit)
15-- Target Devices: generic
16-- Tool versions: ise 8.2-14.7; viv 2014.4-2022.1; ghdl 0.18-2.0.0
17--
18-- Revision History:
19-- Date Rev Version Comment
20-- 2022-12-17 1331 1.4.7 some logic cleanup
21-- 2022-12-12 1330 1.4.6 implement MMR0 instruction complete
22-- 2022-11-29 1323 1.4.5 rename mmu_mmr0_type dspace->page_dspace
23-- 2022-09-05 1294 1.4.4 BUGFIX: correct trap and PDR A logic
24-- 2022-08-13 1279 1.4.3 ssr->mmr rename
25-- 2011-11-18 427 1.4.2 now numeric_std clean
26-- 2010-10-23 335 1.4.1 use ib_sel
27-- 2010-10-17 333 1.4 use ibus V2 interface
28-- 2010-06-20 307 1.3.7 rename cpacc to cacc in mmu_cntl_type
29-- 2009-05-30 220 1.3.6 final removal of snoopers (were already commented)
30-- 2009-05-09 213 1.3.5 BUGFIX: tie inst_compl permanentely '0'
31-- BUGFIX: set mmr0 trap_mmu even when traps disabled
32-- 2008-08-22 161 1.3.4 rename pdp11_ibres_ -> ib_sres_, ubf_ -> ibf_
33-- 2008-04-27 139 1.3.3 allow mmr1/2 tracing even with mmu_ena=0
34-- 2008-04-25 138 1.3.2 add BRESET port, clear mmr0/3 with BRESET
35-- 2008-03-02 121 1.3.1 remove snoopers
36-- 2008-02-24 119 1.3 return always mapped address in PADDRH; remove
37-- cpacc handling; PADDR generation now on _vmbox
38-- 2008-01-05 110 1.2.1 rename _mmu_regs -> _mmu_sadr
39-- rename IB_MREQ(ena->req) SRES(sel->ack, hold->busy)
40-- 2008-01-01 109 1.2 use pdp11_mmu_regs (rather than _regset)
41-- 2007-12-31 108 1.1.1 remove SADR memory address mux (-> _mmu_regfile)
42-- 2007-12-30 107 1.1 use IB_MREQ/IB_SRES interface now
43-- 2007-06-14 56 1.0.1 Use slvtypes.all
44-- 2007-05-12 26 1.0 Initial version
45------------------------------------------------------------------------------
46
47library ieee;
48use ieee.std_logic_1164.all;
49use ieee.numeric_std.all;
50
51use work.slvtypes.all;
52use work.iblib.all;
53use work.pdp11.all;
54
55-- ----------------------------------------------------------------------------
56
57entity pdp11_mmu is -- mmu - memory management unit
58 port (
59 CLK : in slbit; -- clock
60 CRESET : in slbit; -- cpu reset
61 BRESET : in slbit; -- bus reset
62 CNTL : in mmu_cntl_type; -- control port
63 VADDR : in slv16; -- virtual address
64 MONI : in mmu_moni_type; -- monitor port
65 STAT : out mmu_stat_type; -- status port
66 PADDRH : out slv16; -- physical address (upper 16 bit)
67 IB_MREQ: in ib_mreq_type; -- ibus request
68 IB_SRES: out ib_sres_type -- ibus response
69 );
70end pdp11_mmu;
71
72architecture syn of pdp11_mmu is
73
74 constant ibaddr_mmr0 : slv16 := slv(to_unsigned(8#177572#,16));
75 constant ibaddr_mmr3 : slv16 := slv(to_unsigned(8#172516#,16));
76
77 constant mmr0_ibf_abo_nonres : integer := 15;
78 constant mmr0_ibf_abo_length : integer := 14;
79 constant mmr0_ibf_abo_rdonly : integer := 13;
80 constant mmr0_ibf_trap_mmu : integer := 12;
81 constant mmr0_ibf_ena_trap : integer := 9;
82 constant mmr0_ibf_inst_compl : integer := 7;
83 subtype mmr0_ibf_page_mode is integer range 6 downto 5;
84 constant mmr0_ibf_page_dspace : integer := 4;
85 subtype mmr0_ibf_page_num is integer range 3 downto 1;
86 constant mmr0_ibf_ena_mmu : integer := 0;
87
88 constant mmr3_ibf_ena_ubmap : integer := 5;
89 constant mmr3_ibf_ena_22bit : integer := 4;
90 constant mmr3_ibf_dspace_km : integer := 2;
91 constant mmr3_ibf_dspace_sm : integer := 1;
92 constant mmr3_ibf_dspace_um : integer := 0;
93
94 signal IBSEL_MMR0 : slbit := '0'; -- ibus select MMR0
95 signal IBSEL_MMR3 : slbit := '0'; -- ibus select MMR3
96
97 signal R_MMR0 : mmu_mmr0_type := mmu_mmr0_init;
98 signal N_MMR0 : mmu_mmr0_type := mmu_mmr0_init;
99
100 signal R_MMR3 : mmu_mmr3_type := mmu_mmr3_init;
101
102 signal APN : slv4 := "0000"; -- augmented page number (1+3 bit)
103 signal AIB_WE : slbit := '0'; -- update AIB
104 signal AIB_SETA : slbit := '0'; -- set A bit in access information bits
105 signal AIB_SETW : slbit := '0'; -- set W bit in access information bits
106
107 signal TRACE : slbit := '0'; -- enable tracing in mmr1/2
108 signal DSPACE : slbit := '0'; -- use dspace
109
110 signal IB_SRES_PADR : ib_sres_type := ib_sres_init;
111 signal IB_SRES_MMR12 : ib_sres_type := ib_sres_init;
112 signal IB_SRES_MMR03 : ib_sres_type := ib_sres_init;
113
114 signal PARPDR : parpdr_type := parpdr_init;
115
116begin
117
118 PADR : pdp11_mmu_padr port map (
119 CLK => CLK,
120 MODE => CNTL.mode,
121 APN => APN,
122 AIB_WE => AIB_WE,
125 PARPDR => PARPDR,
126 IB_MREQ => IB_MREQ,
128
129 MMR12 : pdp11_mmu_mmr12 port map (
130 CLK => CLK,
131 CRESET => CRESET,
132 TRACE => TRACE,
133 MONI => MONI,
134 VADDR => VADDR,
135 IB_MREQ => IB_MREQ,
137
138 SRES_OR : ib_sres_or_3
139 port map (
144
145 SEL_MMR0 : ib_sel
146 generic map (
148 port map (
149 CLK => CLK,
150 IB_MREQ => IB_MREQ,
151 SEL => IBSEL_MMR0
152 );
153 SEL_MMR3 : ib_sel
154 generic map (
156 port map (
157 CLK => CLK,
158 IB_MREQ => IB_MREQ,
159 SEL => IBSEL_MMR3
160 );
161
162 proc_ibres : process (IBSEL_MMR0, IBSEL_MMR3, IB_MREQ, R_MMR0, R_MMR3)
163
164 variable mmr0out : slv16 := (others=>'0');
165 variable mmr3out : slv16 := (others=>'0');
166
167 begin
168
169 mmr0out := (others=>'0');
170 if IBSEL_MMR0 = '1' then
171 mmr0out(mmr0_ibf_abo_nonres) := R_MMR0.abo_nonres;
172 mmr0out(mmr0_ibf_abo_length) := R_MMR0.abo_length;
173 mmr0out(mmr0_ibf_abo_rdonly) := R_MMR0.abo_rdonly;
174 mmr0out(mmr0_ibf_trap_mmu) := R_MMR0.trap_mmu;
175 mmr0out(mmr0_ibf_ena_trap) := R_MMR0.ena_trap;
176 mmr0out(mmr0_ibf_inst_compl) := R_MMR0.inst_compl;
177 mmr0out(mmr0_ibf_page_mode) := R_MMR0.page_mode;
178 mmr0out(mmr0_ibf_page_dspace):= R_MMR0.page_dspace;
179 mmr0out(mmr0_ibf_page_num) := R_MMR0.page_num;
180 mmr0out(mmr0_ibf_ena_mmu) := R_MMR0.ena_mmu;
181 end if;
182
183 mmr3out := (others=>'0');
184 if IBSEL_MMR3 = '1' then
185 mmr3out(mmr3_ibf_ena_ubmap) := R_MMR3.ena_ubmap;
186 mmr3out(mmr3_ibf_ena_22bit) := R_MMR3.ena_22bit;
187 mmr3out(mmr3_ibf_dspace_km) := R_MMR3.dspace_km;
188 mmr3out(mmr3_ibf_dspace_sm) := R_MMR3.dspace_sm;
189 mmr3out(mmr3_ibf_dspace_um) := R_MMR3.dspace_um;
190 end if;
191
192 IB_SRES_MMR03.dout <= mmr0out or mmr3out;
193 IB_SRES_MMR03.ack <= (IBSEL_MMR0 or IBSEL_MMR3) and
194 (IB_MREQ.re or IB_MREQ.we); -- ack all
195 IB_SRES_MMR03.busy <= '0';
196
197 end process proc_ibres;
198
199 proc_mmr0 : process (CLK)
200 begin
201 if rising_edge(CLK) then
202 if BRESET = '1' then
203 R_MMR0 <= mmu_mmr0_init;
204 else
205 R_MMR0 <= N_MMR0;
206 end if;
207 end if;
208 end process proc_mmr0;
209
210 proc_mmr3 : process (CLK)
211 begin
212 if rising_edge(CLK) then
213 if BRESET = '1' then
214 R_MMR3 <= mmu_mmr3_init;
215 elsif IBSEL_MMR3='1' and IB_MREQ.we='1' then
216 if IB_MREQ.be0 = '1' then
217 R_MMR3.ena_ubmap <= IB_MREQ.din(mmr3_ibf_ena_ubmap);
218 R_MMR3.ena_22bit <= IB_MREQ.din(mmr3_ibf_ena_22bit);
219 R_MMR3.dspace_km <= IB_MREQ.din(mmr3_ibf_dspace_km);
220 R_MMR3.dspace_sm <= IB_MREQ.din(mmr3_ibf_dspace_sm);
221 R_MMR3.dspace_um <= IB_MREQ.din(mmr3_ibf_dspace_um);
222 end if;
223 end if;
224 end if;
225 end process proc_mmr3;
226
227 proc_paddr : process (R_MMR0, R_MMR3, CNTL, PARPDR, VADDR)
228
229 variable ipaddrh : slv16 := (others=>'0');
230 variable dspace_ok : slbit := '0';
231 variable dspace_en : slbit := '0';
232 variable apf : slv3 := (others=>'0'); -- va: active page field
233 variable bn : slv7 := (others=>'0'); -- va: block number
234 variable iapn : slv4 := (others=>'0');-- augmented page number
235
236 begin
237
238 apf := VADDR(15 downto 13);
239 bn := VADDR(12 downto 6);
240
241 dspace_en := '0';
242 case CNTL.mode is
243 when "00" => dspace_en := R_MMR3.dspace_km;
244 when "01" => dspace_en := R_MMR3.dspace_sm;
245 when "11" => dspace_en := R_MMR3.dspace_um;
246 when others => null;
247 end case;
248 dspace_ok := CNTL.dspace and dspace_en;
249
250 iapn(3) := dspace_ok;
251 iapn(2 downto 0) := apf;
252
253 ipaddrh := slv(unsigned("000000000"&bn) + unsigned(PARPDR.paf));
254
255 DSPACE <= dspace_ok;
256 APN <= iapn;
257 PADDRH <= ipaddrh;
258
259 end process proc_paddr;
260
261 proc_nmmr0 : process (R_MMR0, R_MMR3, IB_MREQ, IBSEL_MMR0, DSPACE,
263
264 variable nmmr0 : mmu_mmr0_type := mmu_mmr0_init;
265 variable apf : slv3 := (others=>'0');
266 variable bn : slv7 := (others=>'0');
267 variable abo_nonres : slbit := '0';
268 variable abo_length : slbit := '0';
269 variable abo_rdonly : slbit := '0';
270 variable mmr_freeze : slbit := '0';
271 variable doabort : slbit := '0';
272 variable dotrap : slbit := '0';
273 variable dotrace : slbit := '0';
274 variable iswrite : slbit := '0';
275
276 begin
277
278 nmmr0 := R_MMR0;
279
280 AIB_WE <= '0';
281 AIB_SETA <= '0';
282 AIB_SETW <= '0';
283
284 mmr_freeze := R_MMR0.abo_nonres or R_MMR0.abo_length or R_MMR0.abo_rdonly;
285 dotrace := not(CNTL.cacc or mmr_freeze);
286 iswrite := CNTL.wacc or CNTL.macc;
287
288 apf := VADDR(15 downto 13);
289 bn := VADDR(12 downto 6);
290
291 abo_nonres := '0';
292 abo_length := '0';
293 abo_rdonly := '0';
294 doabort := '0';
295 dotrap := '0';
296
297 if PARPDR.ed = '0' then -- ed=0: upward expansion
298 if unsigned(bn) > unsigned(PARPDR.plf) then
299 abo_length := '1';
300 end if;
301 else -- ed=0: downward expansion
302 if unsigned(bn) < unsigned(PARPDR.plf) then
303 abo_length := '1';
304 end if;
305 end if;
306
307 -- ACF decision logic
308 -- w11 has 4 memory cycle types, the ACF is based only on read or write
309 -- wacc='0' macc'0' : read cycle --> read
310 -- wacc='1' macc'0' : write cycle --> write
311 -- wacc='0' macc'1' : read part of rmw --> write
312 -- wacc='1' macc'1' : write part of rmw --> write
313 -- Depending of ACF the MMU aborts, queues a trap, sets A and W bit in PDR
314 -- ACF abort trap Comment
315 -- 000 nonres - non-resident: abort all accesses
316 -- 001 rdonly R read-only: abort on write, trap on read
317 -- 010 rdonly read-only: abort on write
318 -- 011 nonres - unused: abort all accesses
319 -- 100 - R+W read/write: no abort, trap on read or write
320 -- 101 - W read/write: no abort, trap on write
321 -- 110 - - read/write: no abort, no trap
322 -- 111 nonres - unused: abort all accesses
323 --
324 -- The PDR W bit is set for non-aborted write accesses
325 -- The PDR A bit is set if the trap condition is fulfilled and not aborted
326
327 case PARPDR.acf is -- evaluate accecc control field
328
329 when "000" => -- page non-resident
330 abo_nonres := '1';
331
332 when "001" => -- read-only; trap on read
333 if iswrite='1' then
334 abo_rdonly := '1';
335 end if;
336 dotrap := not iswrite;
337
338 when "010" => -- read-only
339 if iswrite='1' then
340 abo_rdonly := '1';
341 end if;
342
343 when "100" => -- read/write; trap on read&write
344 dotrap := '1';
345
346 when "101" => -- read/write; trap on write
347 dotrap := iswrite;
348
349 when "110" => null; -- read/write;
350
351 when others => -- unused codes: abort access
352 abo_nonres := '1';
353 end case;
354
355 STAT <= mmu_stat_init;
356
357 if IBSEL_MMR0='1' and IB_MREQ.we='1' then
358
359 if IB_MREQ.be1 = '1' then
360 nmmr0.abo_nonres := IB_MREQ.din(mmr0_ibf_abo_nonres);
361 nmmr0.abo_length := IB_MREQ.din(mmr0_ibf_abo_length);
362 nmmr0.abo_rdonly := IB_MREQ.din(mmr0_ibf_abo_rdonly);
363 nmmr0.trap_mmu := IB_MREQ.din(mmr0_ibf_trap_mmu);
364 nmmr0.ena_trap := IB_MREQ.din(mmr0_ibf_ena_trap);
365 end if;
366 if IB_MREQ.be0 = '1' then
367 nmmr0.ena_mmu := IB_MREQ.din(mmr0_ibf_ena_mmu);
368 end if;
369
370 elsif R_MMR0.ena_mmu='1' and CNTL.cacc='0' then
371
372 if mmr_freeze = '0' then -- independent of an active request will
373 nmmr0.inst_compl := MONI.vflow; -- the inst_compl flag follow vflow
374 end if;
375
376 if CNTL.req = '1' then
377 AIB_WE <= '1';
378 if mmr_freeze = '0' then
379 nmmr0.abo_nonres := abo_nonres;
380 nmmr0.abo_length := abo_length;
381 nmmr0.abo_rdonly := abo_rdonly;
382 nmmr0.page_dspace := DSPACE;
383 nmmr0.page_num := apf;
384 nmmr0.page_mode := CNTL.mode;
385 end if;
386 doabort := abo_nonres or abo_length or abo_rdonly;
387
388 if doabort = '0' then
389 AIB_SETA <= dotrap;
390 AIB_SETW <= iswrite;
391 if dotrap='1' then -- if trap condition fulfilled
392 nmmr0.trap_mmu := '1'; -- set trap_mmu flag
393 if R_MMR0.ena_trap='1' and R_MMR0.trap_mmu='0' then
394 STAT.trap <= '1'; -- trap if enabled and not blocked
395 end if;
396 end if;
397 end if;
398
399 end if; -- CNTL.req = '1'
400 end if; -- R_MMR0.ena_mmu='1' and CNTL.cacc='0'
401
402 nmmr0.trace_prev := dotrace;
403
404 if MONI.trace_prev = '0' then
405 TRACE <= dotrace;
406 else
407 TRACE <= R_MMR0.trace_prev;
408 end if;
409
410 N_MMR0 <= nmmr0;
411
412 if R_MMR0.ena_mmu='1' and CNTL.cacc='0' then
413 STAT.vaok <= not doabort;
414 else
415 STAT.vaok <= '1';
416 end if;
417
418 STAT.ena_mmu <= R_MMR0.ena_mmu;
419 STAT.ena_22bit <= R_MMR3.ena_22bit;
420 STAT.ena_ubmap <= R_MMR3.ena_ubmap;
421
422 end process proc_nmmr0;
423
424end syn;
out SEL slbit
Definition: ib_sel.vhd:35
IB_ADDR slv16
Definition: ib_sel.vhd:29
in CLK slbit
Definition: ib_sel.vhd:32
in IB_MREQ ib_mreq_type
Definition: ib_sel.vhd:33
in IB_SRES_2 ib_sres_type := ib_sres_init
in IB_SRES_3 ib_sres_type := ib_sres_init
out IB_SRES_OR ib_sres_type
in IB_SRES_1 ib_sres_type
Definition: iblib.vhd:33
parpdr_type := parpdr_init PARPDR
Definition: pdp11_mmu.vhd:114
slbit := '0' AIB_SETW
Definition: pdp11_mmu.vhd:105
slbit := '0' AIB_SETA
Definition: pdp11_mmu.vhd:104
ib_sres_type := ib_sres_init IB_SRES_MMR12
Definition: pdp11_mmu.vhd:111
integer := 15 mmr0_ibf_abo_nonres
Definition: pdp11_mmu.vhd:77
integer := 1 mmr3_ibf_dspace_sm
Definition: pdp11_mmu.vhd:91
integer := 4 mmr0_ibf_page_dspace
Definition: pdp11_mmu.vhd:84
ib_sres_type := ib_sres_init IB_SRES_MMR03
Definition: pdp11_mmu.vhd:112
integer := 2 mmr3_ibf_dspace_km
Definition: pdp11_mmu.vhd:90
slv4 := "0000" APN
Definition: pdp11_mmu.vhd:102
integer := 5 mmr3_ibf_ena_ubmap
Definition: pdp11_mmu.vhd:88
slbit := '0' AIB_WE
Definition: pdp11_mmu.vhd:103
slv16 := slv( to_unsigned( 8#172516#, 16) ) ibaddr_mmr3
Definition: pdp11_mmu.vhd:75
ib_sres_type := ib_sres_init IB_SRES_PADR
Definition: pdp11_mmu.vhd:110
slv16 := slv( to_unsigned( 8#177572#, 16) ) ibaddr_mmr0
Definition: pdp11_mmu.vhd:74
mmu_mmr3_type := mmu_mmr3_init R_MMR3
Definition: pdp11_mmu.vhd:100
slbit := '0' IBSEL_MMR3
Definition: pdp11_mmu.vhd:95
slbit := '0' DSPACE
Definition: pdp11_mmu.vhd:108
integer range 6 downto 5 mmr0_ibf_page_mode
Definition: pdp11_mmu.vhd:83
integer := 4 mmr3_ibf_ena_22bit
Definition: pdp11_mmu.vhd:89
integer range 3 downto 1 mmr0_ibf_page_num
Definition: pdp11_mmu.vhd:85
mmu_mmr0_type := mmu_mmr0_init N_MMR0
Definition: pdp11_mmu.vhd:98
mmu_mmr0_type := mmu_mmr0_init R_MMR0
Definition: pdp11_mmu.vhd:97
integer := 14 mmr0_ibf_abo_length
Definition: pdp11_mmu.vhd:78
integer := 12 mmr0_ibf_trap_mmu
Definition: pdp11_mmu.vhd:80
integer := 0 mmr3_ibf_dspace_um
Definition: pdp11_mmu.vhd:92
slbit := '0' IBSEL_MMR0
Definition: pdp11_mmu.vhd:94
integer := 9 mmr0_ibf_ena_trap
Definition: pdp11_mmu.vhd:81
integer := 0 mmr0_ibf_ena_mmu
Definition: pdp11_mmu.vhd:86
integer := 13 mmr0_ibf_abo_rdonly
Definition: pdp11_mmu.vhd:79
slbit := '0' TRACE
Definition: pdp11_mmu.vhd:107
integer := 7 mmr0_ibf_inst_compl
Definition: pdp11_mmu.vhd:82
in MONI mmu_moni_type
in IB_MREQ ib_mreq_type
out IB_SRES ib_sres_type
in AIB_WE slbit
in IB_MREQ ib_mreq_type
out IB_SRES ib_sres_type
in AIB_SETW slbit
out PARPDR parpdr_type
in AIB_SETA slbit
out PADDRH slv16
Definition: pdp11_mmu.vhd:66
in VADDR slv16
Definition: pdp11_mmu.vhd:63
in BRESET slbit
Definition: pdp11_mmu.vhd:61
out STAT mmu_stat_type
Definition: pdp11_mmu.vhd:65
in MONI mmu_moni_type
Definition: pdp11_mmu.vhd:64
in CLK slbit
Definition: pdp11_mmu.vhd:59
in CRESET slbit
Definition: pdp11_mmu.vhd:60
in IB_MREQ ib_mreq_type
Definition: pdp11_mmu.vhd:67
in CNTL mmu_cntl_type
Definition: pdp11_mmu.vhd:62
out IB_SRES ib_sres_type
Definition: pdp11_mmu.vhd:69
Definition: pdp11.vhd:123
std_logic_vector( 3 downto 0) slv4
Definition: slvtypes.vhd:36
std_logic_vector( 6 downto 0) slv7
Definition: slvtypes.vhd:39
std_logic_vector( 2 downto 0) slv3
Definition: slvtypes.vhd:35
std_logic_vector( 15 downto 0) slv16
Definition: slvtypes.vhd:48
std_logic slbit
Definition: slvtypes.vhd:30
std_logic_vector slv
Definition: slvtypes.vhd:31