The Fred VHDL Model William F. Richardson UUCS-95-021 Department of Computer Science University of Utah Salt Lake City, UT 84112 USA November 21, 1995 Abstract This is the companion document to my dissertation. It contains 47 pages of schematics, and 163 pages of VHDL code. It is pretty meaningless without the dissertation, and it only exists because I felt that I should archive this information somewhere. Contents 1 Schematic Heirarchy 5 2 VHDL Source Code 9 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 2.10 2.11 2.12 2.13 2.14 2.15 2.16 2.17 2.18 2.19 2.20 2.21 2.22 2.23 2.24 2.25 2.26 2.27 2.28 2.29 arbiter which.vhd arith unit.vhd branch unit.vhd control unit.vhd cpx128.vhd cpx18.vhd cpx32.vhd cpx3op.vhd cpx4op.vhd cpx5.vhd cpx88.vhd cpx96.vhd delaytap.vhd dispatch.vhd logic unit.vhd memory unit.vhd p arith.vhd p constants.vhd p dispatch.vhd p memory unit.vhd p output.vhd qop.vhd registers.vhd regselect.vhd scoreboard.vhd vdelay.vhd verify address.vhd zdelay.vhd zxor.vhd : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 1 9 12 22 30 37 40 43 46 49 52 55 58 61 63 106 114 125 127 131 142 145 147 148 154 162 165 166 170 171 2 3 Schematic Diagrams CONTENTS 173 List of Figures 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 3.20 3.21 3.22 3.23 3.24 3.25 3.26 3.27 3.28 3.29 3.30 3.31 3.32 3.33 arbcall arbcallx88 buf32 buf4 buf8 callx32 cp-delay delaychain distributor ex-unit1 ex-unit2 fo-32 fo-36 fred-memory fred-with-mem fred1 fred2 fred3 fu-arith fu-branch fu-control fu-logic fu-memory gate if-unit1 if-unit2 memory-latches mux2x30 mux2x32 mux2x4 mux2x5 mux2x8 pipe-nx128 : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 3 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 LIST OF FIGURES 4 3.34 3.35 3.36 3.37 3.38 3.39 3.40 3.41 3.42 3.43 3.44 3.45 3.46 3.47 pipe-nx18 pipe-nx32 pipe-nx3op pipe-nx4op pipe-nx5 pipe-nx88 pipe-nx96 qop-even qop-odd ram-byte-order ram16kx32 rf-unit tlnt-32 zerox32 : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 207 208 209 210 211 212 213 214 215 216 217 218 219 220 Chapter 1 Schematic Heirarchy This is the schematic hierarchy. \fred-with-mem" is the top level schematic. The elements listed in parentheses are VHDL modules. Any schematics not listed in this hierarchy are standard library modules. fred-with-mem fred.1 if_unit.1 (dispatch) gate qflop_even (qflop) qflop_odd (qflop) if_unit.2 (scoreboard) arbcall (arbiter_which) mux2x5 pipe_nx128 (cpx128) delaychain (delaytap zxor) cp_delay pipe_nx18 (cpx18) delaychain (delaytap zxor) cp_delay fred.2 pipe_nx5 (cpx5) delaychain (delaytap zxor) cp_delay pipe_nx96 (cpx96) delaychain (delaytap zxor) cp_delay rf_unit (registers regselect) fred.3 ex_unit 5 CHAPTER 1. SCHEMATIC HEIRARCHY 6 distributor fu_arith (arith_unit) pipe_nx3op (cpx3op) delaychain (delaytap zxor) cp_delay fu_control (control_unit) pipe_nx4op (cpx4op) delaychain (delaytap zxor) cp_delay fu_logic (logic_unit) pipe_nx3op (cpx3op) delaychain (delaytap zxor) cp_delay mux2x32 zerox32 buf8 ex_unit.2 arbcallx88 (arbiter_which vdelay) mux2x32 mux2x8 callx32 (vdelay) mux2x32 fu_branch (branch_unit) pipe_nx4op (cpx4op) delaychain (delaytap zxor) cp_delay fu_memory (memory_unit) pipe_nx4op (cpx4op) delaychain (delaytap zxor) cp_delay pipe_nx32 (cpx32) delaychain (delaytap zxor) cp_delay pipe_nx88 (cpx88) delaychain (delaytap zxor) cp_delay fred-memory (arbiter_which verify_address zdelay) 7 memory_latches (vdelay) buf32 buf4 fifo-32 tlnt-32 fifo-36 tlnt-32 mux2x30 mux2x4 ram16kx32 (ram16kx8 vdelay) ram_byte_order 8 CHAPTER 1. SCHEMATIC HEIRARCHY Chapter 2 VHDL Source Code 2.1 arbiter which.vhd ------------- This models an arbiter with an extra level output to indicate which choice it made. It uses a state machine with 5 states. There is no provision for stopping or resetting it, and it assumes that the inputs are well-behaved. ---- The "w" output changes instantly, as soon as it can. The grant signal is ---- subject to a delay (default .1ns), changeable with a DELAY attribute. ENTITY arbiter_which IS GENERIC( delay: TIME := 100 PS) PORT (SIGNAL clr :IN VLBIT SIGNAL r0 :IN VLBIT SIGNAL r1 :IN VLBIT SIGNAL d0 :IN VLBIT SIGNAL d1 :IN VLBIT SIGNAL g0 :OUT VLBIT := '0' SIGNAL g1 :OUT VLBIT := '0' SIGNAL w :OUT VLBIT := '0') END arbiter_which ARCHITECTURE state_behavior OF arbiter_which IS TYPE states IS (wait_any,wait_d0,wait_d1,wait_d0_d1,wait_d1_d0) BEGIN main : PROCESS ( r0, r1, d0, d1 ) VARIABLE state : states := wait_any BEGIN IF (clr g0 <= g1 <= w <= state /= '1') THEN '0' '0' '0' := wait_any ELSE CASE state IS 9 CHAPTER 2. VHDL SOURCE CODE 10 WHEN wait_any => IF (r0'EVENT AND r1'EVENT) THEN w <= '0' g0 <= r0 AFTER delay state := wait_d0_d1 ELSIF (r0'EVENT) THEN w <= '0' g0 <= r0 AFTER delay state := wait_d0 ELSIF (r1'EVENT) THEN w <= '1' g1 <= r1 AFTER delay state := wait_d1 ELSE putline("*** Illegal Input to Arbiter END IF WHEN wait_d0 => IF (d0'EVENT AND r1'EVENT) THEN w <= '1' g1 <= r1 AFTER delay state := wait_d1 ELSIF (d0'EVENT) THEN state := wait_any ELSIF (r1'EVENT) THEN state := wait_d0_d1 ELSE putline("*** Illegal Input to Arbiter END IF WHEN wait_d1 => IF (d1'EVENT AND r0'EVENT) THEN w <= '0' g0 <= r0 AFTER delay state := wait_d0 ELSIF (d1'EVENT) THEN state := wait_any ELSIF (r0'EVENT) THEN state := wait_d1_d0 ELSE putline("*** Illegal Input to Arbiter END IF -- waiting for any request -- got both -- do r0 first -- else got r0 only -- or got r1 only -- no other choice in state WAIT_ANY ***") -- waiting for d0 or r1 -- got both -- assume d0 first -- got d0, go back to start -- else got r1 in state WAIT_D0 ***") -- waiting for d1 or r0 -- got both -- assume d1 first -- got d1, go back to start -- else got r0 in state WAIT_D1 ***") WHEN wait_d0_d1 => -- waiting for d0, r1 in queue IF (d0'EVENT) THEN w <= '1' -- d0 is only acceptible event g1 <= r1 AFTER delay state := wait_d1 ELSE putline("*** Illegal Input to Arbiter in state WAIT_D0_D1 ***") END IF WHEN wait_d1_d0 => -- waiting for d1, r0 in queue 2.1. ARBITER WHICH.VHD 11 IF (d1'EVENT) THEN w <= '0' -- d0 is only acceptible event g0 <= r0 AFTER delay state := wait_d0 ELSE putline("*** Illegal Input to Arbiter in state WAIT_D1_D0 ***") END IF END CASE END IF END PROCESS main END state_behavior -- state CHAPTER 2. VHDL SOURCE CODE 12 2.2 arith unit.vhd USE work.p_constants.ALL USE work.p_arith.ALL USE work.p_output.ALL ---- This unit handles the arithmetic instructions. Currently, there is only ---- one of these units. More could be used, but a separate carry bit is ---- maintained internally to each unit. ---------------------- The EXTRA input was added to provide last-result-reuse and to eliminate zero values of op_a for immediate instructions. The bit usage is: EXTRA(0) EXTRA(1) EXTRA(2) EXTRA(3) = = = = reuseA reuseB reuseD zeroA (unused) ENTITY arith_unit IS GENERIC( delay: TIME := 100 ps ) PORT( SIGNAL clr : IN SIGNAL rin : IN SIGNAL ain : OUT SIGNAL tellme : IN SIGNAL tag : IN SIGNAL dest : IN SIGNAL opcode : IN SIGNAL op_a : IN SIGNAL op_b : IN SIGNAL d_req : OUT SIGNAL d_ack : IN SIGNAL done : OUT SIGNAL rout : OUT SIGNAL aout : IN SIGNAL res : OUT SIGNAL rq_req : OUT SIGNAL rq_ack : IN SIGNAL rq : OUT SIGNAL extra : IN END arith_unit VLBIT VLBIT VLBIT VLBIT VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT_1D (7 DOWNTO 0) (4 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (87 DOWNTO 0) (36 DOWNTO 0) (31 DOWNTO 0) (3 DOWNTO 0) ) ARCHITECTURE behavior OF arith_unit IS BEGIN main : PROCESS VARIABLE debug : BOOLEAN := FALSE -- display everything --- factors affecting response time VARIABLE VARIABLE VARIABLE VARIABLE delay_add delay_sub delay_cmp delay_div : : : : TIME TIME TIME TIME := := := := 100 100 100 100 ps ps ps ps 2.2. ARITH UNIT.VHD 13 VARIABLE delay_mul : TIME := 100 ps VARIABLE delay_to_use : TIME -- scratch for culumative time --- constants CONSTANT MINOR_add CONSTANT MINOR_sub CONSTANT MINOR_div : INTEGER := 1 : INTEGER := 2 : INTEGER := 3 --- output variables VARIABLE v_rout VARIABLE v_rq_req VARIABLE v_d_req : VLBIT : VLBIT : VLBIT --- internal variables VARIABLE index VARIABLE status VARIABLE minor : INTEGER : INTEGER : INTEGER VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE : : : : : Av Bv result lastresult bigresult VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VARIABLE Ai VARIABLE Bi VARIABLE Ri : INTEGER : INTEGER : INTEGER VARIABLE carry : VLBIT (31 (31 (31 (31 (33 DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO 0) 0) 0) 0) 0) --- scratch variables VARIABLE use_carry_in VARIABLE use_carry_out : BOOLEAN : BOOLEAN VARIABLE VARIABLE VARIABLE VARIABLE : : : : tmpi tmpv arg1 arg2 INTEGER VLBIT_1D (31 DOWNTO 0) VLBIT_1D (31 DOWNTO 0) VLBIT_1D (31 DOWNTO 0) --- statistics VARIABLE s_arith_rin VARIABLE s_mul VARIABLE s_div : INTEGER : INTEGER : INTEGER CHAPTER 2. VHDL SOURCE CODE 14 BEGIN --- If clear is asserted, reset everything and stick here. IF clr /= '1' THEN -- reset to beginning v_rout := '0' v_rq_req := '0' v_d_req := '0' carry := '0' arg1 := ZERO(31 DOWNTO 0) arg2 := ZERO(31 DOWNTO 0) ain <= '0' d_req <= v_d_req done <= ZERO(87 DOWNTO 0) rout <= v_rout res <= ZERO(36 DOWNTO 0) rq_req <= v_rq_req rq <= ZERO(31 DOWNTO 0) s_arith_rin := 0 s_mul := 0 s_div := 0 WAIT UNTIL clr = '1' ELSE -- only wakeup event is RIN status := STATUS_done minor := 0 --------- -- assume it will work This stuff had to be encoded by hand. I could have written a Perl script to do it, but it would have taken longer than doing it manually. This stuff shouldn't change that much (I hope). I also made some assumptions about unused bits, which is probably okay. delay_to_use := delay -- default is one gate --- I don't bother to compute anything if I'm just going to throw the --- result away. IF dest /= REG_R0 THEN -- only if worth doing s_arith_rin := s_arith_rin + 1 index := op2index( opcode ) -- identify instruction 2.2. ARITH UNIT.VHD 15 --- determine operand sources IF extra(0)='1' THEN Av := lastresult ELSE Av := op_a END IF IF index <= 31 THEN -- immediate --- All Immediate operands are zero-extended (this could change). Bv := ZERO(31 DOWNTO 16) & opcode(15 DOWNTO 0) ELSE -- triadic IF extra(1)='1' THEN Bv := lastresult ELSE Bv := op_b END IF END IF Ai := v1d2int( Av ) Bi := v1d2int( Bv ) --- determine carry usage use_carry_in := FALSE use_carry_out := FALSE IF ( index = 40 OR -index = 41 OR -index = 46 OR -index = 47 ) -THEN use_carry_in := vlb2boo( opcode(9) ) use_carry_out := vlb2boo( opcode(8) ) END IF add rd,ra,rb addu rd,ra,rb sub rd,ra,rb subu rd,ra,rb IF debug THEN puthexline("op_a is ",Ai) puthexline("op_b is ",Bi) putline("use_carry_in is ",use_carry_in) putline("use_carry_out is ",use_carry_out) END IF --- now, do the operation CASE index IS WHEN 8 | 40 => IF debug THEN -- add CHAPTER 2. VHDL SOURCE CODE 16 putline("ADD") END IF delay_to_use := delay_add IF use_carry_in THEN bigresult := add32( Av, Bv, carry ) ELSE bigresult := add32( Av, Bv, '0' ) END IF --- Overflow is possible, so check for it. IF bigresult(33) = '1' THEN status := STATUS_overflow minor := MINOR_add arg1 := Av arg2 := Bv ELSE -- overflow exception -- report it -- no exception IF use_carry_out THEN carry := bigresult(32) END IF -- save carry if enabled result := bigresult(31 DOWNTO 0) END IF WHEN 9 | 41 => -- addu IF debug THEN putline("ADDU") END IF delay_to_use := delay_add --- Just do it. No faults. IF use_carry_in THEN bigresult := add32( Av, Bv, carry ) ELSE bigresult := add32( Av, Bv, '0' ) END IF IF use_carry_out THEN carry := bigresult(32) END IF result := bigresult(31 DOWNTO 0) -- save carry if enabled 2.2. ARITH UNIT.VHD WHEN 10 | 42 => 17 -- div s_div := s_div + 1 IF debug THEN putline("DIV") END IF delay_to_use := delay_div --- Signed divide. Overflow is possible only for NEGMAX / -1. --- DivByZero is possible. IF Bi = 0 THEN -- divide by zero status := STATUS_int_div minor := MINOR_div arg1 := Av arg2 := Bv ELSIF Bi = -1 AND Av = NEGMAX THEN -- overflow status := STATUS_overflow minor := MINOR_div arg1 := Av arg2 := Bv ELSE Ri := Ai / Bi result := int2v1d( Ri ) -- just do it -- do it -- save it END IF WHEN 11 | 43 => -- divu s_div := s_div + 1 IF debug THEN putline("DIVU") END IF delay_to_use := delay_div --- Unsigned divide. DivByZero is possible, but overflow is not. IF Bi = 0 THEN status := STATUS_int_div minor := MINOR_div -- divide by zero CHAPTER 2. VHDL SOURCE CODE 18 arg1 := Av arg2 := Bv ELSE -- just do it result := divum( Av, Bv ) -- treat as unsigned values END IF WHEN 12 | 44 => -- mul s_mul := s_mul + 1 IF debug THEN putline("MUL") END IF delay_to_use := delay_mul --- Just do it. No faults. --- Shouldn't this be pipelined? How deep? Ri := Ai * Bi result := int2v1d( Ri ) WHEN 13 | 45 => -- cmp IF debug THEN putline("CMP") END IF delay_to_use := delay_cmp --- Do all sorts of comparisons. No faults. result := ZERO(31 DOWNTO 0) -- initialize result(11) := boo2vlb( Av >= Bv ) result(10) := boo2vlb( Av < Bv ) result(9) := boo2vlb( Av <= Bv ) result(8) := boo2vlb( Av > Bv ) ----- hs lo ls hi result(7) result(6) result(5) result(4) result(3) result(2) ------- ge lt le gt ne eq := := := := := := boo2vlb( boo2vlb( boo2vlb( boo2vlb( boo2vlb( boo2vlb( Ai Ai Ai Ai Ai Ai >= Bi ) < Bi ) <= Bi ) > Bi ) /= Bi ) = Bi ) 2.2. ARITH UNIT.VHD 19 WHEN 14 | 46 => -- sub IF debug THEN putline("SUB") END IF delay_to_use := delay_sub IF use_carry_in THEN bigresult := sub32( Av, Bv, carry ) ELSE bigresult := sub32( Av, Bv, '1' ) END IF --- Overflow is possible, so check for it. IF bigresult(33) = '1' THEN status := STATUS_overflow minor := MINOR_sub arg1 := Av arg2 := Bv ELSE -- overflow exception -- report it -- no exception IF use_carry_out THEN carry := bigresult(32) END IF -- save carry if enabled result := bigresult(31 DOWNTO 0) END IF WHEN 15 | 47 => -- subu IF debug THEN putline("SUBU") END IF delay_to_use := delay_sub --- Just do it. No faults. IF use_carry_in THEN bigresult := sub32( Av, Bv, carry ) ELSE bigresult := sub32( Av, Bv, '1' ) END IF IF use_carry_out THEN CHAPTER 2. VHDL SOURCE CODE 20 carry := bigresult(32) END IF -- save carry if enabled result := bigresult(31 DOWNTO 0) WHEN OTHERS => -- anything else putline("*** Illegal Opcode for Arith Unit ***") END CASE --- write output if any was produced. IF status = STATUS_done THEN IF debug THEN tmpi := v1d2int(result) puthexline("Result is ",tmpi) END IF IF dest = REG_R1 THEN rq <= result v_rq_req := NOT v_rq_req rq_req <= v_rq_req AFTER delay_to_use WAIT ON rq_ack ELSE res <= dest & result lastresult := result IF debug THEN puthexline("latched ",tmpi) END IF v_rout := NOT v_rout rout <= v_rout AFTER delay_to_use -- write it out WAIT ON aout END IF END IF END IF -- produce a result --- signal completion of this instruction IF tellme = '1' THEN -- only if needed 2.2. ARITH UNIT.VHD 21 tmpi := status + 256 * minor tmpv := int2v1d( tmpi ) done <= arg1 & arg2 & tmpv(15 DOWNTO 0) & tag IF debug THEN puthexline("Sending status ",tmpi) END IF v_d_req := NOT v_d_req d_req <= v_d_req AFTER delay WAIT ON d_ack END IF ain <= rin AFTER delay -- done with this event IF debug THEN putline("Done with this instruction") END IF END IF -- clr not asserted WAIT ON clr, rin -- wait for next event END PROCESS main END behavior CHAPTER 2. VHDL SOURCE CODE 22 2.3 branch unit.vhd USE work.p_constants.ALL USE work.p_output.ALL ---- The branch_unit computes branch targets for the IF Unit. It may place the ---- result in either the Branch Queue or the Exception Branch Queue. If the ---- branch will be taken, it places the address on the Prefetch Queue. ------------------------------- The EXTRA input was added to provide last-result-reuse and to elminate zero values of op_a for immediate instructions. The bit usage is: EXTRA(0) EXTRA(1) EXTRA(2) EXTRA(3) = = = = reuseA reuseB reuseD zeroA (unused) The branch unit doesn't need it for anything, since it doesn't generate results for the register file. ENTITY branch_unit IS GENERIC( delay: TIME := 100 ps ) PORT( SIGNAL clr : IN SIGNAL rin : IN SIGNAL ain : OUT SIGNAL tellme : IN SIGNAL tag : IN SIGNAL dest : IN SIGNAL pc : IN SIGNAL opcode : IN SIGNAL op_a : IN SIGNAL op_b : IN SIGNAL cr0 : IN SIGNAL d_req : OUT SIGNAL d_ack : IN SIGNAL done : OUT SIGNAL br_req : OUT SIGNAL br_ack : IN SIGNAL br : OUT SIGNAL xbr_req : OUT SIGNAL xbr_ack : IN SIGNAL xbr : OUT SIGNAL pf_req : OUT SIGNAL pf_ack : IN SIGNAL pf : OUT SIGNAL extra : IN END branch_unit VLBIT VLBIT VLBIT VLBIT VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT_1D ARCHITECTURE behavior OF branch_unit IS BEGIN (7 DOWNTO 0) (4 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (87 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (3 DOWNTO 0) ) 2.3. BRANCH UNIT.VHD 23 main : PROCESS VARIABLE debug : BOOLEAN := FALSE -- display everything --- factors affecting response time VARIABLE VARIABLE VARIABLE VARIABLE delay_abs delay_rel delay_cond_abs delay_cond_rel VARIABLE delay_to_use : : : : TIME TIME TIME TIME := := := := 100 100 100 100 : TIME ps ps ps ps -- scratch for culumative time --- output variables VARIABLE VARIABLE VARIABLE VARIABLE v_pf_req v_d_req v_br_req v_xbr_req : : : : VLBIT VLBIT VLBIT VLBIT : : : : : INTEGER INTEGER INTEGER VLBIT_1D( 30 DOWNTO 0) BOOLEAN --- internal variables VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE index A B addr taken --- scratch variables VARIABLE tmpv VARIABLE tmpi VARIABLE tmpb : VLBIT_1D( 31 DOWNTO 0) : INTEGER : VLBIT --- statistics VARIABLE VARIABLE VARIABLE VARIABLE s_branch_rin s_taken s_relative s_indirect : : : : INTEGER INTEGER INTEGER INTEGER BEGIN --- If clear is asserted, reset everything and stick here. IF clr /= '1' THEN v_pf_req := '0' v_d_req := '0' -- reset to beginning CHAPTER 2. VHDL SOURCE CODE 24 v_br_req := '0' v_xbr_req := '0' ain <= '0' pf_req <= v_pf_req pf <= ZERO(31 DOWNTO 0) d_req <= v_d_req tmpv := ZERO(31 DOWNTO 0) done <= ZERO(87 DOWNTO 0) br_req <= v_br_req br <= ZERO(31 DOWNTO 0) xbr_req <= v_xbr_req xbr <= ZERO(31 DOWNTO 0) s_branch_rin := 0 s_taken := 0 s_indirect := 0 s_relative := 0 WAIT UNTIL clr = '1' ELSE -- only wakeup event is RIN s_branch_rin := s_branch_rin + 1 --------- This stuff had to be encoded by hand. I could have written a Perl script to do it, but it would have taken longer than doing it manually. This stuff shouldn't change that much (I hope). I also made some assumptions about unused bits, which is probably okay. delay_to_use := delay IF debug THEN tmpi := v1d2int(op_a) puthexline("op_a is ",tmpi) END IF index := op2index( opcode ) IF index = 87 THEN -- LDBR is special IF debug THEN tmpi := 4 * v1d2int(op_a(31 DOWNTO 2)) puthex("LDBR <= ",tmpi) tmpb := op_a(1) putline(" ",tmpb) END IF br <= op_a v_br_req := NOT v_br_req br_req <= v_br_req AFTER delay -- always use Branch Queue IF op_a(1) = '1' THEN -- do prefetch as well -- write it 2.3. BRANCH UNIT.VHD pf <= op_a v_pf_req := NOT v_pf_req pf_req <= v_pf_req AFTER delay 25 -- write it out -- and wait for both ACKs WAIT UNTIL pf_ack = v_pf_req AND br_ack = v_br_req ELSE WAIT ON br_ack -- no prefetch -- just wait on BR_ACK END IF ELSE -- other instructions CASE index IS WHEN 16 => -- bb0 n,ra,imm16 s_relative := s_relative + 1 delay_to_use := delay_cond_rel --- see if it's taken tmpi := v1d2int( opcode(25 DOWNTO 21) ) -- which bit taken := NOT vlb2boo( op_a(tmpi) ) -- is it set? --- compute word address addr := add2c( pc(31 DOWNTO 2), opcode( 15 DOWNTO 0) ) WHEN 17 => -- bb1 n,ra,imm16 s_relative := s_relative + 1 delay_to_use := delay_cond_rel --- see if it's taken tmpi := v1d2int( opcode(25 DOWNTO 21) ) -- which bit taken := vlb2boo( op_a(tmpi) ) -- is it set? --- compute word address addr := add2c( pc(31 DOWNTO 2), opcode( 15 DOWNTO 0) ) WHEN 18 => -- bxx ra,imm16 CHAPTER 2. VHDL SOURCE CODE 26 s_relative := s_relative + 1 delay_to_use := delay_cond_rel --- see if it's taken tmpi := v1d2int( op_a ) -- get ra IF ( ( (opcode(21) = '1') AND (tmpi > 0 ) ) OR ( (opcode(22) = '1') AND (tmpi = 0 ) ) OR ( (opcode(23) = '1') AND (tmpi < 0 ) ) ) THEN taken := TRUE ELSE taken := FALSE END IF --- compute word address addr := add2c( pc(31 DOWNTO 2), opcode( 15 DOWNTO 0) ) WHEN 19 => -- br imm26 s_relative := s_relative + 1 delay_to_use := delay_rel --- it's always taken taken := TRUE --- compute word address addr := add2c( pc(31 DOWNTO 2), opcode( 25 DOWNTO 0) ) WHEN 48 => -- bb0 n,ra,rb s_indirect := s_indirect + 1 delay_to_use := delay_cond_abs --- see if it's taken tmpi := v1d2int( opcode(25 DOWNTO 21) ) -- which bit taken := NOT vlb2boo( op_a(tmpi) ) -- is it set? --- compute word address addr := '0' & op_b( 31 DOWNTO 2 ) WHEN 49 => -- bb1 n,ra,rb 2.3. BRANCH UNIT.VHD 27 s_indirect := s_indirect + 1 delay_to_use := delay_cond_abs --- see if it's taken tmpi := v1d2int( opcode(25 DOWNTO 21) ) -- which bit taken := vlb2boo( op_a(tmpi) ) -- is it set? --- compute word address addr := '0' & op_b( 31 DOWNTO 2 ) WHEN 50 => -- bxx ra,rb s_indirect := s_indirect + 1 delay_to_use := delay_cond_abs --- see if it's taken tmpi := v1d2int( op_a ) -- get ra IF ( ( (opcode(21) = '1') AND (tmpi > 0 ) ) OR ( (opcode(22) = '1') AND (tmpi = 0 ) ) OR ( (opcode(23) = '1') AND (tmpi < 0 ) ) ) THEN taken := TRUE ELSE taken := FALSE END IF --- compute word address addr := '0' & op_b( 31 DOWNTO 2 ) WHEN 51 => s_indirect := s_indirect + 1 delay_to_use := delay_abs --- it's always taken taken := TRUE --- compute word address addr := '0' & op_b( 31 DOWNTO 2 ) -- br rb CHAPTER 2. VHDL SOURCE CODE 28 WHEN OTHERS => -- anything else putline("*** Illegal Opcode for Branch Unit ***") END CASE --- write output on correct branch queue tmpb := boo2vlb( taken ) tmpv := (addr(29 DOWNTO 0) & tmpb & '0') -- compute branch target IF taken THEN -- do prefetch if needed s_taken := s_taken + 1 pf <= tmpv v_pf_req := NOT v_pf_req pf_req <= v_pf_req AFTER delay_to_use -- write it END IF ------------------------- I had to modify the tag meaning slightly. Originally, all branch instructions simply used the current value of cr0(Excp_Enable) to determine which Branch queue to place the target in. However, branch instructions do not fault, so if an interrupt is noticed after the branch has been issued but before it has completed, the target goes down the wrong pipe. Rather than add another bit to the existing FIFOs, I just modified the tag value so that bit 7 is used to indicate the queue in use when the instruction was issued. This doesn't affect the memory unit since it always has to report its status and the dispatch unit will wait for it to do so before handling exceptions. Only the branch unit uses the new tag bit for anything. IF tag(7) = '1' THEN -- use normal branch queue IF debug THEN tmpi := 4 * v1d2int(tmpv(31 DOWNTO 2)) puthex("BR <= ",tmpi) putline(" ",tmpb) END IF br <= tmpv v_br_req := NOT v_br_req br_req <= v_br_req AFTER delay_to_use IF taken THEN -- must ACK both WAIT UNTIL pf_ack = v_pf_req AND br_ack = v_br_req ELSE WAIT ON br_ack -- just BR_ACK END IF 2.3. BRANCH UNIT.VHD ELSE 29 -- use exception branch queue IF debug THEN tmpi := 4 * v1d2int(tmpv(31 DOWNTO 2)) puthex("XBR <= ",tmpi) putline(" ",tmpb) END IF xbr <= tmpv v_xbr_req := NOT v_xbr_req xbr_req <= v_xbr_req AFTER delay_to_use IF taken THEN -- must ACK both WAIT UNTIL pf_ack = v_pf_req AND xbr_ack = v_xbr_req ELSE WAIT ON xbr_ack -- just XBR_ACK END IF END IF END IF -- not LDBR instruction --- signal completion of this instruction IF tellme = '1' THEN -- only if needed tmpv := int2v1d( STATUS_done ) done(15 DOWNTO 0) <= tmpv(7 DOWNTO 0) & '0' & tag(6 DOWNTO 0) v_d_req := NOT v_d_req d_req <= v_d_req AFTER delay WAIT ON d_ack END IF ain <= rin AFTER delay -- done with this event END IF -- clr not asserted WAIT ON clr, rin -- wait for next event END PROCESS main END behavior CHAPTER 2. VHDL SOURCE CODE 30 2.4 control unit.vhd USE work.p_constants.ALL USE work.p_output.ALL ---- The control_unit handles those few instructions which don't really fit ---- anywhere else. Control register access is done here, as is read access ---- for the Branch Queue and PC value. ---------------------- The EXTRA input was added to provide last-result-reuse and to elminate zero values of op_a for immediate instructions. The bit usage is: EXTRA(0) EXTRA(1) EXTRA(2) EXTRA(3) = = = = reuseA reuseB reuseD zeroA (unused) ENTITY control_unit IS GENERIC( delay: TIME := 100 ps ) PORT( SIGNAL clr : IN SIGNAL rin : IN SIGNAL ain : OUT SIGNAL tellme : IN SIGNAL tag : IN SIGNAL dest : IN SIGNAL pc : IN SIGNAL opcode : IN SIGNAL op_a : IN SIGNAL op_b : IN SIGNAL d_req : OUT SIGNAL d_ack : IN SIGNAL done : OUT SIGNAL rout : OUT SIGNAL aout : IN SIGNAL res : OUT SIGNAL rq_req : OUT SIGNAL rq_ack : IN SIGNAL rq : OUT SIGNAL putcr_req : OUT SIGNAL putcr_ack : IN SIGNAL putcr : OUT SIGNAL cr_num : OUT SIGNAL getcr_req : OUT SIGNAL getcr_ack : IN SIGNAL getcr : IN SIGNAL extra : IN END control_unit VLBIT VLBIT VLBIT VLBIT VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT_1D ARCHITECTURE behavior OF control_unit IS BEGIN main : PROCESS (7 DOWNTO 0) (4 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (87 DOWNTO 0) (36 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (9 DOWNTO 0) (31 DOWNTO 0) (3 DOWNTO 0) ) 2.4. CONTROL UNIT.VHD VARIABLE debug 31 : BOOLEAN := FALSE --- factors affecting response time VARIABLE delay_mvpc : TIME := 100 ps -- this is the only hard one --- output variables VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE v_rout v_rq_req v_d_req v_putcr_req v_getcr_req : : : : : VLBIT VLBIT VLBIT VLBIT VLBIT : : : : INTEGER VLBIT_1D(31 DOWNTO 0) VLBIT_1D(31 DOWNTO 0) VLBIT_1D(31 DOWNTO 0) --- internal variables VARIABLE VARIABLE VARIABLE VARIABLE index op_aa op_bb lastresult --- scratch variables VARIABLE tmpi VARIABLE tmpv : INTEGER : VLBIT_1D (31 DOWNTO 0) --- statistics VARIABLE VARIABLE VARIABLE VARIABLE s_mvpc s_getcr s_putcr s_mvbr : : : : INTEGER INTEGER INTEGER INTEGER BEGIN --- If clear is asserted, reset everything and stick here. IF clr /= '1' THEN v_rout := '0' v_rq_req := '0' v_d_req := '0' v_putcr_req := '0' v_getcr_req := '0' ain <= '0' d_req <= v_d_req done <= ZERO(87 DOWNTO 0) -- reset to beginning CHAPTER 2. VHDL SOURCE CODE 32 rout <= v_rout res <= ZERO(36 DOWNTO 0) rq_req <= v_rq_req rq <= ZERO(31 DOWNTO 0) putcr_req <= v_putcr_req putcr <= ZERO(31 DOWNTO 0) cr_num <= ZERO(9 DOWNTO 0) getcr_req <= v_getcr_req s_mvpc := 0 s_putcr := 0 s_getcr := 0 s_mvbr := 0 WAIT UNTIL clr = '1' ELSE --------- -- only wakeup event is RIN This stuff had to be encoded by hand. I could have written a Perl script to do it, but it would have taken longer than doing it manually. This stuff shouldn't change that much (I hope). I also made some assumptions about unused bits, which is probably okay. IF extra(0)='1' THEN op_aa := lastresult ELSE op_aa := op_a END IF -- reuse op_a result IF extra(1)='1' THEN op_bb := lastresult ELSE op_bb := op_b END IF -- reuse op_b IF debug THEN tmpi := v1d2int(op_aa) puthexline("op_a is ",tmpi) tmpi := v1d2int(op_bb) puthexline("op_b is ",tmpi) END IF index := op2index( opcode ) CASE index IS WHEN 20 => -- mvpc rd,imm16 2.4. CONTROL UNIT.VHD 33 IF dest /= REG_R0 THEN -- if worth doing s_mvpc := s_mvpc + 1 --- compute word address tmpv(30 DOWNTO 0) := add2c( pc(31 DOWNTO 2), opcode( 15 DOWNTO 0) ) IF dest = REG_R1 THEN rq <= tmpv(29 DOWNTO 0) & ('0','0') v_rq_req := NOT v_rq_req -- write it out rq_req <= v_rq_req AFTER delay_mvpc WAIT ON rq_ack ELSE res <= dest & tmpv(29 DOWNTO 0) & ('0','0') lastresult := tmpv(29 DOWNTO 0) & ('0','0') IF debug THEN tmpi := v1d2int(lastresult) puthexline("latched ",tmpi) END IF v_rout := NOT v_rout rout <= v_rout AFTER delay_mvpc -- write it out WAIT ON aout END IF END IF WHEN 92 | 93 => IF dest /= REG_R0 THEN -- done with it -- getcr rd,cr -- if worth doing s_getcr := s_getcr + 1 IF index = 92 THEN -- direct cr number cr_num <= opcode(9 DOWNTO 0) ELSE cr_num <= op_bb(9 DOWNTO 0) -- indirect control register END IF v_getcr_req := NOT v_getcr_req getcr_req <= v_getcr_req AFTER delay WAIT ON getcr_ack CHAPTER 2. VHDL SOURCE CODE 34 --- NOTE: This would normally need to be four-phase, but since this --- is the only unit which can read the control registers, it should --- work fine. --- write it out IF dest = REG_R1 THEN rq <= getcr v_rq_req := NOT v_rq_req rq_req <= v_rq_req AFTER delay -- write it out WAIT ON rq_ack ELSE res <= dest & getcr lastresult := getcr IF debug THEN tmpi := v1d2int(lastresult) puthexline("latched ",tmpi) END IF v_rout := NOT v_rout rout <= v_rout AFTER delay -- write it out WAIT ON aout END IF END IF WHEN 94 | 95 => -- done with it -- putcr cr,ra s_putcr := s_putcr + 1 putcr <= op_aa IF index = 94 THEN cr_num <= opcode(9 DOWNTO 0) ELSE cr_num <= op_bb(9 DOWNTO 0) END IF v_putcr_req := NOT v_putcr_req putcr_req <= v_putcr_req AFTER delay -- write out data -- direct cr number -- indirect control register WAIT ON putcr_ack WHEN 86 => -- mvbr rd 2.4. CONTROL UNIT.VHD 35 IF dest /= REG_R0 THEN -- if worth doing s_mvbr := s_mvbr + 1 IF dest = REG_R1 THEN rq <= pc v_rq_req := NOT v_rq_req rq_req <= v_rq_req AFTER delay -- write it out WAIT ON rq_ack ELSE res <= dest & pc lastresult := pc IF debug THEN tmpi := v1d2int(lastresult) puthexline("latched ",tmpi) END IF v_rout := NOT v_rout rout <= v_rout AFTER delay -- write it out WAIT ON aout END IF END IF -- done with it WHEN OTHERS => -- anything else putline("*** Illegal Opcode for Control Unit ***") END CASE --- signal completion of this instruction IF tellme = '1' THEN -- only if needed tmpv := int2v1d( STATUS_done ) done <= ZERO(87 DOWNTO 16) & tmpv(7 DOWNTO 0) & tag v_d_req := NOT v_d_req d_req <= v_d_req AFTER delay WAIT ON d_ack END IF CHAPTER 2. VHDL SOURCE CODE 36 ain <= rin AFTER delay -- done with this event END IF -- clr not asserted WAIT ON clr, rin -- wait for next event END PROCESS main END behavior 2.5. CPX128.VHD 37 2.5 cpx128.vhd USE work.p_constants.ALL ---------------------- This is used to capture the data for a large FIFO. This is just a ViewSim performance hack. Passing the data through several latches uses an incredible number of signals and nets, so I use this VHDL program to store the data, and I use an external delay chain to model the time behavior. While this models the C/CD P/PD interface, the CD and PD pins are absent. This unit takes zero time. External delays must be used to model the done responses. ENTITY cpx128 IS PORT (SIGNAL clr SIGNAL c SIGNAL p SIGNAL i SIGNAL o END cpx128 :IN :IN :IN :IN :OUT VLBIT VLBIT VLBIT VLBIT_1D(127 DOWNTO 0) VLBIT_1D(127 DOWNTO 0)) ARCHITECTURE behavior OF cpx128 IS BEGIN main : PROCESS CONSTANT MaxDepth : INTEGER := 16 TYPE pipe_type IS ARRAY( 0 TO MaxDepth ) OF VLBIT_1D(127 DOWNTO 0) VARIABLE pipe : pipe_type VARIABLE head VARIABLE tail VARIABLE count : INTEGER : INTEGER : INTEGER VARIABLE v_cd VARIABLE v_pd : VLBIT : VLBIT VARIABLE s_maxusage : INTEGER VARIABLE s_total_count : INTEGER VARIABLE s_total_times : INTEGER BEGIN IF (clr /= '1') THEN s_maxusage := 0 s_total_count := 0 s_total_times := 0 head := 0 tail := 0 count := 0 -- only for error checking -- not for output -- for statistics CHAPTER 2. VHDL SOURCE CODE 38 v_cd := '0' v_pd := '0' o <= ZERO(127 DOWNTO 0) WAIT UNTIL clr = '1' ELSE IF c'EVENT THEN -- data coming in IF c = v_cd THEN putline("*** Handshake violation on Capture ***") END IF IF ( count < MaxDepth ) THEN -- latch incoming data pipe(tail) := i tail := tail + 1 IF tail >= MaxDepth THEN tail := 0 END IF count := count + 1 s_total_count := s_total_count + count s_total_times := s_total_times + 1 IF count > s_maxusage THEN s_maxusage := count END IF -- keep track of maxium v_cd := NOT v_cd -- remember this event END IF END IF IF p'EVENT THEN -- want data on output IF count = 0 OR p = v_pd THEN putline("*** Handshake violation on Pass ***") END IF head := head + 1 IF head >= MaxDepth THEN head := 0 END IF count := count - 1 -- so I can get rid of it 2.5. CPX128.VHD v_pd := NOT v_pd 39 -- remember this event END IF IF count = 0 THEN pipe(head) := i END IF -- copy through if nothing o <= pipe(head) -- show latest data END IF WAIT ON clr, c, p END PROCESS main END behavior -- clr not asserted CHAPTER 2. VHDL SOURCE CODE 40 2.6 cpx18.vhd USE work.p_constants.ALL ---------------------- This is used to capture the data for a large FIFO. This is just a ViewSim performance hack. Passing the data through several latches uses an incredible number of signals and nets, so I use this VHDL program to store the data, and I use an external delay chain to model the time behavior. While this models the C/CD P/PD interface, the CD and PD pins are absent. This unit takes zero time. External delays must be used to model the done responses. ENTITY cpx18 IS PORT (SIGNAL clr SIGNAL c SIGNAL p SIGNAL i SIGNAL o END cpx18 :IN :IN :IN :IN :OUT VLBIT VLBIT VLBIT VLBIT_1D(17 DOWNTO 0) VLBIT_1D(17 DOWNTO 0)) ARCHITECTURE behavior OF cpx18 IS BEGIN main : PROCESS CONSTANT MaxDepth : INTEGER := 16 TYPE pipe_type IS ARRAY( 0 TO MaxDepth ) OF VLBIT_1D(17 DOWNTO 0) VARIABLE pipe : pipe_type VARIABLE head VARIABLE tail VARIABLE count : INTEGER : INTEGER : INTEGER VARIABLE v_cd VARIABLE v_pd : VLBIT : VLBIT VARIABLE s_maxusage : INTEGER VARIABLE s_total_count : INTEGER VARIABLE s_total_times : INTEGER BEGIN IF (clr /= '1') THEN s_maxusage := 0 s_total_count := 0 s_total_times := 0 head := 0 tail := 0 count := 0 -- only for error checking -- not for output -- for statistics 2.6. CPX18.VHD 41 v_cd := '0' v_pd := '0' o <= ZERO(17 DOWNTO 0) WAIT UNTIL clr = '1' ELSE IF c'EVENT THEN -- data coming in IF c = v_cd THEN putline("*** Handshake violation on Capture ***") END IF IF ( count < MaxDepth ) THEN -- latch incoming data pipe(tail) := i tail := tail + 1 IF tail >= MaxDepth THEN tail := 0 END IF count := count + 1 s_total_count := s_total_count + count s_total_times := s_total_times + 1 IF count > s_maxusage THEN s_maxusage := count END IF -- keep track of maxium v_cd := NOT v_cd -- remember this event END IF END IF IF p'EVENT THEN -- want data on output IF count = 0 OR p = v_pd THEN putline("*** Handshake violation on Pass ***") END IF head := head + 1 IF head >= MaxDepth THEN head := 0 END IF count := count - 1 -- so I can get rid of it CHAPTER 2. VHDL SOURCE CODE 42 v_pd := NOT v_pd -- remember this event END IF IF count = 0 THEN pipe(head) := i END IF -- copy through if nothing o <= pipe(head) -- show latest data END IF WAIT ON clr, c, p END PROCESS main END behavior -- clr not asserted 2.7. CPX32.VHD 43 2.7 cpx32.vhd USE work.p_constants.ALL ---------------------- This is used to capture the data for a large FIFO. This is just a ViewSim performance hack. Passing the data through several latches uses an incredible number of signals and nets, so I use this VHDL program to store the data, and I use an external delay chain to model the time behavior. While this models the C/CD P/PD interface, the CD and PD pins are absent. This unit takes zero time. External delays must be used to model the done responses. ENTITY cpx32 IS PORT (SIGNAL clr SIGNAL c SIGNAL p SIGNAL i SIGNAL o END cpx32 :IN :IN :IN :IN :OUT VLBIT VLBIT VLBIT VLBIT_1D(31 DOWNTO 0) VLBIT_1D(31 DOWNTO 0)) ARCHITECTURE behavior OF cpx32 IS BEGIN main : PROCESS CONSTANT MaxDepth : INTEGER := 16 TYPE pipe_type IS ARRAY( 0 TO MaxDepth ) OF VLBIT_1D(31 DOWNTO 0) VARIABLE pipe : pipe_type VARIABLE head VARIABLE tail VARIABLE count : INTEGER : INTEGER : INTEGER VARIABLE v_cd VARIABLE v_pd : VLBIT : VLBIT VARIABLE s_maxusage : INTEGER VARIABLE s_total_count : INTEGER VARIABLE s_total_times : INTEGER BEGIN IF (clr /= '1') THEN s_maxusage := 0 s_total_count := 0 s_total_times := 0 head := 0 tail := 0 count := 0 -- only for error checking -- not for output -- for statistics CHAPTER 2. VHDL SOURCE CODE 44 v_cd := '0' v_pd := '0' o <= ZERO(31 DOWNTO 0) WAIT UNTIL clr = '1' ELSE IF c'EVENT THEN -- data coming in IF c = v_cd THEN putline("*** Handshake violation on Capture ***") END IF IF ( count < MaxDepth ) THEN -- latch incoming data pipe(tail) := i tail := tail + 1 IF tail >= MaxDepth THEN tail := 0 END IF count := count + 1 s_total_count := s_total_count + count s_total_times := s_total_times + 1 IF count > s_maxusage THEN s_maxusage := count END IF -- keep track of maxium v_cd := NOT v_cd -- remember this event END IF END IF IF p'EVENT THEN -- want data on output IF count = 0 OR p = v_pd THEN putline("*** Handshake violation on Pass ***") END IF head := head + 1 IF head >= MaxDepth THEN head := 0 END IF count := count - 1 -- so I can get rid of it 2.7. CPX32.VHD v_pd := NOT v_pd 45 -- remember this event END IF IF count = 0 THEN pipe(head) := i END IF -- copy through if nothing o <= pipe(head) -- show latest data END IF WAIT ON clr, c, p END PROCESS main END behavior -- clr not asserted CHAPTER 2. VHDL SOURCE CODE 46 2.8 cpx3op.vhd USE work.p_constants.ALL ---------------------- This is used to capture the data for a large FIFO. This is just a ViewSim performance hack. Passing the data through several latches uses an incredible number of signals and nets, so I use this VHDL program to store the data, and I use an external delay chain to model the time behavior. While this models the C/CD P/PD interface, the CD and PD pins are absent. This unit takes zero time. External delays must be used to model the done responses. ENTITY cpx3op IS PORT (SIGNAL clr SIGNAL c SIGNAL p SIGNAL i SIGNAL o END cpx3op :IN :IN :IN :IN :OUT VLBIT VLBIT VLBIT VLBIT_1D(113 DOWNTO 0) VLBIT_1D(113 DOWNTO 0)) ARCHITECTURE behavior OF cpx3op IS BEGIN main : PROCESS CONSTANT MaxDepth : INTEGER := 16 TYPE pipe_type IS ARRAY( 0 TO MaxDepth ) OF VLBIT_1D(113 DOWNTO 0) VARIABLE pipe : pipe_type VARIABLE head VARIABLE tail VARIABLE count : INTEGER : INTEGER : INTEGER VARIABLE v_cd VARIABLE v_pd : VLBIT : VLBIT VARIABLE s_maxusage : INTEGER VARIABLE s_total_count : INTEGER VARIABLE s_total_times : INTEGER BEGIN IF (clr /= '1') THEN s_maxusage := 0 s_total_count := 0 s_total_times := 0 head := 0 tail := 0 count := 0 -- only for error checking -- not for output -- for statistics 2.8. CPX3OP.VHD 47 v_cd := '0' v_pd := '0' o <= ZERO(113 DOWNTO 0) WAIT UNTIL clr = '1' ELSE IF c'EVENT THEN -- data coming in IF c = v_cd THEN putline("*** Handshake violation on Capture ***") END IF IF ( count < MaxDepth ) THEN -- latch incoming data pipe(tail) := i tail := tail + 1 IF tail >= MaxDepth THEN tail := 0 END IF count := count + 1 s_total_count := s_total_count + count s_total_times := s_total_times + 1 IF count > s_maxusage THEN s_maxusage := count END IF -- keep track of maxium v_cd := NOT v_cd -- remember this event END IF END IF IF p'EVENT THEN -- want data on output IF count = 0 OR p = v_pd THEN putline("*** Handshake violation on Pass ***") END IF head := head + 1 IF head >= MaxDepth THEN head := 0 END IF count := count - 1 -- so I can get rid of it CHAPTER 2. VHDL SOURCE CODE 48 v_pd := NOT v_pd -- remember this event END IF IF count = 0 THEN pipe(head) := i END IF -- copy through if nothing o <= pipe(head) -- show latest data END IF WAIT ON clr, c, p END PROCESS main END behavior -- clr not asserted 2.9. CPX4OP.VHD 49 2.9 cpx4op.vhd USE work.p_constants.ALL ---------------------- This is used to capture the data for a large FIFO. This is just a ViewSim performance hack. Passing the data through several latches uses an incredible number of signals and nets, so I use this VHDL program to store the data, and I use an external delay chain to model the time behavior. While this models the C/CD P/PD interface, the CD and PD pins are absent. This unit takes zero time. External delays must be used to model the done responses. ENTITY cpx4op IS PORT (SIGNAL clr SIGNAL c SIGNAL p SIGNAL i SIGNAL o END cpx4op :IN :IN :IN :IN :OUT VLBIT VLBIT VLBIT VLBIT_1D(145 DOWNTO 0) VLBIT_1D(145 DOWNTO 0)) ARCHITECTURE behavior OF cpx4op IS BEGIN main : PROCESS CONSTANT MaxDepth : INTEGER := 16 TYPE pipe_type IS ARRAY( 0 TO MaxDepth ) OF VLBIT_1D(145 DOWNTO 0) VARIABLE pipe : pipe_type VARIABLE head VARIABLE tail VARIABLE count : INTEGER : INTEGER : INTEGER VARIABLE v_cd VARIABLE v_pd : VLBIT : VLBIT VARIABLE s_maxusage : INTEGER VARIABLE s_total_count : INTEGER VARIABLE s_total_times : INTEGER BEGIN IF (clr /= '1') THEN s_maxusage := 0 s_total_count := 0 s_total_times := 0 head := 0 tail := 0 count := 0 -- only for error checking -- not for output -- for statistics CHAPTER 2. VHDL SOURCE CODE 50 v_cd := '0' v_pd := '0' o <= ZERO(145 DOWNTO 0) WAIT UNTIL clr = '1' ELSE IF c'EVENT THEN -- data coming in IF c = v_cd THEN putline("*** Handshake violation on Capture ***") END IF IF ( count < MaxDepth ) THEN -- latch incoming data pipe(tail) := i tail := tail + 1 IF tail >= MaxDepth THEN tail := 0 END IF count := count + 1 s_total_count := s_total_count + count s_total_times := s_total_times + 1 IF count > s_maxusage THEN s_maxusage := count END IF -- keep track of maxium v_cd := NOT v_cd -- remember this event END IF END IF IF p'EVENT THEN -- want data on output IF count = 0 OR p = v_pd THEN putline("*** Handshake violation on Pass ***") END IF head := head + 1 IF head >= MaxDepth THEN head := 0 END IF count := count - 1 -- so I can get rid of it 2.9. CPX4OP.VHD v_pd := NOT v_pd 51 -- remember this event END IF IF count = 0 THEN pipe(head) := i END IF -- copy through if nothing o <= pipe(head) -- show latest data END IF WAIT ON clr, c, p END PROCESS main END behavior -- clr not asserted CHAPTER 2. VHDL SOURCE CODE 52 2.10 cpx5.vhd USE work.p_constants.ALL ---------------------- This is used to capture the data for a large FIFO. This is just a ViewSim performance hack. Passing the data through several latches uses an incredible number of signals and nets, so I use this VHDL program to store the data, and I use an external delay chain to model the time behavior. While this models the C/CD P/PD interface, the CD and PD pins are absent. This unit takes zero time. External delays must be used to model the done responses. ENTITY cpx5 IS PORT (SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL END cpx5 clr c p i o :IN :IN :IN :IN :OUT VLBIT VLBIT VLBIT VLBIT_1D(4 DOWNTO 0) VLBIT_1D(4 DOWNTO 0)) ARCHITECTURE behavior OF cpx5 IS BEGIN main : PROCESS CONSTANT MaxDepth : INTEGER := 16 TYPE pipe_type IS ARRAY( 0 TO MaxDepth ) OF VLBIT_1D(4 DOWNTO 0) VARIABLE pipe : pipe_type VARIABLE head VARIABLE tail VARIABLE count : INTEGER : INTEGER : INTEGER VARIABLE v_cd VARIABLE v_pd : VLBIT : VLBIT VARIABLE s_maxusage : INTEGER VARIABLE s_total_count : INTEGER VARIABLE s_total_times : INTEGER BEGIN IF (clr /= '1') THEN s_maxusage := 0 s_total_count := 0 s_total_times := 0 head := 0 tail := 0 count := 0 -- only for error checking -- not for output -- for statistics 2.10. CPX5.VHD 53 v_cd := '0' v_pd := '0' o <= ZERO(4 DOWNTO 0) WAIT UNTIL clr = '1' ELSE IF c'EVENT THEN -- data coming in IF c = v_cd THEN putline("*** Handshake violation on Capture ***") END IF IF ( count < MaxDepth ) THEN -- latch incoming data pipe(tail) := i tail := tail + 1 IF tail >= MaxDepth THEN tail := 0 END IF count := count + 1 s_total_count := s_total_count + count s_total_times := s_total_times + 1 IF count > s_maxusage THEN s_maxusage := count END IF -- keep track of maxium v_cd := NOT v_cd -- remember this event END IF END IF IF p'EVENT THEN -- want data on output IF count = 0 OR p = v_pd THEN putline("*** Handshake violation on Pass ***") END IF head := head + 1 IF head >= MaxDepth THEN head := 0 END IF count := count - 1 -- so I can get rid of it CHAPTER 2. VHDL SOURCE CODE 54 v_pd := NOT v_pd -- remember this event END IF IF count = 0 THEN pipe(head) := i END IF -- copy through if nothing o <= pipe(head) -- show latest data END IF WAIT ON clr, c, p END PROCESS main END behavior -- clr not asserted 2.11. CPX88.VHD 55 2.11 cpx88.vhd USE work.p_constants.ALL ---------------------- This is used to capture the data for a large FIFO. This is just a ViewSim performance hack. Passing the data through several latches uses an incredible number of signals and nets, so I use this VHDL program to store the data, and I use an external delay chain to model the time behavior. While this models the C/CD P/PD interface, the CD and PD pins are absent. This unit takes zero time. External delays must be used to model the done responses. ENTITY cpx88 IS PORT (SIGNAL clr SIGNAL c SIGNAL p SIGNAL i SIGNAL o END cpx88 :IN :IN :IN :IN :OUT VLBIT VLBIT VLBIT VLBIT_1D(87 DOWNTO 0) VLBIT_1D(87 DOWNTO 0)) ARCHITECTURE behavior OF cpx88 IS BEGIN main : PROCESS CONSTANT MaxDepth : INTEGER := 16 TYPE pipe_type IS ARRAY( 0 TO MaxDepth ) OF VLBIT_1D(87 DOWNTO 0) VARIABLE pipe : pipe_type VARIABLE head VARIABLE tail VARIABLE count : INTEGER : INTEGER : INTEGER VARIABLE v_cd VARIABLE v_pd : VLBIT : VLBIT VARIABLE s_maxusage : INTEGER VARIABLE s_total_count : INTEGER VARIABLE s_total_times : INTEGER BEGIN IF (clr /= '1') THEN s_maxusage := 0 s_total_count := 0 s_total_times := 0 head := 0 tail := 0 count := 0 -- only for error checking -- not for output -- for statistics CHAPTER 2. VHDL SOURCE CODE 56 v_cd := '0' v_pd := '0' o <= ZERO(87 DOWNTO 0) WAIT UNTIL clr = '1' ELSE IF c'EVENT THEN -- data coming in IF c = v_cd THEN putline("*** Handshake violation on Capture ***") END IF IF ( count < MaxDepth ) THEN -- latch incoming data pipe(tail) := i tail := tail + 1 IF tail >= MaxDepth THEN tail := 0 END IF count := count + 1 s_total_count := s_total_count + count s_total_times := s_total_times + 1 IF count > s_maxusage THEN s_maxusage := count END IF -- keep track of maxium v_cd := NOT v_cd -- remember this event END IF END IF IF p'EVENT THEN -- want data on output IF count = 0 OR p = v_pd THEN putline("*** Handshake violation on Pass ***") END IF head := head + 1 IF head >= MaxDepth THEN head := 0 END IF count := count - 1 -- so I can get rid of it 2.11. CPX88.VHD v_pd := NOT v_pd 57 -- remember this event END IF IF count = 0 THEN pipe(head) := i END IF -- copy through if nothing o <= pipe(head) -- show latest data END IF WAIT ON clr, c, p END PROCESS main END behavior -- clr not asserted CHAPTER 2. VHDL SOURCE CODE 58 2.12 cpx96.vhd USE work.p_constants.ALL ---------------------- This is used to capture the data for a large FIFO. This is just a ViewSim performance hack. Passing the data through several latches uses an incredible number of signals and nets, so I use this VHDL program to store the data, and I use an external delay chain to model the time behavior. While this models the C/CD P/PD interface, the CD and PD pins are absent. This unit takes zero time. External delays must be used to model the done responses. ENTITY cpx96 IS PORT (SIGNAL clr SIGNAL c SIGNAL p SIGNAL i SIGNAL o END cpx96 :IN :IN :IN :IN :OUT VLBIT VLBIT VLBIT VLBIT_1D(95 DOWNTO 0) VLBIT_1D(95 DOWNTO 0)) ARCHITECTURE behavior OF cpx96 IS BEGIN main : PROCESS CONSTANT MaxDepth : INTEGER := 16 TYPE pipe_type IS ARRAY( 0 TO MaxDepth ) OF VLBIT_1D(95 DOWNTO 0) VARIABLE pipe : pipe_type VARIABLE head VARIABLE tail VARIABLE count : INTEGER : INTEGER : INTEGER VARIABLE v_cd VARIABLE v_pd : VLBIT : VLBIT VARIABLE s_maxusage : INTEGER VARIABLE s_total_count : INTEGER VARIABLE s_total_times : INTEGER BEGIN IF (clr /= '1') THEN s_maxusage := 0 s_total_count := 0 s_total_times := 0 head := 0 tail := 0 count := 0 -- only for error checking -- not for output -- for statistics 2.12. CPX96.VHD 59 v_cd := '0' v_pd := '0' o <= ZERO(95 DOWNTO 0) WAIT UNTIL clr = '1' ELSE IF c'EVENT THEN -- data coming in IF c = v_cd THEN putline("*** Handshake violation on Capture ***") END IF IF ( count < MaxDepth ) THEN -- latch incoming data pipe(tail) := i tail := tail + 1 IF tail >= MaxDepth THEN tail := 0 END IF count := count + 1 s_total_count := s_total_count + count s_total_times := s_total_times + 1 IF count > s_maxusage THEN s_maxusage := count END IF -- keep track of maxium v_cd := NOT v_cd -- remember this event END IF END IF IF p'EVENT THEN -- want data on output IF count = 0 OR p = v_pd THEN putline("*** Handshake violation on Pass ***") END IF head := head + 1 IF head >= MaxDepth THEN head := 0 END IF count := count - 1 -- so I can get rid of it CHAPTER 2. VHDL SOURCE CODE 60 v_pd := NOT v_pd -- remember this event END IF IF count = 0 THEN pipe(head) := i END IF -- copy through if nothing o <= pipe(head) -- show latest data END IF WAIT ON clr, c, p END PROCESS main END behavior -- clr not asserted 2.13. DELAYTAP.VHD 61 2.13 delaytap.vhd USE work.p_constants.ALL ---------------- This taps into a 16-element FIFO at a given point, so that the effective length of the FIFO can be adjusted dynamically. It just passes the REQ and ACK signals, without touching the data. It is strictly a performance hack to avoid altering the FIFO circuit just to change its length. It does not check or enforce correct handshaking. ENTITY delaytap IS PORT ( SIGNAL clr SIGNAL rin SIGNAL ain SIGNAL rx SIGNAL ax END delaytap :IN :IN :OUT :OUT :IN VLBIT VLBIT VLBIT VLBIT_1D(15 DOWNTO 0) VLBIT_1D(15 DOWNTO 0) ) ARCHITECTURE behavior OF delaytap IS BEGIN main : PROCESS VARIABLE tap : INTEGER := 8 VARIABLE v_rx VARIABLE v_ax : VLBIT_1D(15 DOWNTO 0) : VLBIT_1D(15 DOWNTO 0) BEGIN IF (clr /= '1') THEN ain <= '0' v_rx := ZERO(15 DOWNTO 0) v_ax := ZERO(15 DOWNTO 0) rx <= v_rx WAIT UNTIL clr = '1' ELSE IF rin'EVENT THEN v_rx(tap) := NOT v_rx(tap) rx <= v_rx ELSE IF ax(tap) /= v_ax(tap) THEN -- request new data -- toggle output request -- else must be AX event -- wait for just mine v_ax := ax -- remember vector ain <= rin -- ack it END IF -- that's all CHAPTER 2. VHDL SOURCE CODE 62 END IF END IF WAIT ON clr, rin, ax END PROCESS main END behavior -- clr not asserted 2.14. DISPATCH.VHD 63 2.14 dispatch.vhd USE work.p_constants.ALL USE work.p_dispatch.ALL USE work.p_output.ALL ---- The dispatch module is the heart of the IF Unit. The IF Unit is what ---- the rest of the processor connects to, but the dispatch module has ---- slightly different interfaces and behavior. ENTITY dispatch IS GENERIC( delay : TIME := start_addr : INTEGER init_cr0 : INTEGER PORT( SIGNAL clr SIGNAL sb SIGNAL sb_num SIGNAL sb_r_d SIGNAL sb_r_g SIGNAL sb_r_r SIGNAL sb_set SIGNAL sb_w_r SIGNAL sb_w_a SIGNAL br SIGNAL br_ack SIGNAL br_p SIGNAL br_p_ack SIGNAL br_p_req SIGNAL cr_num SIGNAL done SIGNAL done_ack SIGNAL done_req SIGNAL ex SIGNAL ex_p SIGNAL ex_p_ack SIGNAL ex_p_req SIGNAL ex_req SIGNAL external_int SIGNAL fault_pending SIGNAL getcr SIGNAL getcr_ack SIGNAL getcr_req SIGNAL i_addr SIGNAL i_data SIGNAL i_status SIGNAL inst_ack SIGNAL inst_ack_ack SIGNAL inst_req SIGNAL putcr SIGNAL putcr_ack SIGNAL putcr_req SIGNAL reply_hazy SIGNAL rf 100 ps := 0 := 112 ) : IN VLBIT : IN VLBIT_1D : OUT VLBIT_1D : OUT VLBIT : IN VLBIT : OUT VLBIT : OUT VLBIT : OUT VLBIT : IN VLBIT : IN VLBIT_1D : OUT VLBIT : IN VLBIT : IN VLBIT : OUT VLBIT : IN VLBIT_1D : IN VLBIT_1D : OUT VLBIT : IN VLBIT : OUT VLBIT_1D : IN VLBIT : IN VLBIT : OUT VLBIT : OUT VLBIT : IN VLBIT : OUT VLBIT : OUT VLBIT_1D : OUT VLBIT : IN VLBIT : OUT VLBIT_1D : IN VLBIT_1D : IN VLBIT_1D : IN VLBIT : OUT VLBIT : OUT VLBIT : IN VLBIT_1D : OUT VLBIT : IN VLBIT : OUT VLBIT : OUT VLBIT_1D -- handshaking -- initial PC value -- Exceptions, Ints, Supervisor (31 DOWNTO 0) (4 DOWNTO 0) (31 DOWNTO 0) (9 DOWNTO 0) (87 DOWNTO 0) (127 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (3 DOWNTO 0) (31 DOWNTO 0) (17 DOWNTO 0) CHAPTER 2. VHDL SOURCE CODE 64 SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL END dispatch rf_p rf_p_ack rf_p_req rf_req sync_ack sync_nack sync_req x_cr0 xbr xbr_ack xbr_p xbr_p_ack xbr_p_req pf_debug x_debug : : : : : : : : : : : : : : : IN IN OUT OUT IN IN OUT OUT IN OUT IN IN OUT OUT OUT VLBIT VLBIT VLBIT VLBIT VLBIT VLBIT VLBIT VLBIT_1D (31 DOWNTO 0) VLBIT_1D (31 DOWNTO 0) VLBIT VLBIT VLBIT VLBIT VLBIT VLBIT) -- for debugging only ARCHITECTURE behavior OF dispatch IS BEGIN main : PROCESS VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE debug debug_reuse trace_dispatch trace_iw trace_excp all_tellme no_tellme reuse_result skip_r0_ops out_of_order : : : : : : : : : : BOOLEAN BOOLEAN BOOLEAN BOOLEAN BOOLEAN BOOLEAN BOOLEAN BOOLEAN BOOLEAN BOOLEAN := := := := := := := := := := FALSE -- display everything FALSE -- display reuse stuff FALSE -- display dispatches FALSE -- display IW loads FALSE -- display IW loads FALSE -- for debugging only FALSE -- for debugging only TRUE -- reuse last results TRUE -- speed up OP rD,r0,imm16 TRUE -- issue insts out of order --- Necessary constants and type definitions. VARIABLE VARIABLE VARIABLE VARIABLE IW_tap BR_Max XBR_Max R1_Max : : : : INTEGER INTEGER INTEGER INTEGER := := := := IW_Max 8 8 8 ----- useful IW size Branch Queue size Exception Branch Queue size R1 Queue size --- factors affecting response time VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE delay_decode delay_doit delay_done_req delay_getcr delay_inst_ack delay_iw_search delay_putcr delay_rte delay_save_state delay_sync_ack : : : : : : : : : : TIME TIME TIME TIME TIME TIME TIME TIME TIME TIME := := := := := := := := := := 100 100 100 100 100 100 100 100 100 100 ps ps ps ps ps ps ps ps ps ps ----------- dispatch output signals handle DOIT instruction update IW on done read CR put new inst in IW look for inst to dispatch write CR restore state on RTE save state on fault respond to SYNC_ACK 2.14. DISPATCH.VHD VARIABLE delay_sync_nack VARIABLE delay_to_use 65 : TIME := 100 ps -- respond to SYNC_NACK : TIME -- scratch for culumative time --- constant definitions CONSTANT Tag_Max_Value : INTEGER := 127 CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT : : : : : : : : ICR_Saved_Control ICR_Fault_Status ICR_Fault_Address ICR_Next_PC ICR_BR_Count ICR_R1_Count ICR_IW_Count ICR_IW_Faults INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER := := := := := := := := 1 2 3 4 5 6 7 8 --- These control registers are not affected by anything. They're just here --- for scratch storage in supervisor mode. CONSTANT CONSTANT CONSTANT CONSTANT ICR_S1 ICR_S2 ICR_S3 ICR_S4 : : : : INTEGER INTEGER INTEGER INTEGER := := := := 9 10 11 12 --- type definitions TYPE tag_sb_type IS ARRAY ( 0 TO Tag_Max_Value ) OF BOOLEAN TYPE cr_type IS ARRAY ( IF_ICR_Min TO IF_ICR_Max ) OF INTEGER TYPE siw_type IS ARRAY ( IF_SIW_Min TO IF_SIW_Max ) OF INTEGER TYPE pflag_type IS ARRAY ( 0 TO 31 ) OF BOOLEAN TYPE lfu_type IS ARRAY ( 0 TO 4 ) OF INTEGER --- control register 0 is located here. VARIABLE cr0 : VLBIT_1D (31 DOWNTO 0) --- internal variables VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE iw : iw_type iw_bottom : INTEGER wat_flag : BOOLEAN single_flag : BOOLEAN pc : INTEGER faulting_instruction : iw_slot doit_instruction : iw_slot -------- instruction window next available slot wait at top scoreboard bit single instruction flag program counter remembers who caused fault where DOIT came from CHAPTER 2. VHDL SOURCE CODE 66 VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE out_count br_count new_br_count xbr_count new_xbr_count r1_count new_r1_count r1_pending new_r1_pending tag_value tag_sb waiting_for_inst cr siw scoreboard : : : : : : : : : : : : : : : INTEGER -- number of incomplete insts. INTEGER -- entries in Branch Queue INTEGER INTEGER -- entries in X Branch Queue INTEGER INTEGER -- entries in R1 Queue INTEGER -- used to decrement r1_count INTEGER INTEGER INTEGER -- assign tags to insts. tag_sb_type -- prevent multiple tag use BOOLEAN -- controls INST_REQ cr_type -- internal control regs siw_type -- shadow IW slots VLBIT_1D(31 DOWNTO 0) -- internal copy only --- Variables for use in dispatching out-of-order, reusing last results, --- and skipping r0 operands. VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE pload pstore pbranch pcarry pdest psrc ldest fu_num reuseA reuseB reuseD zeroA latched_in_fu got_probes VARIABLE try_dispatch VARIABLE done_dispatch VARIABLE done_ex_dispatch --------- : : : : : : : : : : : : : : BOOLEAN BOOLEAN BOOLEAN BOOLEAN pflag_type pflag_type pflag_type INTEGER BOOLEAN BOOLEAN BOOLEAN BOOLEAN lfu_type BOOLEAN : BOOLEAN : BOOLEAN : BOOLEAN --------------- have I have I have I have I have I have I have I number flag flag flag flag tracks have I seen a prior load? seen a prior store? seen a prior branch? seen a prior carry? seen prior dest regs? seen prior src regs? seen issued dests? of dest FU latched values probed queues? -- hack to dispatch more often -- hack to do it only once -- hack to do it only once Input signal event variables. These are the events which wake up this process, for various reasons. The first four are externally arbitrated. The control register operations don't have to be, since control registers are only written here under quiescent conditions. VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE l_inst_ack l_done_req l_external_int l_getcr_req l_putcr_req : : : : : VLBIT VLBIT VLBIT VLBIT VLBIT --- output signal value variables VARIABLE v_br_ack : VLBIT ------ arbitrated arbitrated arbitrated can be done at any time only done by PUTCR inst. 2.14. DISPATCH.VHD VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE v_br_p_req v_done_ack v_ex v_ex_p_req v_ex_req v_fault_pending v_i_addr v_inst_req v_reply_hazy v_rf v_rf_p_req v_rf_req v_sb_r_r v_sb_w_r v_sync_req v_xbr_ack v_xbr_p_req v_x_debug v_pf_debug 67 : : : : : : : : : : : : : : : : : : : VLBIT VLBIT VLBIT_1D (127 DOWNTO 0) VLBIT VLBIT VLBIT VLBIT_1D (31 DOWNTO 0) VLBIT VLBIT VLBIT_1D (17 DOWNTO 0) VLBIT VLBIT VLBIT VLBIT VLBIT VLBIT VLBIT VLBIT VLBIT --- scratch variables VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE tmpi tmpb1 tmpb2 tmpv tmpmvbr : : : : : INTEGER BOOLEAN BOOLEAN VLBIT_1D (31 DOWNTO 0) VLBIT_1D (31 DOWNTO 0) VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE iw_index vA, vB, vD srcA, srcB, srcD dest op_type status single, wat tellme found_one icount : : : : : : : : : : INTEGER BOOLEAN INTEGER INTEGER INTEGER INTEGER BOOLEAN BOOLEAN BOOLEAN INTEGER ----------- temp for searching IW valid flags for operands source operand registers destination register decode instruction type status of decoded inst. flags for decoded inst. flags for decoded inst. found inst to issue count issued insts in IW : : : : : : : : : : : INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER ------------ got new instruction for IW cumulative sum of IW count maximum IW fullness reported done status tried to dispatch actually did it (not doit) same, but only for faults inst. needed operands done status is faulty invoked exception handler count zeroA times --- statistics VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE s_inst_ack s_iw_total s_iw_max s_done_req s_dispatch_req s_did_dispatch s_excp_dispatch s_need_operands s_excp_status s_did_excp s_zeroA VARIABLE s_reuse_result : INTEGER -- count last-result-reuse CHAPTER 2. VHDL SOURCE CODE 68 VARIABLE VARIABLE VARIABLE VARIABLE s_reuse_helps s_iw_ooo_count s_iw_ooo_total s_iw_ooo_max : : : : INTEGER INTEGER INTEGER INTEGER ----- count when it helps out-of-order insts issued how far out-of-order total maximum out-of-order dist --- other stuff CONSTANT EX_PADDING : VLBIT_1D(127 DOWNTO 0) := ( '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0' ) BEGIN ----- If clear is asserted, reset everything and stick here. --IF clr /= '1' THEN cr0 := int2v1d( init_cr0 ) x_cr0 <= cr0 FOR i IN 0 TO (IW_Max - 1) LOOP iw(i).valid := FALSE END LOOP iw_bottom := 0 FOR i IN 0 TO Tag_Max_Value LOOP tag_sb(i) := FALSE END LOOP wat_flag := FALSE single_flag := FALSE pc := start_addr tag_value := 0 out_count := 0 br_count := 0 -- reset to beginning -- init CR0 -- clear IW -- clear the tag scoreboard 2.14. DISPATCH.VHD 69 xbr_count := 0 r1_count := 0 new_r1_count := 0 r1_pending := 0 new_r1_pending := 0 waiting_for_inst := FALSE done_dispatch := FALSE done_ex_dispatch := FALSE l_inst_ack := '0' l_done_req := '0' l_external_int := '0' l_getcr_req := '0' l_putcr_req := '0' v_br_ack := '0' v_br_p_req := '0' v_done_ack := '0' v_ex_p_req := '0' v_ex_req := '0' v_fault_pending := '0' v_inst_req := '0' v_reply_hazy := '0' v_rf_p_req := '0' v_rf_req := '0' v_sb_r_r := '0' v_sb_w_r := '0' v_sync_req := '0' v_xbr_ack := '0' v_xbr_p_req := '0' br_ack <= v_br_ack br_p_req <= v_br_p_req done_ack <= v_done_ack ex <= EX_PADDING ex_p_req <= v_ex_p_req ex_req <= v_ex_req fault_pending <= v_fault_pending getcr <= ZERO(31 DOWNTO 0) getcr_ack <= '0' inst_ack_ack <= '0' inst_req <= v_inst_req putcr_ack <= '0' reply_hazy <= v_reply_hazy rf <= ZERO( 17 DOWNTO 0 ) rf_p_req <= v_rf_p_req rf_req <= v_rf_req sb_num <= ('0','0','0','0','0') sb_r_r <= v_sb_r_r sb_r_d <= v_sb_r_r sb_set <= '0' sb_w_r <= v_sb_w_r sync_req <= v_sync_req xbr_ack <= v_xbr_ack -- now set outputs CHAPTER 2. VHDL SOURCE CODE 70 xbr_p_req <= v_xbr_p_req v_i_addr := int2v1d(pc) i_addr <= (v_i_addr(31 DOWNTO 2) & '0' & '0') -- just for now v_x_debug := '0' x_debug <= v_x_debug v_pf_debug := '0' pf_debug <= v_pf_debug --- clear statistics s_inst_ack := 0 s_iw_total := 0 s_iw_max := 0 s_done_req := 0 s_dispatch_req := 0 s_did_dispatch := 0 s_excp_dispatch := 0 s_need_operands := 0 s_excp_status := 0 s_did_excp := 0 s_zeroA := 0 s_reuse_result := 0 s_reuse_helps := 0 s_iw_ooo_count := 0 s_iw_ooo_total := 0 s_iw_ooo_max := 0 WAIT UNTIL clr = '1' -- wait till ready to run --- Send out first instruction request to start things off. v_i_addr := int2v1d(pc) -- get 32-bit PC value i_addr <= (v_i_addr(31 DOWNTO 2) & cr0(Supervisor) & '0') v_inst_req := NOT v_inst_req inst_req <= v_inst_req AFTER delay waiting_for_inst := TRUE IF debug THEN puthexline("sent out INST_REQ for address ",pc) END IF ELSE -- unit is running ---- Normal running condition --- The process loses events if I'm busy elsewhere, so I need to make my --- own virtual wait statement, instead of relying on the actual wait --- from VHDL. I'll just sample by hand, and only wait if there are no 2.14. DISPATCH.VHD 71 --- pending requests. Since the REQ/ACK is paired, this will work fine. --- The critical signals are externally arbitrated, so I can respond to --- any that I see here. got_probes := FALSE try_dispatch := TRUE done_dispatch := FALSE IF ex_p = '0' THEN done_ex_dispatch := FALSE END IF WHILE ( inst_ack /= l_inst_ack OR try_dispatch OR done_req /= l_done_req OR external_int /= l_external_int OR getcr_req /= l_getcr_req OR putcr_req /= l_putcr_req ) LOOP IF debug THEN putline("Top of event loop") END IF ----------- Requests to read and write internal control registers must always be handled, but don't need to be arbitrated, since the internal control registers are only changed when starting and ending exception processing (when everything has stopped), and by PUTCR instructions (when everything has also stopped). IF getcr_req /= l_getcr_req THEN -- request to read control reg l_getcr_req := getcr_req tmpi := v1d2int( cr_num ) -- which register IF debug THEN putline("handling GETCR request for CR",tmpi) END IF --- NOTE: This would normally need to be four-phase, but since there --- is only one unit which can read the control registers, it should --- work fine. IF tmpi >= getcr <= ELSIF tmpi getcr <= ELSIF tmpi getcr <= ELSE getcr <= IF_ICR_Min AND tmpi <= IF_ICR_Max THEN int2v1d( cr(tmpi) ) -- actual register value >= IF_SIW_Min AND tmpi <= IF_SIW_Max THEN int2v1d( siw(tmpi) ) -- shadow IW = 0 THEN cr0 -- this isn't necessary ZERO(31 DOWNTO 0) -- no register here, use zero CHAPTER 2. VHDL SOURCE CODE 72 END IF getcr_ack <= getcr_req AFTER delay_getcr END IF -- getcr_req --- Reading and writing can't happen at the same time, since PUTCR is --- a SINGLE instruction, which must be the only one active. IF putcr_req /= l_putcr_req THEN -- request to write control reg l_putcr_req := putcr_req tmpi := v1d2int( cr_num ) -- which register to write IF debug THEN putline("handling PUTCR request for CR",tmpi) END IF IF (tmpi >= IF_ICR_Min AND tmpi <= IF_ICR_Max) THEN -- control reg cr(tmpi) := v1d2int( putcr ) ELSIF (tmpi >= IF_SIW_Min AND tmpi <= IF_SIW_Max) THEN -- shadow IW siw(tmpi) := v1d2int( putcr ) ELSIF tmpi = 0 THEN -- cr0 cr0 := putcr x_cr0 <= cr0 END IF putcr_ack <= putcr_req AFTER delay_putcr END IF -- putcr_req IF inst_ack /= l_inst_ack THEN -- new operand has arrived l_inst_ack := inst_ack s_inst_ack := s_inst_ack + 1 IF debug THEN putline("got INST_ACK event") END IF waiting_for_inst := FALSE --- Is there room? There had better be! IF ((IW_tap - iw_bottom) >= 1) THEN -- yes, there's room --- see if it really arrived, or if there was a memory fault tmpi := STATUS_none -- assume there's not 2.14. DISPATCH.VHD 73 --- check for memory faults IF ( ( i_status(0) = '1' ( i_status(1) = '1' ( i_status(2) = '1' ( i_status(3) = '1' THEN tmpi := STATUS_imem END IF AND AND AND AND cr0(Imem0) cr0(Imem1) cr0(Imem2) cr0(Imem3) = = = = '1' '1' '1' '1' ) ) ) ) OR OR OR ) iw(iw_bottom).status := tmpi -- save status iw(iw_bottom).valid := TRUE -- mark it valid iw(iw_bottom).address := v1d2int( v_i_addr ) iw(iw_bottom).issued := FALSE IF tmpi /= STATUS_none THEN -- yes, there's a fault IF debug THEN putline("found a memory fault") END IF IF v_fault_pending = '0' THEN -- might need to signal it faulting_instruction.status := tmpi faulting_instruction.address := v1d2int( v_i_addr ) v_fault_pending := '1' -- do so fault_pending <= v_fault_pending v_x_debug := NOT v_x_debug x_debug <= v_x_debug IF trace_excp THEN putline("IMem exception: out_count = ",out_count) END IF END IF ELSE -- no fault ------------- Just stick the new instructions in the IW. They will be decoded at dispatch time. This simplifies the return from exceptions, since I don't have to do anything special to the IW, other than to just reload it with nothing dispatched. Well, that's not quite true: I will need to set the single_flag again. --------- I do need to set the single_flag now, so that I don't fetch anything that I don't need. I could just throw away all instructions after the SINGLE instruction, but that would be messier. tmpi := v1d2int( i_data ) IF tmpi /= OPCODE_doit THEN -- get opcode CHAPTER 2. VHDL SOURCE CODE 74 iw(iw_bottom).opcode := tmpi IF debug OR trace_iw THEN put("IW(",iw_bottom) puthex(") got opcode ",iw(iw_bottom).opcode) puthexline(" from address ",iw(iw_bottom).address) END IF IF is_single( i_data ) THEN -- see if it's single iw(iw_bottom).single := TRUE single_flag := TRUE IF debug THEN putline("single flag is now ",single_flag) END IF END IF iw_bottom := iw_bottom + 1 -- next slot s_iw_total := s_iw_total + iw_bottom IF iw_bottom > s_iw_max THEN s_iw_max := iw_bottom END IF ELSE cr0(Doit) := '1' single_flag := TRUE -- explicit doit -- set Doit flag doit_instruction.address := v1d2int( v_i_addr ) doit_instruction.opcode := tmpi IF debug OR trace_iw THEN put("IW(-) ") puthex("got opcode ",iw(iw_bottom).opcode) puthexline(" from address ",iw(iw_bottom).address) END IF IF debug THEN putline("single flag is now ",single_flag) END IF --- signal desire for normal branch target IF cr0(Excp_Enable) = '1' THEN v_pf_debug := NOT v_pf_debug pf_debug <= v_pf_debug END IF END IF IF i_data(31) = '1' THEN -- add implicit doit 2.14. DISPATCH.VHD cr0(Doit) := '1' single_flag := TRUE 75 -- set Doit flag doit_instruction.address := v1d2int( v_i_addr ) doit_instruction.opcode := tmpi IF debug OR trace_iw THEN putline("got implicit DOIT") END IF IF debug THEN putline("single flag is now ",single_flag) END IF --- signal desire for normal branch target IF cr0(Excp_Enable) = '1' THEN v_pf_debug := NOT v_pf_debug pf_debug <= v_pf_debug END IF END IF --------------- I can go ahead and increment the program counter now, because if I just added a SINGLE instruction, the PC won't be used until the instruction has finished, at which time the PC will have been changed if it needs to be. NOTE: This means that the DOIT instruction must either replace the PC or leave it alone. It shouldn't increment it. Same for RTE, and PUTCR only affects the user/supervisor mode bit. pc := pc + 4 -- increment program counter IF debug THEN puthexline("PC advanced to ",pc) END IF END IF END IF -- (no memory fault) -- (there's room in the IW) inst_ack_ack <= inst_ack AFTER delay_inst_ack IF debug THEN putline("done with this event") END IF END IF IF done_req /= l_done_req THEN l_done_req := done_req -- inst_ack -- instruction has completed CHAPTER 2. VHDL SOURCE CODE 76 s_done_req := s_done_req + 1 IF debug THEN putline("got DONE_REQ event") END IF --- Find instruction associated with the tag. tmpi := v1d2int( done(7 DOWNTO 0) ) -- get tag IF debug THEN putline("looking for tag ",tmpi) END IF iw_index := -1 FOR i IN 0 TO (iw_bottom - 1) LOOP -- it will do 0 to 0 IF iw(i).valid AND iw(i).issued AND iw(i).tag = tmpi THEN -- got it iw_index := i EXIT END IF END LOOP --- If tag wasn't found, crash and burn. ASSERT iw_index /= -1 REPORT "Retiring Invalid Tag" SEVERITY FAILURE IF debug THEN putline("found it in slot ",iw_index) END IF --- We've heard from the instruction. Count it off. out_count := out_count - 1 IF debug THEN putline("now out_count = ",out_count) END IF --- Mark the tag as not in use. This is safe, because if the --- instruction is faulty, nothing more will be dispatched until --- the fault is handled. Right? tag_sb(tmpi) := FALSE --- now handle reported status tmpi := v1d2int( done(15 DOWNTO 8) ) -- get major status IF debug THEN putline("major status is ",tmpi) 2.14. DISPATCH.VHD 77 END IF IF tmpi = STATUS_done THEN IF iw(iw_index).dest == 1 THEN r1_count := r1_count + 1 r1_pending := r1_pending - 1 -- No fault. Remove it. -- produced r1 value -- so count it, -- since it succeeded --- clear scoreboard for R1 sb_set <= '0' sb_num <= REG_R1 v_sb_w_r := NOT v_sb_w_r sb_w_r <= v_sb_w_r AFTER delay WAIT ON sb_w_a IF debug THEN putline("r1_count is now ",r1_count) putline("r1_pending is now ",r1_pending) putline("clearing scoreboard bit ",iw(iw_index).dest) END IF END IF iw_remove( iw_index, iw, iw_bottom, wat_flag, single_flag ) IF debug THEN putline("wat_flag is now ",wat_flag) putline("single_flag is now ",single_flag) END IF ELSE -- faulty instruction s_excp_status := s_excp_status + 1 ----------- Save minor status as well as major. In this register, the minor status is the upper 16 bits, while the major status is the lower 16 bits. Only 8 bits of each are actually returned from execution units, but the internally generated major status is actually 9 bits wide, so we split the register this way. tmpi := tmpi + 65536 * v1d2int( done(23 DOWNTO 16) ) iw(iw_index).status := tmpi -- save status with instruction --- save other reported values iw(iw_index).arg1 := v1d2int( done(87 DOWNTO 56) ) iw(iw_index).arg2 := v1d2int( done(55 DOWNTO 23) ) IF iw(iw_index).dest >= 1 THEN -- clear scoreboard bit if set IF debug THEN putline("clearing scoreboard bit ",iw(iw_index).dest) END IF CHAPTER 2. VHDL SOURCE CODE 78 sb_set <= '0' tmpv := int2v1d( iw(iw_index).dest sb_num <= tmpv(4 DOWNTO 0) v_sb_w_r := NOT v_sb_w_r sb_w_r <= v_sb_w_r AFTER delay WAIT ON sb_w_a ) -- IDIOTIC ViewLogic crap END IF IF v_fault_pending = '0' THEN -- need to signal fault faulting_instruction := iw(iw_index) -- remember who did it v_fault_pending := '1' -- do so fault_pending <= v_fault_pending v_x_debug := NOT v_x_debug x_debug <= v_x_debug IF trace_excp THEN putline("faulty status: out_count = ",out_count) END IF END IF END IF v_done_ack := NOT v_done_ack done_ack <= v_done_ack AFTER delay_done_req IF debug THEN putline("done with this event") END IF END IF -- done_req IF external_int /= l_external_int THEN -- guess what IF debug THEN putline("got EXTERNAL_INT event") END IF l_external_int := external_int --- decide whether to postpone the INT or not. If it's --- disabled, or if I'm in the process of switching to an --- exception handler already, then put it off until later. IF cr0(Int_Enable) = '0' OR v_fault_pending = '1' THEN v_reply_hazy := NOT v_reply_hazy reply_hazy <= v_reply_hazy -- ask again later IF debug THEN putline("reply hazy - ask again later") 2.14. DISPATCH.VHD 79 END IF ELSE -- I can do it now faulting_instruction.status := STATUS_int v_fault_pending := '1' -- do so fault_pending <= v_fault_pending v_x_debug := NOT v_x_debug x_debug <= v_x_debug IF trace_excp THEN putline("interrupt: out_count = ",out_count) END IF try_dispatch := FALSE END IF IF debug THEN putline("done with this event") END IF END IF -- external_int IF NOT done_dispatch AND try_dispatch THEN -- try to dispatch something try_dispatch := FALSE s_dispatch_req := s_dispatch_req + 1 IF debug THEN putline("got try_dispatch signal") END IF --------------- Now try to dispatch an instruction from the IW. All decoding, fault detection, tag assignments, etc. is done here to simplify returning from exceptions. I don't have to preload anything, just start dispatching again. If it's dispatched externally, increment out_count DOITs are a special case, since they are handled entirely within this module, and don't produce a done_req signal. MVPC and MVBR must provide operands to the instruction. delay_to_use := delay found_one := FALSE -- looking for one IF ( v_fault_pending = '0' and NOT wat_flag ) THEN -- no dispatch while faults -- no dispatch until cleared CHAPTER 2. VHDL SOURCE CODE 80 IF debug THEN putline("Looking for something to dispatch") END IF delay_to_use := delay_iw_search -- time to find valid inst. --- set up data structures for loop pload := FALSE pstore := FALSE pbranch := FALSE pcarry := FALSE pdest := ( FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE ) psrc := ( FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE ) ldest := ( FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE, FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE ) icount := 0 FOR i IN 0 TO (iw_bottom - 1) LOOP IF ( NOT iw(i).valid ) THEN -- check each slot for valid -- stop when I run out IF debug THEN putline("end of IW entries") END IF EXIT END IF IF debug THEN putline("looking at iw slot ",i) put(" valid = ",iw(i).valid) put(" issued = ",iw(i).issued) putline(" tag = ",iw(i).tag) puthexline(" status = ",iw(i).status) puthexline(" address = ",iw(i).address) puthexline(" opcode = ",iw(i).opcode) END IF IF iw(i).issued THEN icount := icount + 1 -- count issued insts in IW 2.14. DISPATCH.VHD 81 --- Keep track of all the currently pending destinations in --- case I want to reuse them. IF reuse_result THEN IF debug_reuse OR debug THEN putline("setting ldest ",iw(i).dest) END IF ldest(iw(i).dest) := TRUE END IF NEXT -- skip issued instructions END IF --- Now, I'm looking at a valid, non-issued instruction. Decode --- it and see if I can issue it. tmpb1 := vlb2boo( cr0(Supervisor) ) -- stupid Viewlogic crap tmpb2 := vlb2boo( cr0(Excp_Enable) ) -- stupid Viewlogic crap decode( BR_Max, XBR_Max, R1_Max, -- queue length inputs iw(i).opcode, tmpb1, tmpb2, -- inputs r1_count, r1_pending, br_count, xbr_count, -- inputs new_r1_count, new_r1_pending, -- outputs new_br_count, new_xbr_count, -- outputs status, op_type, single, wat, tellme, -- outputs vA, srcA, vB, srcB, vD, srcD, dest) -- outputs IF all_tellme THEN tellme := TRUE ELSIF no_tellme THEN tellme := FALSE END IF iw(i).single := single iw(i).wat := wat iw(i).status := status iw(i).dest := dest -- for debugging only -- used for starting exceptions IF debug THEN putline("found a non-issued instruction in slot ",i) END IF IF status /= STATUS_none THEN faulting_instruction := iw(i) -- need to signal fault -- remember who did it v_fault_pending := '1' -- do so fault_pending <= v_fault_pending v_x_debug := NOT v_x_debug CHAPTER 2. VHDL SOURCE CODE 82 x_debug <= v_x_debug IF debug THEN puthexline("but it's faulty. Status = 0x",status) END IF IF trace_excp THEN put("invalid instruction:") puthex(" op ",iw(i).opcode) puthexline(" addr ",iw(i).address) putline("invalid instruction: out_count = ",out_count) END IF EXIT -- skip out of loop END IF IF wat AND i /= 0 THEN -- only dispatch WAT at top IF debug THEN putline("can't dispatch it: WAT") END IF EXIT END IF ------------- -- jump out to prevent more Check for out-of-order dependencies. I need to do all the tests first, then go to the next slot if it's not valid, so that I can update the flags for this slot after I've considered the instruction. This stuff is only considered based on non-issued instructions. The scoreboard handles interaction between issued instructions. tmpb1 := TRUE -- is it valid? assume so. IF ( pdest(dest) OR psrc(dest) OR ( vA AND pdest(srcA) ) OR ( vB AND pdest(srcB) ) OR ( vD AND pdest(srcD) ) ) THEN ------ destination is prior dest destination is prior source sourceA is prior dest sourceB is prior dest sourceD is prior dest IF debug THEN putline("can't dispatch it: out-of-order dependency") END IF tmpb1 := FALSE END IF --- instructions writing to the branch queue must be sequential 2.14. DISPATCH.VHD IF ( op_type = OP_branch OR op_type = OP_ldbr ) AND pbranch THEN IF debug THEN putline("can't dispatch it: prior branches") END IF tmpb1 := FALSE END IF --------- Instructions using the carry bit must be sequential. This is a bit of cheating using the opcodes to watch for instructions which use the carry bit. I should do this in p_dispatch, but I'm in a hurry. tmpv := int2v1d( iw(i).opcode ) tmpi := op2index( tmpv ) IF ( ( tmpi = 40 OR tmpi = 41 OR tmpi = 46 OR tmpi = 47 ) AND ( tmpv(8) = '1' OR tmpv(9) = '1' ) AND pcarry ) THEN IF debug THEN putline("can't dispatch it: prior carry") END IF tmpb1 := FALSE END IF --- also check for MEM unit dependencies --- I can reorder loads unless I've seen a store. IF op_type = OP_load AND pstore THEN IF debug THEN putline("can't dispatch it: prior stores") END IF tmpb1 := FALSE END IF --- I can't reorder stores at all. IF ( ( op_type = OP_store OR op_type = OP_xmem ) AND ( pload OR pstore ) ) THEN IF debug THEN putline("can't dispatch it: prior memory instructions") 83 CHAPTER 2. VHDL SOURCE CODE 84 END IF tmpb1 := FALSE END IF --- Now update the out-of-order data structures for this slot, --- and then skip out if it's not valid. IF dest /= 0 THEN pdest(dest) := TRUE IF debug THEN putline("setting pdest ",dest) END IF END IF IF vA AND srcA /= 0 THEN psrc(srcA) := TRUE IF debug THEN putline("setting psrc ",srcA) END IF END IF IF vB AND srcB /= 0 THEN psrc(srcB) := TRUE IF debug THEN putline("setting psrc ",srcB) END IF END IF IF vD AND srcD /= 0 THEN psrc(srcD) := TRUE IF debug THEN putline("setting psrc ",srcD) END IF END IF IF op_type = OP_branch OR op_type = OP_ldbr THEN pbranch := TRUE IF debug THEN putline("setting pbranch") END IF END IF IF ( ( tmpi = 40 OR tmpi = 41 OR tmpi = 46 OR tmpi = 47 ) AND ( tmpv(8) = '1' OR tmpv(9) = '1' ) ) THEN pcarry := TRUE IF debug THEN putline("setting pcarry") END IF END IF IF op_type = OP_load THEN pload := TRUE 2.14. DISPATCH.VHD 85 IF debug THEN putline("setting pload") END IF END IF IF op_type = OP_store OR op_type = OP_xmem THEN pstore := TRUE IF debug THEN putline("setting pstore") END IF END IF NEXT WHEN NOT tmpb1 -------------------------------------------------------------------------------------------------- -- go to next IW slot Check to see if queues are ready. I could just probe the queues that I'm interested in, but since I might want them all, and it's pretty likely to take longer to probe each one as needed instead of probing them all, I'll just probe them now. IF NOT got_probes THEN v_ex_p_req := NOT v_ex_p_req -- probe EX queue ex_p_req <= v_ex_p_req AFTER delay v_rf_p_req := NOT v_rf_p_req -- probe RF queue rf_p_req <= v_rf_p_req AFTER delay v_br_p_req := NOT v_br_p_req -- probe BR queue (for MVBR) br_p_req <= v_br_p_req AFTER delay v_sb_r_r := NOT v_sb_r_r -- read the scoreboard sb_r_r <= v_sb_r_r AFTER delay --- I need to wait for all four signals to acknowledge. WAIT UNTIL ( ex_p_ack rf_p_ack br_p_ack sb_r_g = = v_ex_p_req AND = v_rf_p_req AND = v_br_p_req AND v_sb_r_r ) scoreboard := sb sb_r_d <= sb_r_g -- grab a copy -- unlock scoreboard got_probes := TRUE -- only do this once END IF CHAPTER 2. VHDL SOURCE CODE 86 --- Now use the queue information to determine whether I can --- dispatch or not. --- This is not quite right, since RTE and SYNC don't use the EX --- queue, but those don't happen very often, especially when the --- queue isn't ready. IF ex_p = '0' OR done_ex_dispatch THEN -- room to issue new inst? IF debug THEN putline("EX queue isn't ready") END IF NEXT END IF IF ( vA OR vB OR vD ) AND rf_p = '0' THEN -- need RF operands IF debug THEN putline("RF queue isn't ready") END IF NEXT END IF IF op_type = OP_mvbr AND br_p = '0' THEN -- need branch target --- Can't dispatch if there's no branch target there. It must --- come from the normal Branch Queue, regardless of which --- queue is active. IF debug THEN putline("BR queue not ready (MVBR instruction)") END IF NEXT END IF ------------- Before I check the scoreboard, see if I can reuse the last result from a particular functional unit. I can only do this if I haven't seen the particular destination register used as a destination in the currently executing instructions in the IW, so that I know that the result will be valid when I use it. IF reuse_result THEN -- see where I can reuse values 2.14. DISPATCH.VHD 87 --- to which unit is this instruction going? CASE op_type IS WHEN OP_arith => -- unit 0 fu_num := OP_arith WHEN OP_logic => -- unit 1 fu_num := OP_logic WHEN OP_ctrl | OP_mvbr => -- unit 2 fu_num := OP_ctrl WHEN OP_load | OP_store | OP_xmem => -- unit 3 fu_num := OP_load WHEN OP_branch | OP_ldbr => -- unit 4 fu_num := OP_branch WHEN OTHERS => -- not implemented fu_num := OP_branch -- does not latch END CASE --- can I use the last value that's there? reuseA := ( vA AND srcA /= 0 AND srcA /= NOT ldest(srcA) AND latched_in_fu(fu_num) = srcA reuseB := ( vB AND srcB /= 0 AND srcB /= NOT ldest(srcB) AND latched_in_fu(fu_num) = srcB reuseD := ( vD AND srcD /= 0 AND srcD /= NOT ldest(srcD) AND latched_in_fu(fu_num) = srcD ELSE 1 AND ) 1 AND ) 1 AND ) -- last-result-reuse disabled reuseA := FALSE reuseB := FALSE reuseD := FALSE END IF --- Modify vA, vB, vD according to reuse policy, since these are --- used to request operands. I can ignore scoreboard conflicts --- if I'm reusing the last result for that operand. zeroA := skip_r0_ops AND vA AND (srcA = 0) vA := vA AND NOT reuseA AND NOT zeroA vB := vB AND NOT reuseB vD := vD AND NOT reuseD --- Now check scoreboard conflicts. IF ( (vA AND scoreboard(srcA)='1') OR (vB AND scoreboard(srcB)='1') OR CHAPTER 2. VHDL SOURCE CODE 88 (vD AND scoreboard(srcD)='1') OR scoreboard(dest)='1' ) -- also prevent WAW THEN IF debug THEN putline("can't dispatch it: scoreboard") END IF NEXT END IF --- If I get this far, then the current instruction is a valid --- one to dispatch. The only thing that could prevent dispatch --- is if I don't allow out-of-order issue. --- See if I'm allowed to issue out-of-order. tmpi := i - icount IF tmpi > 0 THEN -- out-of-order distance IF NOT out_of_order THEN IF debug THEN putline("can't dispatch it: no out-of-order") END IF EXIT END IF --- Okay, everything is ready. Gather some stats on it. s_iw_ooo_count := s_iw_ooo_count + 1 s_iw_ooo_total := s_iw_ooo_total + tmpi IF tmpi > s_iw_ooo_max THEN s_iw_ooo_max := tmpi END IF END IF IF debug THEN putline("Found a dispatchable instruction in IW slot ",i) END IF --- remember destination reg & unit for reuse later IF ( reuse_result AND dest /= 0 AND dest /= 1 ) THEN FOR k IN 0 TO 4 LOOP -- enabled -- valid register -- valid destination to latch 2.14. DISPATCH.VHD 89 IF latched_in_fu(k) = dest THEN -- found it somewhere else latched_in_fu(k) := 0 END IF END LOOP latched_in_fu(fu_num) := dest -- remember who has it END IF --- gather some more statistics IF zeroA THEN IF (NOT vB) AND (NOT vD) THEN s_zeroA := s_zeroA + 1 END IF -- just count useful ones IF debug THEN putline("zeroA") END IF END IF IF reuseA OR reuseB OR reuseD THEN s_reuse_result := s_reuse_result + 1 -- could reuse result IF ( (reuseA AND scoreboard(srcA)='1') OR (reuseB AND scoreboard(srcB)='1') OR (reuseD AND scoreboard(srcD)='1') ) THEN s_reuse_helps := s_reuse_helps + 1 -- it actually helps END IF IF debug OR debug_reuse THEN putline("reuseA is ",reuseA) putline("reuseB is ",reuseB) putline("reuseD is ",reuseD) END IF END IF found_one := TRUE iw_index := i EXIT END LOOP -- hop out and dispatch it -- end of look-for-instruction --- If I have something to dispatch, the loop below does the --- dispatch, but doesn't actually loop. It just provides a --- convenient way to abort for any reason. CHAPTER 2. VHDL SOURCE CODE 90 WHILE found_one LOOP --------- -- iw_index says which one Now, do different things, depending on the instruction. Some are executed entirely in this module, and are not actually dispatched through external queues. DOITs are handled later, and should no longer appear in the IW at all. IF op_type = OP_rte THEN -- rte instruction IF trace_dispatch THEN put("Dispatch IW(",iw_index) put("/",icount) puthex("): op ",iw(iw_index).opcode) puthex(" addr ",iw(iw_index).address) putline(" RTE") END IF IF debug THEN putline("type OP_rte. restore status") END IF --- The RTE instruction is replaced by the new IW contents, so --- it doesn't need to be removed explicitly. --- restore internal counters and flags ----------- The queue counts are NOT updated, since they should always be accurate. They are only provided so that the handler can empty the R1 Queue and Branch Queues. Loading these queues is visible by the dispatch unit, since it is done with normal instructions. pc := cr(ICR_Next_PC) iw_bottom := cr(ICR_IW_Count) IF iw_bottom > IW_tap THEN iw_bottom := IW_tap END IF IF debug THEN putline(" IW_Count = ",iw_bottom) END IF single_flag wat_flag tag_value := FALSE := FALSE := 0 -- RTE set it, so clear it -- RTE set it, so clear it --- out_count should be zero, since RTE is WAT and SINGLE --------- The tag_scoreboard should already be clear, since we've now heard from every outstanding instruction. The register scoreboard may not be clear, but it can take care of itself. Since we clear the destination bit for faulty 2.14. DISPATCH.VHD 91 --- instructions, it will eventually clear. ----------------- Reload IW with all non-issued instructions. Note that although this sets the single_flag appropriately, it does NOT insert implicit DOIT instructions. If the IW was saved from a previous thread, it should already have the DOIT in there. Otherwise, if you want a DOIT, you have to put it in yourself via software. Be careful, though. Because DOITs are SINGLE instructions, having more than one in the IW at a time can cause a LOT of confusion. FOR k IN 0 TO iw_bottom - 1 LOOP iw(k).valid := TRUE iw(k).address := siw(IW_CRNUM*k+IF_SIW_Min+IW_CR_ADDR) iw(k).opcode := siw(IW_CRNUM*k+IF_SIW_Min+IW_CR_OPCD) iw(k).wat := FALSE iw(k).single := FALSE tmpv := int2v1d( iw(k).opcode ) -- IDIOTIC ViewLogic crap IF is_single( tmpv ) THEN iw(k).single := TRUE single_flag := TRUE END IF iw(k).issued := FALSE iw(k).status := STATUS_none IF debug THEN putline("IW slot ",k) put(" valid = ",iw(k).valid) put(" issued = ",iw(k).issued) putline(" tag = ",iw(k).tag) puthexline(" status = ",iw(k).status) puthexline(" address = ",iw(k).address) puthexline(" opcode = ",iw(k).opcode) END IF END LOOP FOR k IN iw_bottom TO IW_Max - 1 LOOP iw(k).valid := FALSE END LOOP --- Now replace CR0 with the Saved Control value cr0 := int2v1d( cr(ICR_Saved_Control) ) x_cr0 <= cr0 IF cr0(Doit) = '1' THEN single_flag := TRUE END IF IF debug THEN puthexline(" CR0 = ",cr(ICR_Saved_Control)) puthexline("pc is now ",pc) putline("single_flag is now ",single_flag) tmpb1 := vlb2boo( cr0(Doit) ) -- stupid Viewlogic crap CHAPTER 2. VHDL SOURCE CODE 92 putline("doit_flag is now ",tmpb1) END IF --- That's it. The RTE has been replaced by the new IW --- contents, and everything is ready to continue dispatching. --- The SINGLE flag has been cleared if appropriate. --------- Now, I need to go back and try to dispatch all over again. Since the RTE was the only remaining instruction in the IW when I started, there's no external event to wake up the dispatch cycle again. I'll have to generate one. try_dispatch := TRUE done_dispatch := FALSE EXIT -- do it again -- don't count RTE -- hop out of dispatch loop delay_to_use := delay_to_use + delay_rte -- time to do RTE s_did_dispatch := s_did_dispatch + 1 -- count it ELSIF op_type = OP_sync THEN -- sync instruction IF trace_dispatch THEN put("Dispatch IW(",iw_index) put("/",icount) puthex("): op ",iw(iw_index).opcode) puthex(" addr ",iw(iw_index).address) putline(" SYNC") END IF --- This is complete, just by getting to the top. Remove it --- from the IW. Doesn't affect queue counts. It takes --- essentially no extra time. tmpi := iw_index iw_remove( tmpi, iw, iw_bottom, wat_flag, single_flag ) IF debug THEN putline("type OP_sync. Done by default.") putline("wat_flag is now ",wat_flag) putline("single_flag is now ",single_flag) END IF s_did_dispatch := s_did_dispatch + 1 -- count it ELSIF op_type = OP_sync_x THEN -- sync.x instruction IF trace_dispatch THEN put("Dispatch IW(",iw_index) put("/",icount) puthex("): op ",iw(iw_index).opcode) 2.14. DISPATCH.VHD 93 puthex(" addr ",iw(iw_index).address) putline(" SYNC.X") END IF --- Wait for external sync. Not interruptible. --- Doesn't affect queue counts. Is that bad? IF debug THEN putline("type OP_sync_x") END IF v_sync_req := NOT v_sync_req sync_req <= v_sync_req AFTER delay_to_use WAIT ON sync_ack, sync_nack -- might work, might not s_did_dispatch := s_did_dispatch + 1 -- either way it counts IF sync_ack'EVENT THEN -- did it --- Done. Remove this instruction from the IW. tmpi := iw_index iw_remove( tmpi, iw, iw_bottom, wat_flag, single_flag ) IF debug THEN putline("done with SYNC.X") putline("wat_flag is now ",wat_flag) putline("single_flag is now ",single_flag) END IF delay_to_use := delay_sync_ack ELSE -- didn't sync IF debug THEN putline("SYNC.X failed.") END IF iw(iw_index).status := STATUS_sync faulting_instruction := iw(iw_index) -- remember who did it IF v_fault_pending = '0' THEN -- need to signal fault v_fault_pending := '1' -- do so fault_pending <= v_fault_pending v_x_debug := NOT v_x_debug x_debug <= v_x_debug END IF delay_to_use := delay_sync_nack END IF CHAPTER 2. VHDL SOURCE CODE 94 ELSE -- any other instruction IF debug THEN putline("type OP_other") END IF --------------------------- Pick tag to assign to instruction. Note: It's possible to issue enough instructions that a tag would be reused before its first use has completed. For example, an instruction which uses R1 as a destination might take a VERY long time to get the result while a large number of much faster instructions complete. This could be a problem, unless some means of determining tag usage is provided. For the simulator, I'm just going to use a scoreboard to keep track of 8-bit tags, and if I can't find a free tag it means that I can't dispatch. In a real implementation I might use a different method (I really only need the same number of unique tags as there are slots in the IW, so a unary encoding would do). --- But wait! If the instruction doesn't report its DONE --- status, then I don't need to assign it a tag, because I'll --- remove it from the IW as soon as it goes out. --------------------------- I had to modify the tag meaning slightly. Originally, all branch instructions simply used the current value of cr0(Excp_Enable) to determine which Branch queue to place the target in. However, branch instructions do not fault, so if an interrupt is noticed after the branch has been issued but before it has completed, the target goes down the wrong pipe. Rather than add another bit to the existing FIFOs, I just modified the tag value so that bit 7 is used to indicate the queue in use when the instruction was issued. This doesn't affect the memory unit since it always has to report its status and the dispatch unit will wait for it to do so before handling exceptions. Only the branch unit uses the new tag bit for anything. IF tellme THEN -- assign tags tag_value := tag_value + 1 IF tag_value > Tag_Max_Value THEN tag_value := 0 END IF IF tag_sb(tag_value) THEN -- this tag is still in use --- try to find one that's not being used FOR j IN 1 TO Tag_Max_Value LOOP 2.14. DISPATCH.VHD 95 tmpi := j + tag_value -- determine tag to try IF tmpi > Tag_Max_Value THEN tmpi := tmpi - Tag_Max_Value END IF IF NOT tag_sb(tmpi) THEN tag_value := tmpi EXIT END IF -- if free, use it END LOOP --- if tag_sb(tag_value) is false, there are no free tags! ASSERT NOT tag_sb(tag_value) REPORT "Tag" SEVERITY FAILURE END IF -- finding tag tag_sb(tag_value) := TRUE -- mark tag in use END IF -- assigning tag --- We got a tag, so let's dispatch the instruction. iw(iw_index).tag := tag_value iw(iw_index).issued := TRUE -- only needed if tellme=TRUE -- ditto IF op_type = OP_mvbr THEN -- need branch target tmpmvbr := br v_br_ack := NOT v_br_ack br_ack <= v_br_ack -- grab branch target data -- eat branch target from queue -- ack branch data IF trace_dispatch THEN put("Dispatch IW(",iw_index) put("/",icount) puthex("): op ",iw(iw_index).opcode) puthex(" addr ",iw(iw_index).address) putline(" MVBR") END IF ELSE IF trace_dispatch THEN put("Dispatch IW(",iw_index) put("/",icount) puthex("): op ",iw(iw_index).opcode) puthexline(" addr ",iw(iw_index).address) END IF END IF CHAPTER 2. VHDL SOURCE CODE 96 IF ( ( debug OR debug_reuse ) AND reuse_result AND dest /= 0 AND dest /= 1 ) THEN put("unit ",fu_num) putline(" will latch register ",dest) END IF --------- The operand requests and scoreboard quickly, since this information was we were checking for scoreboard for The instruction information is what IF dest >= 1 THEN setting can go out determined earlier when dispatch conditions. takes additional time. -- set scoreboard bit IF debug THEN putline("setting scoreboard bit ",dest) END IF sb_set <= '1' tmpv := int2v1d( dest ) -- IDIOTIC ViewLogic crap sb_num <= tmpv(4 DOWNTO 0) v_sb_w_r := NOT v_sb_w_r sb_w_r <= v_sb_w_r AFTER delay_to_use WAIT ON sb_w_a END IF s_did_dispatch := s_did_dispatch + 1 IF cr0(Excp_Enable) = '0' THEN -- only count in exceptions s_excp_dispatch := s_excp_dispatch + 1 END IF IF vA OR vB OR vD THEN -- send operand request to RF s_need_operands := s_need_operands + 1 v_rf := rf_encode( vA, srcA, vB, srcB, vD, srcD ) rf <= v_rf v_rf_req := NOT v_rf_req rf_req <= v_rf_req AFTER delay_to_use --- I know it's ready, so I don't have to wait for the ACK END IF IF wat THEN -- also wat_flag if applicable wat_flag := TRUE IF debug THEN putline("wat_flag is now ",wat_flag) END IF END IF 2.14. DISPATCH.VHD br_count := new_br_count xbr_count := new_xbr_count r1_count := new_r1_count r1_pending := new_r1_pending 97 -- update queue counts -- this only decrements -- this only increments IF debug THEN putline("br_count is now ",br_count) putline("xbr_count is now ",xbr_count) putline("r1_count is now ",r1_count) putline("r1_pending is now ",r1_pending) END IF --- Send dispatch information ex <= EX_PADDING -- clear all bits first ex(90) <= boo2vlb( zeroA ) --- bits 89-87 are operand reuse bits ex(89) <= boo2vlb( reuseD ) ex(88) <= boo2vlb( reuseB ) ex(87) <= boo2vlb( reuseA ) --- bit 86 is set if instruction should report DONE status IF tellme THEN ex(86) <= '1' out_count := out_count + 1 -- I might have to wait for it IF debug THEN putline("now out_count = ",out_count) putline("tag = ",iw(iw_index).tag) END IF ELSE ex(86) <= '0' END IF --- bit 85 is set if operands are needed from the RF Unit IF vA OR vB OR vD THEN ex(85) <= '1' ELSE ex(85) <= '0' END IF --- bit 76 is part of the tag field containing the current --- value of cr0(Excp_Enable) but only for branch unit, so set --- the default now. ex(76) <= '0' --- bits 84-77 are select lines for functional units CASE op_type IS WHEN OP_arith => -- unit 0 ex(84 DOWNTO 77) <= ('0','0','0','0','0','0','0','1') CHAPTER 2. VHDL SOURCE CODE 98 WHEN OP_logic => -- unit 1 ex(84 DOWNTO 77) <= ('0','0','0','0','0','0','1','0') WHEN OP_ctrl | OP_mvbr => -- unit 2 ex(84 DOWNTO 77) <= ('0','0','0','0','0','1','0','0') WHEN OP_load | OP_store | OP_xmem => -- unit 3 ex(84 DOWNTO 77) <= ('0','0','0','0','1','0','0','0') WHEN OP_branch | OP_ldbr => -- unit 4 ex(84 DOWNTO 77) <= ('0','0','0','1','0','0','0','0') --- bit 76 is current value of cr0(Excp_Enable) ex(76) <= cr0(Excp_Enable) WHEN OTHERS => -- not implemented ex(84 DOWNTO 77) <= ('0','0','0','0','0','0','0','0') END CASE --- bits 75-69 are for instruction tag tmpv := int2v1d(tag_value) ex(75 DOWNTO 69) <= tmpv(6 DOWNTO 0) --- bits 68-64 is destination register (not always valid) tmpv := int2v1d(dest) ex(68 DOWNTO 64) <= tmpv(4 DOWNTO 0) --- bits 63-32 are usually PC, but may hold Branch Queue data IF op_type = OP_mvbr THEN ex(63 DOWNTO 32) <= tmpmvbr ELSE ex(63 DOWNTO 32) <= int2v1d( iw(iw_index).address ) END IF --- bits 31-0 are original opcode ex(31 DOWNTO 0) <= int2v1d( iw(iw_index).opcode ) v_ex_req := NOT v_ex_req ex_req <= v_ex_req AFTER delay_to_use done_ex_dispatch := TRUE IF debug THEN putline("instruction dispatched") END IF --- If the instruction isn't going to report its DONE status, --- then I need to remove it from the IW now, because otherwise --- it will never happen. IF NOT tellme THEN -- remove it tmpi := iw_index iw_remove( tmpi, iw, iw_bottom, wat_flag, single_flag ) IF debug THEN putline("instruction won't report -- removed from IW") END IF 2.14. DISPATCH.VHD 99 END IF END IF ----------- -- any other instruction Now, I've dispatched one instruction. I can't do more than one at a time, so I should quit the loop. I don't really need the loop at all once I've found a potential instruction, but it's convenient as a way to abort the whole dispatch process. done_dispatch := TRUE -- done one EXIT -- hop out of dispatch loop END LOOP END IF -- dispatching loop -- can I even try to dispatch IF debug THEN putline("done with this event") END IF END IF ----------- -- dispatch_req Now I should try to consume a DOIT, if there's one pending. Obviously, I can't do this if faults are pending or I'm otherwise prevented. I don't have to do this in any particular order. This isn't really a loop, it's just a convenient way to jump out if I want to. WHILE ( cr0(Doit) = '1' AND v_fault_pending = '0' ) LOOP ----------------- Check for deadlock condition. If the Doit flag is set, no the IW is empty and nothing is in the Branch Queue, then I'm waiting for a branch that will never arrive. Note that I won't notice deadlock at the same time that I notice external interrupts, since there is only one status register to indicate the cause of the exception. However, when handling any other exception, this deadlock condition can be detected by software by checking for the same conditions. IF ( iw_bottom = 0 AND ( (cr0(Excp_Enable) = '1' AND br_count = 0) OR (cr0(Excp_Enable) = '0' AND xbr_count = 0) ) ) THEN faulting_instruction := doit_instruction faulting_instruction.status := STATUS_lock_b0 CHAPTER 2. VHDL SOURCE CODE 100 v_fault_pending := '1' -- do so fault_pending <= v_fault_pending v_x_debug := NOT v_x_debug x_debug <= v_x_debug IF trace_excp THEN putline("deadlock exception") END IF EXIT -- jump out END IF IF cr0(Excp_Enable) = '1' THEN -- use normal Branch Queue IF debug THEN putline("Probing BR queue") END IF ---------- v_br_p_req := NOT v_br_p_req br_p_req <= v_br_p_req AFTER delay WAIT ON br_p_ack IF br_p = '0' THEN IF debug THEN putline("BR queue isn't ready") END IF EXIT END IF IF br(1) = '1' THEN -- if condition code pc := 4 * v1d2int(br(31 DOWNTO 2)) -- take branch END IF v_br_ack := NOT v_br_ack br_ack <= v_br_ack -- eat branch target from queue -- ack branch data br_count := br_count - 1 ELSE -- use X Branch Queue IF debug THEN putline("Probing XBR queue") END IF ---------- v_xbr_p_req := NOT v_xbr_p_req xbr_p_req <= v_xbr_p_req AFTER delay WAIT ON xbr_p_ack IF xbr_p = '0' THEN 2.14. DISPATCH.VHD 101 IF debug THEN putline("XBR queue isn't ready") END IF EXIT END IF IF xbr(1) = '1' THEN -- if condition code pc := 4 * v1d2int(xbr(31 DOWNTO 2)) -- take branch END IF v_xbr_ack := NOT v_xbr_ack -- eat branch target from queue xbr_ack <= v_xbr_ack -- ack branch data xbr_count := xbr_count - 1 END IF -- done consuming targets IF debug THEN puthexline("PC is now ",pc) END IF --- Done. Clear the Doit and single flags, and let a new --- instruction be requested. cr0(Doit) := '0' single_flag := FALSE IF debug THEN putline("Did a DOIT") putline("single_flag is now ",single_flag) putline("br_count is now ",br_count) putline("xbr_count is now ",xbr_count) END IF IF trace_dispatch THEN put("Dispatch IW(-/-): ") puthex("op ",doit_instruction.opcode) puthex(" addr ",doit_instruction.address) putline(" DOIT") END IF EXIT -- exit the loop now END LOOP -- looking for DOITs ----------- Deal with faults. If a fault has been signaled, all outstanding instructions must either complete or fault. Deadlock cannot occur, since we prevent that by counting producer/consumer pairs as they are dispatched. We don't have to lock the IW data structures, since we won't do anything until the entire chip is CHAPTER 2. VHDL SOURCE CODE 102 --- quiescent, and therefore we are the only ones using the IW. IF v_fault_pending = '1' THEN -- do nothing until all done IF debug THEN putline("fault is pending. sit and wait") putline("out_count = ",out_count) END IF --------------- Wait until we've heard from all outstanding instructions, then do interrupt handling stuff. I don't have to worry that all results have arrived at their destinations, provided I know that all instructions have completed. Anything that needs the results will just have to wait for them. I do have to wait for any outstanding instruction fetches, since those have to be put in the IW. IF ( out_count = 0 AND NOT waiting_for_inst ) THEN s_did_excp := s_did_excp + 1 IF debug THEN putline("everything has stopped. save status") END IF IF trace_excp THEN putline("iw_bottom = ",iw_bottom) putline("br_count = ",br_count) putline("r1_count = ",r1_count) END IF --- clear IW, WAT, SINGLE, scoreboard, etc. tmpi := 0 FOR i IN 0 TO (IW_Max - 1) LOOP -- save (internal) and clear IW IF iw(i).valid AND iw(i).status /= STATUS_none THEN tmpi := tmpi + 1 END IF siw(IW_CRNUM*i+IF_SIW_Min+IW_CR_STAT) siw(IW_CRNUM*i+IF_SIW_Min+IW_CR_ADDR) siw(IW_CRNUM*i+IF_SIW_Min+IW_CR_OPCD) siw(IW_CRNUM*i+IF_SIW_Min+IW_CR_ARG1) siw(IW_CRNUM*i+IF_SIW_Min+IW_CR_ARG2) iw(i).valid := FALSE := := := := := iw(i).status iw(i).address iw(i).opcode iw(i).arg1 iw(i).arg2 IF debug THEN putline("IW slot ",i) put(" valid = ",iw(i).valid) put(" issued = ",iw(i).issued) putline(" tag = ",iw(i).tag) puthexline(" status = ",iw(i).status) puthexline(" address = ",iw(i).address) 2.14. DISPATCH.VHD puthexline(" puthexline(" puthexline(" END IF 103 opcode = ",iw(i).opcode) arg1 = ",iw(i).arg1) arg2 = ",iw(i).arg2) END LOOP ----------- Save exception status in (internal) control registers. The r1_count and br_count values are needed to know how to empty and save the R1 and Branch Queues. This is done with normal instructions, so the counts do not need to be reloaded when the exception is over. cr(ICR_Saved_Control) := v1d2int(cr0) cr(ICR_Fault_Status) := faulting_instruction.status cr(ICR_Fault_Address) := faulting_instruction.address cr(ICR_Next_PC) := pc cr(ICR_BR_Count) := br_count cr(ICR_R1_Count) := r1_count cr(ICR_IW_Count) := iw_bottom cr(ICR_IW_Faults) := tmpi IF debug THEN puthexline(" ICR_Saved_Control = ",cr(ICR_Saved_Control)) puthexline(" ICR_Fault_Status = ",cr(ICR_Fault_Status)) puthexline(" ICR_Fault_Address = ",cr(ICR_Fault_Address)) puthexline(" ICR_Next_PC = ",cr(ICR_Next_PC)) putline(" ICR_BR_Count = ",cr(ICR_BR_Count)) putline(" ICR_R1_Count = ",cr(ICR_R1_Count)) putline(" ICR_IW_Count = ",cr(ICR_IW_Count)) putline(" ICR_IW_Faults = ",cr(ICR_IW_Faults)) END IF iw_bottom := 0 -- IW is now empty FOR i IN 0 TO Tag_Max_Value LOOP tag_sb(i) := FALSE END LOOP -- clear the tag scoreboard wat_flag := FALSE single_flag := FALSE tag_value := 0 out_count := 0 --- turn off interrupts, exceptions, etc. --- Excp_Enable bit controls queue --- set supervisor mode. tmpv := ZERO(31 DOWNTO 0) tmpv(Supervisor) := '1' cr0 := tmpv x_cr0 <= cr0 -- change CR0 CHAPTER 2. VHDL SOURCE CODE 104 --- clear fault_pending after interrupts are disabled v_fault_pending := '0' fault_pending <= v_fault_pending AFTER delay --- If exceptions were already disabled, take error vector. tmpv := int2v1d( cr(ICR_Saved_Control) ) -- convert to vlbit IF tmpv(Excp_Enable) = '0' THEN faulting_instruction.status := STATUS_error END IF --- Set PC to interrupt handler address. Each exception vector --- has four status values available to it, so the status code --- can be truncated to determine the vector address. tmpv := tmpi := IF tmpi pc := ELSE pc := END IF int2v1d(faulting_instruction.status) v1d2int(tmpv(15 DOWNTO 0)) -- get major status >= STATUS_trap THEN 4 * v1d2int( tmpv( 7 DOWNTO 0) ) 4 * v1d2int( tmpv( 7 DOWNTO 2) ) --- Now everything is ready to go. Let INST_REQ go out below. IF debug OR trace_dispatch THEN puthexline("faulting status is ",faulting_instruction.status) puthexline("ready for vector. PC is now ",pc) END IF --- We can just sit and wait here, since nothing else should be --- going on anyway. WAIT FOR delay_save_state END IF END IF ----------- -- time to save state -- outstanding insts -- fault pending Send out a request for more instructions to dispatch. If there's a fault pending, we don't request any new instructions until the PC has been set to the exception handler. Otherwise, if there's room for another instruction in the IW, and the SINGLE flag isn't set, and we haven't already, then request the next instruction. IF v_fault_pending = '1' THEN -- skip back to top of loop IF debug THEN putline("no inst reqs while faults are pending") 2.14. DISPATCH.VHD 105 END IF NEXT END IF IF ((IW_tap - iw_bottom) >= 1 ) AND NOT single_flag THEN IF waiting_for_inst THEN -- skip back to top of loop IF debug THEN putline("already requested an instruction") END IF NEXT END IF v_i_addr := int2v1d(pc) -- get 32-bit PC value i_addr <= (v_i_addr(31 DOWNTO 2) & cr0(Supervisor) & '0') v_inst_req := NOT v_inst_req inst_req <= v_inst_req AFTER delay IF debug THEN puthexline("sent out INST_REQ for address ",pc) END IF waiting_for_inst := TRUE END IF END LOOP END IF ----------- -- main process loop -- CLR not asserted Wait for something new to happen. The four main events are arbitrated, so that data structures can be shared. The control register requests do not need arbitration, since control registers are only written when everything else is quiet. The other events just awaken the dispatch process. IF debug THEN putline("wait for something to happen") END IF WAIT ON clr, inst_ack, done_req, external_int, getcr_req, putcr_req, br_p, xbr_p, rf_p, ex_p, sb END PROCESS main END behavior CHAPTER 2. VHDL SOURCE CODE 106 2.15 logic unit.vhd USE work.p_constants.ALL USE work.p_output.ALL ---- This unit handles the logic instructions. Currently, there is only ---- one of these units, and it is very simple. It could be expanded to do ---- split transactions, reordering memory operations, etc. ---------------------- The EXTRA input was added to provide last-result-reuse and to elminate zero values of op_a for immediate instructions. The bit usage is: EXTRA(0) EXTRA(1) EXTRA(2) EXTRA(3) = = = = reuseA reuseB reuseD zeroA (unused) ENTITY logic_unit IS GENERIC( delay: TIME := 100 ps ) PORT( SIGNAL clr : IN SIGNAL rin : IN SIGNAL ain : OUT SIGNAL tellme : IN SIGNAL tag : IN SIGNAL dest : IN SIGNAL opcode : IN SIGNAL op_a : IN SIGNAL op_b : IN SIGNAL d_req : OUT SIGNAL d_ack : IN SIGNAL done : OUT SIGNAL rout : OUT SIGNAL aout : IN SIGNAL res : OUT SIGNAL rq_req : OUT SIGNAL rq_ack : IN SIGNAL rq : OUT SIGNAL extra : IN END logic_unit VLBIT VLBIT VLBIT VLBIT VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT_1D (7 DOWNTO 0) (4 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (87 DOWNTO 0) (36 DOWNTO 0) (31 DOWNTO 0) (3 DOWNTO 0) ) ARCHITECTURE behavior OF logic_unit IS BEGIN main : PROCESS VARIABLE debug : BOOLEAN := FALSE --- factors affecting response time VARIABLE delay_boolean VARIABLE delay_barrel VARIABLE delay_ff : TIME := 100 ps -- boolean operations : TIME := 100 ps -- need barrel shifter : TIME := 100 ps -- find first bit stuff 2.15. LOGIC UNIT.VHD VARIABLE delay_to_use 107 : TIME -- scratch for culumative time --- output variables VARIABLE v_rout VARIABLE v_rq_req VARIABLE v_d_req : VLBIT : VLBIT : VLBIT --- internal variables VARIABLE index : INTEGER VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE : : : : : : Av Bv Wi Oi result lastresult VLBIT_1D VLBIT_1D INTEGER INTEGER VLBIT_1D VLBIT_1D (31 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) --- scratch variables VARIABLE tmpv VARIABLE tmpb VARIABLE tmpi : VLBIT_1D (31 DOWNTO 0) : VLBIT : INTEGER --- statistics VARIABLE s_logic_rin VARIABLE s_barrel VARIABLE s_ff : INTEGER : INTEGER : INTEGER BEGIN --- If clear is asserted, reset everything and stick here. IF clr /= '1' THEN v_rout := '0' v_rq_req := '0' v_d_req := '0' ain <= '0' d_req <= v_d_req done <= ZERO(87 DOWNTO 0) rout <= v_rout res <= ZERO(36 DOWNTO 0) rq_req <= v_rq_req rq <= ZERO(31 DOWNTO 0) -- reset to beginning CHAPTER 2. VHDL SOURCE CODE 108 s_logic_rin := 0 s_barrel := 0 s_ff := 0 WAIT UNTIL clr = '1' ELSE --------- -- only wakeup event is RIN This stuff had to be encoded by hand. I could have written a Perl script to do it, but it would have taken longer than doing it manually. This stuff shouldn't change that much (I hope). I also made some assumptions about unused bits, which is probably okay. --- I don't bother to compute anything if I'm just going to throw the --- result away. IF dest /= REG_R0 THEN -- only if worth doing s_logic_rin := s_logic_rin + 1 delay_to_use := delay_boolean -- assume simple case index := op2index( opcode ) -- identify instruction --- determine operands IF extra(0)='1' THEN Av := lastresult ELSE Av := op_a END IF IF index <= 31 OR (index >= 72 AND index <= 77) THEN -- immediate --- All Immediate operands are zero-extended (this could change). Bv := ZERO(31 DOWNTO 16) & opcode(15 DOWNTO 0) ELSE -- triadic IF extra(1)='1' THEN Bv := lastresult ELSE Bv := op_b END IF END IF IF debug THEN tmpi := v1d2int(Av) puthexline("op_a is ",tmpi) tmpi := v1d2int(Bv) puthexline("op_b is ",tmpi) END IF 2.15. LOGIC UNIT.VHD 109 --- get W and O fields just in case. Wi := v1d2int( Bv(9 DOWNTO 5) ) IF Wi = 0 THEN Wi := 32 END IF Oi := v1d2int( Bv(4 DOWNTO 0) ) --- now, do the operation CASE index IS WHEN 0 => -- and rd,ra,imm16 tmpv := Av AND Bv result := Av(31 DOWNTO 16) & tmpv(15 DOWNTO 0) WHEN 1 => -- and.u rd,ra,imm16 Bv := Bv(15 DOWNTO 0) & Bv(15 DOWNTO 0) tmpv := Av AND Bv result := tmpv(31 DOWNTO 16) & Av(15 DOWNTO 0) WHEN 2 => -- mask rd,ra,imm16 tmpv := Av AND Bv result := ZERO(31 DOWNTO 16) & tmpv(15 DOWNTO 0) WHEN 3 => -- mask.u rd,ra,imm16 Bv := Bv(15 DOWNTO 0) & Bv(15 DOWNTO 0) tmpv := Av AND Bv result := tmpv(31 DOWNTO 16) & ZERO(15 DOWNTO 0) WHEN 4 => -- or rd,ra,imm16 tmpv := Av OR Bv result := Av(31 DOWNTO 16) & tmpv(15 DOWNTO 0) WHEN 5 => -- or.u rd,ra,imm16 Bv := Bv(15 DOWNTO 0) & Bv(15 DOWNTO 0) tmpv := Av OR Bv result := tmpv(31 DOWNTO 16) & Av(15 DOWNTO 0) WHEN 6 => -- xor rd,ra,imm16 tmpv := Av XOR Bv result := Av(31 DOWNTO 16) & tmpv(15 DOWNTO 0) WHEN 7 => -- xor.u rd,ra,imm16 CHAPTER 2. VHDL SOURCE CODE 110 Bv := Bv(15 DOWNTO 0) & Bv(15 DOWNTO 0) tmpv := Av XOR Bv result := tmpv(31 DOWNTO 16) & Av(15 DOWNTO 0) WHEN 32 => -- and rd,ra,rb result := Av AND Bv WHEN 33 => -- and.c rd,ra,rb result := Av AND NOT Bv WHEN 36 => -- or rd,ra,rb result := Av OR Bv WHEN 37 => -- or.c rd,ra,rb result := Av OR NOT Bv WHEN 38 => -- xor rd,ra,rb result := Av XOR Bv WHEN 39 => -- xor.c rd,ra,rb result := Av XOR NOT Bv WHEN 64 | 72 => -- clr s_barrel := s_barrel + 1 delay_to_use := delay_barrel FOR k IN 0 TO 31 IF k >= Oi AND result(k) := ELSE result(k) := END IF END LOOP LOOP k < (Oi + Wi) THEN '0' -- in range Av(k) WHEN 65 | 73 => -- set s_barrel := s_barrel + 1 delay_to_use := delay_barrel FOR k IN 0 TO 31 IF k >= Oi AND result(k) := ELSE result(k) := END IF LOOP k < (Oi + Wi) THEN '1' Av(k) -- in range 2.15. LOGIC UNIT.VHD 111 END LOOP WHEN 66 | 74 => -- ext s_barrel := s_barrel + 1 delay_to_use := delay_barrel tmpi := Wi + Oi - 1 IF tmpi > 31 THEN tmpb := Av(31) ELSE tmpb := Av(tmpi) END IF FOR k IN 0 TO 31 LOOP IF k < Wi AND k+Oi <= 31 THEN result(k) := Av(k+Oi) ELSE result(k) := tmpb END IF END LOOP WHEN 67 | 75 => -- determine sign bit -- copy sign bit -- extu s_barrel := s_barrel + 1 delay_to_use := delay_barrel FOR k IN 0 TO 31 LOOP IF k < Wi AND k+Oi <= 31 THEN result(k) := Av(k+Oi) ELSE result(k) := '0' END IF END LOOP WHEN 68 | 76 => -- mak s_barrel := s_barrel + 1 delay_to_use := delay_barrel FOR k IN 0 TO 31 IF k >= Oi AND result(k) := ELSE result(k) := END IF END LOOP LOOP k < (Oi + Wi) THEN Av(k-Oi) -- in range '0' WHEN 69 | 77 => s_barrel := s_barrel + 1 -- rot CHAPTER 2. VHDL SOURCE CODE 112 delay_to_use := delay_barrel FOR k IN 0 TO 31 LOOP IF k+Oi <= 31 THEN result(k) := Av(k+Oi) ELSE result(k) := Av(K+Oi-32) END IF END LOOP WHEN 70 => -- ff0 rd,rb s_ff := s_ff + 1 delay_to_use := delay_ff tmpi := 32 FOR k IN 31 DOWNTO 0 LOOP IF Bv(k) = '0' THEN tmpi := k EXIT END IF END LOOP result := int2v1d(tmpi) WHEN 71 => -- ff1 rd,rb s_ff := s_ff + 1 delay_to_use := delay_ff tmpi := 32 FOR k IN 31 DOWNTO 0 LOOP IF Bv(k) = '1' THEN tmpi := k EXIT END IF END LOOP result := int2v1d(tmpi) WHEN OTHERS => -- anything else putline("*** Illegal Opcode for Logic Unit ***") END CASE --- write output IF dest = REG_R1 THEN rq <= result v_rq_req := NOT v_rq_req rq_req <= v_rq_req AFTER delay_to_use 2.15. LOGIC UNIT.VHD 113 WAIT ON rq_ack ELSE res <= dest & result lastresult := result IF debug THEN tmpi := v1d2int(lastresult) puthexline("latched ",tmpi) END IF v_rout := NOT v_rout rout <= v_rout AFTER delay_to_use -- write it out WAIT ON aout END IF END IF -- produce a result --- signal completion of this instruction IF tellme = '1' THEN -- only if needed tmpv := int2v1d( STATUS_done ) done <= ZERO(87 DOWNTO 24) & tmpv(15 DOWNTO 0) & tag v_d_req := NOT v_d_req d_req <= v_d_req AFTER delay WAIT ON d_ack END IF ain <= rin AFTER delay -- done with this event END IF -- clr not asserted WAIT ON clr, rin -- wait for next event END PROCESS main END behavior CHAPTER 2. VHDL SOURCE CODE 114 2.16 memory unit.vhd USE work.p_constants.ALL USE work.p_memory_unit.ALL USE work.p_output.ALL ---- The memory_unit module provides the interface to the external data memory. ---------------------- The EXTRA input was added to provide last-result-reuse and to elminate zero values of op_a for immediate instructions. The bit usage is: EXTRA(0) EXTRA(1) EXTRA(2) EXTRA(3) = = = = reuseA reuseB reuseD zeroA (unused) ENTITY memory_unit IS GENERIC( delay: TIME := 100 ps ) PORT( SIGNAL clr : IN SIGNAL rin : IN SIGNAL ain : OUT SIGNAL tellme : IN SIGNAL tag : IN SIGNAL dest : IN SIGNAL opcode : IN SIGNAL op_s : IN SIGNAL op_a : IN SIGNAL op_b : IN SIGNAL data_req : OUT SIGNAL data_ack : IN SIGNAL data_ack_ack : OUT SIGNAL read : OUT SIGNAL byte_strobe : OUT SIGNAL d_addr : OUT SIGNAL d_read : IN SIGNAL d_status : IN SIGNAL d_write : OUT SIGNAL cr0 : IN SIGNAL d_req : OUT SIGNAL d_ack : IN SIGNAL done : OUT SIGNAL reg_q_req : OUT SIGNAL reg_q_ack : IN SIGNAL reg_q : OUT SIGNAL r1_q_req : OUT SIGNAL r1_q_ack : IN SIGNAL r1_q : OUT SIGNAL extra : IN END memory_unit VLBIT VLBIT VLBIT VLBIT VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT VLBIT VLBIT VLBIT VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT_1D ARCHITECTURE behavior OF memory_unit IS BEGIN (7 DOWNTO 0) (4 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (3 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (3 DOWNTO 0) (31 DOWNTO 0) (31 DOWNTO 0) (87 DOWNTO 0) (36 DOWNTO 0) (31 DOWNTO 0) (3 DOWNTO 0) ) 2.16. MEMORY UNIT.VHD 115 main : PROCESS VARIABLE debug : BOOLEAN := FALSE --- Minor status code values. The minor field is actually --- "operation + opsize". Opsize is currently only 1, 2, or 4. --- I'm leaving room for size 8. CONSTANT MINOR_load CONSTANT MINOR_store CONSTANT MINOR_xmem : INTEGER := 16 : INTEGER := 32 : INTEGER := MINOR_load + MINOR_store --- factors affecting response time VARIABLE delay_decode : TIME := 100 ps -- decode & compute address --- internal variables VARIABLE VARIABLE VARIABLE VARIABLE lastresult op_aa op_bb op_ss : : : : VLBIT_1D(31 VLBIT_1D(31 VLBIT_1D(31 VLBIT_1D(31 DOWNTO DOWNTO DOWNTO DOWNTO 0) 0) 0) 0) VARIABLE opA VARIABLE opB VARIABLE addr : INTEGER : INTEGER : INTEGER VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE imm opsize scaled do_sign_ext force_usr_mode do_load do_store : : : : : : : BOOLEAN INTEGER BOOLEAN BOOLEAN BOOLEAN BOOLEAN BOOLEAN VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE read_result status minor arg1 arg2 : : : : : VLBIT_1D (31 DOWNTO 0) INTEGER INTEGER INTEGER INTEGER --- output signal value variables VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE v_byte_strobe v_d_addr v_data_req v_d_req v_r1_q_req v_reg_q_req : : : : : : VLBIT_1D (3 DOWNTO 0) VLBIT_1D (31 DOWNTO 0) VLBIT VLBIT VLBIT VLBIT --- scratch variables VARIABLE tmpi : INTEGER CHAPTER 2. VHDL SOURCE CODE 116 VARIABLE tmpv VARIABLE DoTheLoop : VLBIT_1D (31 DOWNTO 0) : BOOLEAN --- statistics VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE s_memory_rin s_lda s_load_word s_load_half s_load_byte s_store_word s_store_half s_store_byte : : : : : : : : INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER BEGIN --- If clear is asserted, reset everything and stick here. IF clr /= '1' THEN v_byte_strobe := ('0','0','0','0') v_d_addr := ZERO(31 DOWNTO 0) v_data_req := '0' v_d_req := '0' v_r1_q_req := '0' v_reg_q_req := '0' ain <= '0' byte_strobe <= v_byte_strobe d_addr <= v_d_addr d_write <= ZERO(31 DOWNTO 0) data_req <= v_data_req data_ack_ack <= '0' d_req <= v_d_req done <= ZERO(87 DOWNTO 0) r1_q <= ZERO(31 DOWNTO 0) r1_q_req <= v_r1_q_req read <= '0' reg_q <= ZERO(36 DOWNTO 0) reg_q_req <= v_reg_q_req s_memory_rin := 0 s_lda := 0 s_load_word := 0 s_load_half := 0 s_load_byte := 0 s_store_word := 0 s_store_half := 0 s_store_byte := 0 WAIT UNTIL clr = '1' -- reset to beginning 2.16. MEMORY UNIT.VHD ELSE 117 -- only wakeup event is RIN s_memory_rin := s_memory_rin + 1 --- Determine what operands to use. IF extra(0)='1' THEN op_aa := lastresult ELSE op_aa := op_a END IF IF extra(1)='1' THEN op_bb := lastresult ELSE op_bb := op_b END IF IF extra(2)='1' THEN op_ss := lastresult ELSE op_ss := op_s END IF IF debug THEN puthexline("op_a is ",tmpi) tmpi := v1d2int(op_bb) puthexline("op_b is ",tmpi) tmpi := v1d2int(op_ss) puthexline("op_s is ",tmpi) END IF --------- There are number of sequential steps, which I need to abort if I get a fault at any point. This loop lets me jump immediately to the end of the sequence when I detect a fault. It doesn't really loop. DoTheLoop := TRUE WHILE DoTheLoop LOOP DoTheLoop := FALSE status := STATUS_done arg1 := 0 arg2 := 0 -- do it -- here it is -- no, don't do it -- assume it will work --- Determine what to do. mem_decode( opcode, imm, -- boolean CHAPTER 2. VHDL SOURCE CODE 118 opsize, scaled, do_sign_ext, force_usr_mode, do_load, do_store ) ------- integer boolean boolean boolean boolean boolean --- Compute address opA := v1d2int( op_aa ) IF imm THEN -- use imm16 value opB := v1d2int( opcode( 15 DOWNTO 0 ) ) ELSE -- use register value opB := v1d2int( op_bb ) IF scaled THEN -- scale factor opB := opB * opsize END IF END IF addr := opA + opB -- add 'em together --- Model this computation time. I can just wait, because there is only --- one possible wake-up event, and it isn't in parallel with anything. WAIT FOR delay_decode --- deal with lda instructions as a special case IF ( NOT do_load ) AND ( NOT do_store ) THEN -- lda instruction s_lda := s_lda + 1 read_result := int2v1d( addr ) IF dest = REG_R1 THEN -- dest is R1 Queue r1_q <= read_result v_r1_q_req := NOT v_r1_q_req r1_q_req <= v_r1_q_req AFTER delay WAIT ON r1_q_ack ELSIF dest /= REG_R0 THEN reg_q <= dest & read_result lastresult := read_result -- dest is not R0 2.16. MEMORY UNIT.VHD 119 IF debug THEN tmpi := v1d2int(lastresult) puthexline("latched ",tmpi) END IF v_reg_q_req := NOT v_reg_q_req reg_q_req <= v_reg_q_req AFTER delay WAIT ON reg_q_ack END IF EXIT END IF -- jump out here -- lda instruction --- make sure address alignment is okay for operation size IF (addr MOD opsize) /= 0 THEN -- misalignment status := STATUS_align IF do_load AND do_store THEN minor := MINOR_xmem + opsize ELSIF do_load THEN minor := MINOR_load + opsize ELSE minor := MINOR_store + opsize END IF arg1 := addr arg2 := v1d2int( op_ss ) -- that's a fault EXIT -- jump to end -- just in case END IF --- set supervisor bit as desired tmpv := int2v1d( addr ) IF force_usr_mode THEN v_d_addr := (tmpv(31 DOWNTO 2) & '0' & '0') ELSE v_d_addr := (tmpv(31 DOWNTO 2) & cr0(Supervisor) & '0') END IF --- determine byte strobe values IF opsize = 4 THEN v_byte_strobe := ('1','1','1','1') ELSIF opsize = 2 THEN IF (addr MOD 4) = 0 THEN -- word -- half-word -- lower half CHAPTER 2. VHDL SOURCE CODE 120 v_byte_strobe := ('0','0','1','1') ELSE v_byte_strobe := ('1','1','0','0') END IF ELSE tmpi := addr MOD 4 IF tmpi = 0 THEN v_byte_strobe := ('0','0','0','1') ELSIF tmpi = 1 THEN v_byte_strobe := ('0','0','1','0') ELSIF tmpi = 2 THEN v_byte_strobe := ('0','1','0','0') ELSE v_byte_strobe := ('1','0','0','0') END IF END IF -- upper half -- byte -- byte 0 -- byte 1 -- byte 2 -- byte 3 --- Do read operation if requested IF do_load THEN IF opsize = 4 THEN s_load_word := s_load_word + 1 ELSIF opsize = 2 THEN s_load_half := s_load_half + 1 ELSE s_load_byte := s_load_byte + 1 END IF read <= '1' byte_strobe <= v_byte_strobe d_addr <= v_d_addr v_data_req := NOT v_data_req data_req <= v_data_req AFTER delay -- send read request WAIT ON data_ack -- wait for response --- check for memory fault IF ( ( d_status(0) = '1' ( d_status(1) = '1' ( d_status(2) = '1' ( d_status(3) = '1' THEN status := STATUS_dmem ELSE AND AND AND AND cr0(Dmem0) cr0(Dmem1) cr0(Dmem2) cr0(Dmem3) = = = = '1' '1' '1' '1' ) ) ) ) OR OR OR ) --- sign-extend or zero-extend the result according to size read_result := d_read -- get result 2.16. MEMORY UNIT.VHD 121 IF opsize = 2 THEN IF do_sign_ext AND d_read(15) = '1' THEN read_result(31 DOWNTO 16) := ('1','1','1','1','1','1','1','1', '1','1','1','1','1','1','1','1') ELSE read_result(31 DOWNTO 16) := ZERO(31 DOWNTO 16) END IF ELSIF opsize = 1 THEN IF do_sign_ext AND d_read(7) = '1' THEN read_result(31 DOWNTO 8) := ('1','1','1','1','1','1','1','1', '1','1','1','1','1','1','1','1', '1','1','1','1','1','1','1','1') ELSE read_result(31 DOWNTO 8) := ZERO(31 DOWNTO 8) END IF END IF END IF --- now acknowledge receipt of status and data data_ack_ack <= data_ack AFTER delay IF status /= STATUS_done THEN -- found a fault IF do_store THEN minor := MINOR_xmem + opsize ELSE minor := MINOR_load + opsize END IF arg1 := addr arg2 := v1d2int( op_ss ) -- this is xmem instruction EXIT -- jump to end END IF END IF --- Do write operation if requested IF do_store THEN IF opsize = 4 THEN s_store_word := s_store_word + 1 ELSIF opsize = 2 THEN -- of do_load CHAPTER 2. VHDL SOURCE CODE 122 s_store_half := s_store_half + 1 ELSE s_store_byte := s_store_byte + 1 END IF read <= '0' byte_strobe <= v_byte_strobe d_addr <= v_d_addr --- align and shift the output data correctly IF opsize = 4 THEN -- full word at once d_write <= op_ss ELSIF opsize = 2 THEN -- half word d_write( 31 DOWNTO 16 ) <= op_ss( 15 DOWNTO 0) d_write( 15 DOWNTO 0 ) <= op_ss( 15 DOWNTO 0) ELSE -- byte d_write( 31 DOWNTO 24 ) <= op_ss( 7 DOWNTO 0) d_write( 23 DOWNTO 16 ) <= op_ss( 7 DOWNTO 0) d_write( 15 DOWNTO 8 ) <= op_ss( 7 DOWNTO 0) d_write( 7 DOWNTO 0 ) <= op_ss( 7 DOWNTO 0) END IF v_data_req := NOT v_data_req data_req <= v_data_req AFTER delay -- send read request WAIT ON data_ack -- wait for response --- check for memory fault IF ( ( d_status(0) = '1' ( d_status(1) = '1' ( d_status(2) = '1' ( d_status(3) = '1' THEN status := STATUS_dmem END IF AND AND AND AND cr0(Dmem0) cr0(Dmem1) cr0(Dmem2) cr0(Dmem3) = = = = '1' '1' '1' '1' ) ) ) ) OR OR OR ) --- now acknowledge receipt of status data_ack_ack <= data_ack AFTER delay IF status /= STATUS_done THEN IF do_load THEN minor := MINOR_xmem + opsize ELSE minor := MINOR_store + opsize END IF arg1 := addr -- found a fault -- this is xmem instruction 2.16. MEMORY UNIT.VHD 123 arg2 := v1d2int( op_ss ) EXIT -- jump to end END IF END IF -- of do_store --- Everything was successful. Put any read result out the queue. IF do_load THEN IF dest = REG_R1 THEN -- if load operation -- dest is R1 Queue r1_q <= read_result v_r1_q_req := NOT v_r1_q_req r1_q_req <= v_r1_q_req AFTER delay WAIT ON r1_q_ack ELSIF dest /= REG_R0 THEN -- dest is not R0 reg_q <= dest & read_result lastresult := read_result IF debug THEN tmpi := v1d2int(lastresult) puthexline("latched ",tmpi) END IF v_reg_q_req := NOT v_reg_q_req reg_q_req <= v_reg_q_req AFTER delay WAIT ON reg_q_ack END IF END IF END LOOP -- here's the jump-out point --- Send completion status. IF tellme = '1' THEN -- only if needed tmpi := status + 256 * minor tmpv := int2v1d( tmpi ) done <= int2v1d(arg1) & int2v1d(arg2) & tmpv(15 DOWNTO 0) & tag CHAPTER 2. VHDL SOURCE CODE 124 v_d_req := NOT v_d_req d_req <= v_d_req AFTER delay WAIT ON d_ack END IF ain <= rin AFTER delay -- done with this event END IF -- clr not asserted WAIT ON clr, rin -- wait for next event END PROCESS main END behavior 2.17. P ARITH.VHD 2.17 p arith.vhd PACKAGE p_arith IS ----------- Stupid ViewLogic VHDL doesn't implement addum correctly for 32 bits. I have to write my own. Bunch of idiots. Not only that, but it's impossible to make these functions work generically for any vector length, because you can't put expressions in the range of variable declarations. FUNCTION add32( Av, Bv : VLBIT_1D Cin : VLBIT ) RETURN VLBIT_1D FUNCTION sub32( Av, Bv : VLBIT_1D Cin : VLBIT ) RETURN VLBIT_1D END p_arith PACKAGE BODY p_arith IS --- Compute sum of two 32-bit vectors (A + B). The result is two bits longer --- than the input vectors. Bit 33 of the result is the overflow bit, bit 32 --- is the carry out. FUNCTION add32( Av, Bv : VLBIT_1D Cin : VLBIT ) RETURN VLBIT_1D IS VARIABLE res : VLBIT_1D( 33 DOWNTO 0 ) VARIABLE carry : VLBIT BEGIN carry := Cin FOR k IN 0 TO 31 LOOP res(k) := Av(k) XOR Bv(k) XOR carry carry := (Av(k) AND Bv(k)) OR (carry AND (Av(k) OR Bv(k))) END LOOP res(32) := carry -- carry out --- overflow bit res(33) := ( (Bv(Bv'left) AND Av(Av'left) AND NOT res(Av'left)) OR (NOT Bv(Bv'left) AND NOT Av(Av'left) AND res(Av'left)) ) RETURN res END add32 --- Compute difference of two 32-bit vectors (A - B). The result is two bits --- longer than the input vectors. Bit 33 of the result is the overflow bit, --- bit 32 is the carry out. FUNCTION sub32( Av, Bv : VLBIT_1D Cin : VLBIT ) 125 CHAPTER 2. VHDL SOURCE CODE 126 RETURN VLBIT_1D IS VARIABLE res : VLBIT_1D(33 DOWNTO 0) VARIABLE carry : VLBIT BEGIN carry := Cin FOR k IN 0 TO 31 LOOP res(k) := Av(k) XOR (NOT Bv(k)) XOR carry carry := (Av(k) AND (NOT Bv(k))) OR (carry AND (Av(k) OR (NOT Bv(k)))) END LOOP res(32) := carry -- carry out --- overflow bit res(33) := ( (NOT Bv(Bv'left) AND Av(Av'left) AND NOT res(Av'left)) OR (Bv(Bv'left) AND NOT Av(Av'left) AND res(Av'left)) ) RETURN res END sub32 END p_arith 2.18. P CONSTANTS.VHD 127 2.18 p constants.vhd --- Constants used in place of magic numbers, where possible. PACKAGE p_constants IS ---- Misc. useful constants. CONSTANT REG_R1: VLBIT_1D(4 DOWNTO 0) := ('0','0','0','0','1') CONSTANT REG_R0: VLBIT_1D(4 DOWNTO 0) := ('0','0','0','0','0') CONSTANT ZERO : VLBIT_1D(151 DOWNTO 0) := ('0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0') CONSTANT NEGMAX : VLBIT_1D(31 DOWNTO 0) := ('1','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0') ---- Control register 0 bits. CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT Imem0 Imem1 Imem2 Imem3 Supervisor Int_Enable Excp_Enable Doit Dmem0 Dmem1 Dmem2 Dmem3 : : : : : : : : : : : : INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER := := := := := := := := := := := := 0 1 2 3 4 5 6 7 8 9 10 11 ---- Number of Instruction Window slots CHAPTER 2. VHDL SOURCE CODE 128 CONSTANT IW_Max : INTEGER := 16 ---- Number of control registers for each IW slot CONSTANT IW_CRNUM : INTEGER := 5 CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT : : : : : IW_CR_STAT IW_CR_ADDR IW_CR_OPCD IW_CR_ARG1 IW_CR_ARG2 INTEGER INTEGER INTEGER INTEGER INTEGER := := := := := 0 1 2 3 4 -- what they mean ---- Location of control registers. These are the registers which are not ---- normally visible. CR0 is a special case, since it is visible everywhere. --- IF Unit registers CONSTANT IF_ICR_Min CONSTANT IF_ICR_Max CONSTANT IF_SIW_Min CONSTANT IF_SIW_Max : : : : INTEGER INTEGER INTEGER INTEGER := := := := 1 -- normal registers 12 100 -- shadow IW registers IF_SIW_Min + IW_CRNUM*IW_Max - 1 ---- Exception vector numbers CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT VECTOR_reset VECTOR_imem VECTOR_dmem VECTOR_illegal VECTOR_error VECTOR_int : : : : : : INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER := := := := := := 0 1 2 3 4 5 ---- Status code values. CONSTANT STATUS_none CONSTANT STATUS_done : INTEGER := 0 : INTEGER := 1 ----- no status yet completed successfully undecided undecided CONSTANT STATUS_imem : INTEGER := 4 ----- imem fault undecided undecided undecided CONSTANT STATUS_dmem CONSTANT STATUS_align : INTEGER := 8 : INTEGER := 9 ----- dmem fault misaligned data access undecided undecided CONSTANT STATUS_illegal CONSTANT STATUS_user : INTEGER := 12 : INTEGER := 13 ----- unimplemented opcode user mode violation undecided undecided 2.18. P CONSTANTS.VHD 129 CONSTANT STATUS_error : INTEGER := 16 ----- unrecoverable error undecided undecided undecided CONSTANT STATUS_int CONSTANT STATUS_sync : INTEGER := 20 : INTEGER := 21 ----- external interrupt sync.x aborted externally undecided undecided CONSTANT CONSTANT CONSTANT CONSTANT : : : : 24 25 26 27 ----- deadlock deadlock deadlock deadlock CONSTANT STATUS_overflow : INTEGER := 28 ----- integer overflow undecided undecided undecided CONSTANT STATUS_int_div ----- integer divide error undecided undecided undecided ------------- STATUS_lock_b0 STATUS_lock_b1 STATUS_lock_r0 STATUS_lock_r1 INTEGER INTEGER INTEGER INTEGER := := := := : INTEGER := 32 on on on on BR BR R1 R1 Queue Queue Queue Queue empty full empty full Trap code values. When bit 8 of the status is set, it indicates that the vector was taken as the result of a trap instruction. In the dispatch unit, the major and minor status codes are each 16 bits wide, but only 8 bits are returned from the various units. CONSTANT STATUS_trap : INTEGER := 256 -- bits 7-0 are vector number ---- Returns the index number of the given opcode. Useful for decoding by ---- functional units. FUNCTION op2index( opcode: VLBIT_1D(31 DOWNTO 0) ) RETURN INTEGER END p_constants PACKAGE BODY p_constants IS ---- Returns the index number of the given opcode. Useful for decoding by ---- functional units. FUNCTION op2index( opcode: VLBIT_1D(31 DOWNTO 0) ) RETURN INTEGER IS CHAPTER 2. VHDL SOURCE CODE 130 VARIABLE major : INTEGER VARIABLE minor : INTEGER VARIABLE index : INTEGER BEGIN major := v1d2int( opcode( 30 DOWNTO 26 ) ) -- ignore bit 31 minor := v1d2int( opcode( 15 DOWNTO 10 ) ) IF major = 23 THEN index := 32 + minor ELSE index := major END IF RETURN index END op2index END p_constants 2.19. P DISPATCH.VHD 131 2.19 p dispatch.vhd USE work.p_constants.ALL PACKAGE p_dispatch IS -- package declaration CONSTANT OPCODE_doit : INTEGER := 16#5c005c00# -- plain doit opcode --- These are EX Unit functional units. CONSTANT OP_arith : INTEGER := 0 CONSTANT OP_logic : INTEGER := 1 CONSTANT OP_ctrl : INTEGER := 2 CONSTANT OP_branch : INTEGER := 3 CONSTANT OP_load : INTEGER := 4 --- These are handled inside CONSTANT OP_doit : INTEGER CONSTANT OP_rte : INTEGER CONSTANT OP_sync : INTEGER CONSTANT OP_sync_x : INTEGER --- These are used CONSTANT OP_trap CONSTANT OP_ill CONSTANT OP_mvbr CONSTANT OP_ldbr CONSTANT OP_store CONSTANT OP_xmem the IF Unit. := 100 := 101 := 102 := 103 mostly for decoding. : INTEGER := 200 : INTEGER := 201 : INTEGER := 202 : INTEGER := 203 : INTEGER := 204 : INTEGER := 205 TYPE iw_slot IS RECORD valid : BOOLEAN tag : INTEGER address : INTEGER opcode : INTEGER wat : BOOLEAN single : BOOLEAN issued : BOOLEAN status : INTEGER dest : INTEGER arg1 : INTEGER arg2 : INTEGER END RECORD -- mem unit ----- ctrl unit branch unit mem unit mem unit ------------ slot is filled dispatch tag instruction address instruction opcode is a WAT instruction is a SINGLE instruction has been issued completion status dest reg for SB checking for fault recovery for fault recovery TYPE iw_type IS ARRAY ( 0 TO IW_Max - 1 ) OF iw_slot --- This function returns TRUE if the opcode is a SINGLE type. --FUNCTION is_single( opcode : VLBIT_1D(31 DOWNTO 0) ) RETURN BOOLEAN CHAPTER 2. VHDL SOURCE CODE 132 --- This removes the specified --PROCEDURE iw_remove ( VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE instruction from the IW. iw_index : INOUT INTEGER -- which to remove iw : INOUT iw_type -- IW iw_bottom : INOUT INTEGER -- iw_bottom wat_flag : INOUT BOOLEAN -- wat flag single_flag : INOUT BOOLEAN ) -- single flag --- determines decode information needed to --PROCEDURE decode ( VARIABLE BR_Max VARIABLE XBR_Max VARIABLE R1_Max CONSTANT iopcode VARIABLE supervisor_mode VARIABLE exceptions_ok VARIABLE r1_count VARIABLE r1_pending VARIABLE br_count VARIABLE xbr_count VARIABLE new_r1_count VARIABLE new_r1_pending VARIABLE new_br_count VARIABLE new_xbr_count VARIABLE status VARIABLE op_type VARIABLE single VARIABLE wat VARIABLE tellme VARIABLE vA VARIABLE srcA VARIABLE vB VARIABLE srcB VARIABLE vD VARIABLE srcD VARIABLE dest dispatch instructions : : : : : : : : : : : : : : : : : : : : : : : : : : IN INTEGER IN INTEGER IN INTEGER IN INTEGER IN BOOLEAN IN BOOLEAN IN INTEGER IN INTEGER IN INTEGER IN INTEGER INOUT INTEGER INOUT INTEGER INOUT INTEGER INOUT INTEGER INOUT INTEGER INOUT INTEGER INOUT BOOLEAN INOUT BOOLEAN INOUT BOOLEAN INOUT BOOLEAN INOUT INTEGER INOUT BOOLEAN INOUT INTEGER INOUT BOOLEAN INOUT INTEGER INOUT INTEGER ) --- packs variable values into RF operand request vector ----17 operand S requested --- 16-12 operand S register number --11 operand A requested --- 10-6 operand A register number --5 operand B requested --4-0 operand B register number --FUNCTION rf_encode ( CONSTANT vA : BOOLEAN CONSTANT srcA : INTEGER CONSTANT vB : BOOLEAN CONSTANT srcB : INTEGER CONSTANT vD : BOOLEAN CONSTANT srcD : INTEGER ) RETURN VLBIT_1D 2.19. P DISPATCH.VHD 133 END p_dispatch -- end of package declaration PACKAGE BODY p_dispatch IS -- package body is here --------------- Define a table to help with decoding. This table is produced from the opcodes.tex file in the write-up, by running it through a Perl script. It doesn't need to mention the .d variants, since they are never decoded. Instead, when instructions are fetched from memory, the .d is used to insert a DOIT in the IW. If the IW is changed by an exception handler, any .d instructions must be explicitly expanded into two IW slots by software. ---- Start of insertion. CONSTANT CONSTANT CONSTANT CONSTANT INDEX_doit INDEX_rte INDEX_putcr INDEX_putcr1 CONSTANT T CONSTANT F : : : : INTEGER INTEGER INTEGER INTEGER := := := := 55 80 94 95 : BOOLEAN := TRUE : BOOLEAN := FALSE TYPE decode_table_entry IS RECORD bp : BOOLEAN bc : BOOLEAN rcd : BOOLEAN rca : BOOLEAN rcb : BOOLEAN dr : BOOLEAN wat : BOOLEAN single : BOOLEAN usr : BOOLEAN tellme : BOOLEAN op_type : INTEGER END RECORD TYPE decode_table_type IS ARRAY ( 0 TO 95 CONSTANT decode_table : decode_table_type --- Fields are: BP BC RP RCd RCa RCb DR (F,F,F,T,F,T,F,F,F,F,OP_logic ), -(F,F,F,T,F,T,F,F,F,F,OP_logic ), -(F,F,F,T,F,T,F,F,F,F,OP_logic ), -(F,F,F,T,F,T,F,F,F,F,OP_logic ), -(F,F,F,T,F,T,F,F,F,F,OP_logic ), -(F,F,F,T,F,T,F,F,F,F,OP_logic ), -(F,F,F,T,F,T,F,F,F,F,OP_logic ), -(F,F,F,T,F,T,F,F,F,F,OP_logic ), -(F,F,F,T,F,T,F,F,F,T,OP_arith ), -(F,F,F,T,F,T,F,F,F,F,OP_arith ), -- ------------ branch producer branch consumer r1 consumer (dest reg) r1 consumer (src reg A) r1 consumer (src reg B) destination register wait-at-top instruction single instruction user instruction only should report DONE status type of instruction ) OF decode_table_entry := ( WAT SGL USR TELLME TYPE 0 and rd,ra,imm16 1 and.u rd,ra,imm16 2 mask rd,ra,imm16 3 mask.u rd,ra,imm16 4 or rd,ra,imm16 5 or.u rd,ra,imm16 6 xor rd,ra,imm16 7 xor.u rd,ra,imm16 8 add rd,ra,imm16 9 addu rd,ra,imm16 CHAPTER 2. VHDL SOURCE CODE 134 (F,F,F,T,F,T,F,F,F,T,OP_arith ), (F,F,F,T,F,T,F,F,F,T,OP_arith ), (F,F,F,T,F,T,F,F,F,F,OP_arith ), (F,F,F,T,F,T,F,F,F,F,OP_arith ), (F,F,F,T,F,T,F,F,F,T,OP_arith ), (F,F,F,T,F,T,F,F,F,F,OP_arith ), (T,F,F,T,F,F,F,F,F,F,OP_branch), (T,F,F,T,F,F,F,F,F,F,OP_branch), (T,F,F,T,F,F,F,F,F,F,OP_branch), (T,F,F,F,F,F,F,F,F,F,OP_branch), (F,F,F,F,F,T,F,F,F,F,OP_ctrl ), (F,F,F,F,F,F,F,F,F,F,OP_trap ), (F,F,T,T,F,T,F,F,F,T,OP_xmem ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,T,F,T,F,F,F,T,OP_load ), (F,F,F,T,F,T,F,F,F,T,OP_load ), (F,F,F,T,F,T,F,F,F,T,OP_load ), (F,F,F,T,F,T,F,F,F,T,OP_load ), (F,F,F,T,F,T,F,F,F,T,OP_load ), (F,F,T,T,F,F,F,F,F,T,OP_store ), (F,F,T,T,F,F,F,F,F,T,OP_store ), (F,F,T,T,F,F,F,F,F,T,OP_store ), (F,F,F,T,T,T,F,F,F,F,OP_logic ), (F,F,F,T,T,T,F,F,F,F,OP_logic ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,T,T,T,F,F,F,F,OP_logic ), (F,F,F,T,T,T,F,F,F,F,OP_logic ), (F,F,F,T,T,T,F,F,F,F,OP_logic ), (F,F,F,T,T,T,F,F,F,F,OP_logic ), (F,F,F,T,T,T,F,F,F,T,OP_arith ), (F,F,F,T,T,T,F,F,F,F,OP_arith ), (F,F,F,T,T,T,F,F,F,T,OP_arith ), (F,F,F,T,T,T,F,F,F,T,OP_arith ), (F,F,F,T,T,T,F,F,F,F,OP_arith ), (F,F,F,T,T,T,F,F,F,F,OP_arith ), (F,F,F,T,T,T,F,F,F,T,OP_arith ), (F,F,F,T,T,T,F,F,F,F,OP_arith ), (T,F,F,T,T,F,F,F,F,F,OP_branch), (T,F,F,T,T,F,F,F,F,F,OP_branch), (T,F,F,T,T,F,F,F,F,F,OP_branch), (T,F,F,F,T,F,F,F,F,F,OP_branch), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,T,T,T,T,F,F,T,T,OP_xmem ), (F,T,F,F,F,F,F,T,F,F,OP_doit ), (F,F,F,T,T,T,F,F,T,T,OP_load ), (F,F,F,T,T,T,F,F,F,F,OP_load ), (F,F,F,T,T,T,F,F,F,F,OP_load ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,T,T,T,F,F,F,T,T,OP_store ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), ------------------------------------------------------- 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 div rd,ra,imm16 divu rd,ra,imm16 mul rd,ra,imm16 cmp rd,ra,imm16 sub rd,ra,imm16 subu rd,ra,imm16 bb0 n,ra,imm16 bb1 n,ra,imm16 ble ra,imm16 br imm26 mvpc rd,imm16 trap imm8 xmem rs,ra,imm16 ld.bu rd,ra,imm16 ld.b rd,ra,imm16 ld.hu rd,ra,imm16 ld.h rd,ra,imm16 ld rd,ra,imm16 st.b rs,ra,imm16 st.h rs,ra,imm16 st rs,ra,imm16 and rd,ra,rb and.c rd,ra,rb or rd,ra,rb or.c rd,ra,rb xor rd,ra,rb xor.c rd,ra,rb add.io rd,ra,rb addu.io rd,ra,rb div rd,ra,rb divu rd,ra,rb mul rd,ra,rb cmp rd,ra,rb sub.io rd,ra,rb subu.io rd,ra,rb bb0 n,ra,rb bb1 n,ra,rb ble ra,rb br rb xmem.usr rs,rarb] doit ld.h.usr rd,rarb] lda rd,rarb] lda.h rd,rarb] st.h.usr rs,rarb] 2.19. P DISPATCH.VHD (F,F,F,T,T,T,F,F,F,F,OP_logic ), (F,F,F,T,T,T,F,F,F,F,OP_logic ), (F,F,F,T,T,T,F,F,F,F,OP_logic ), (F,F,F,T,T,T,F,F,F,F,OP_logic ), (F,F,F,T,T,T,F,F,F,F,OP_logic ), (F,F,F,T,T,T,F,F,F,F,OP_logic ), (F,F,F,F,T,T,F,F,F,F,OP_logic ), (F,F,F,F,T,T,F,F,F,F,OP_logic ), (F,F,F,T,F,T,F,F,F,F,OP_logic ), (F,F,F,T,F,T,F,F,F,F,OP_logic ), (F,F,F,T,F,T,F,F,F,F,OP_logic ), (F,F,F,T,F,T,F,F,F,F,OP_logic ), (F,F,F,T,F,T,F,F,F,F,OP_logic ), (F,F,F,T,F,T,F,F,F,F,OP_logic ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,F,F,F,T,T,T,F,OP_rte ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,F,F,F,T,F,F,F,OP_sync ), (F,F,F,F,F,F,T,F,T,F,OP_sync_x), (F,T,F,F,F,T,F,F,F,F,OP_mvbr ), (T,F,F,T,F,F,F,F,F,F,OP_ldbr ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,F,F,F,F,F,F,F,OP_ill ), (F,F,F,F,F,T,F,F,T,F,OP_ctrl ), (F,F,F,F,T,T,F,F,T,F,OP_ctrl ), (F,F,F,T,F,F,T,T,T,T,OP_ctrl ), (F,F,F,T,T,F,T,T,T,T,OP_ctrl )) 135 --------------------------------- 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 clr rd,ra,rb set rd,ra,rb ext rd,ra,rb extu rd,ra,rb mak rd,ra,rb rot rd,ra,rb ff0 rd,rb ff1 rd,rb clr rd,ra,w5<o5> set rd,ra,w5<o5> ext rd,ra,w5<o5> extu rd,ra,w5<o5> mak rd,ra,w5<o5> rot rd,ra,<o5> rte sync sync.x mvbr rd ldbr ra getcr getcr putcr putcr rd,cr rd,rb cr,ra rb,ra ---- End of insertion. --- This function returns TRUE if the opcode is a SINGLE type. --FUNCTION is_single( opcode : VLBIT_1D(31 DOWNTO 0) ) RETURN BOOLEAN IS VARIABLE index : INTEGER BEGIN index := op2index( opcode ) RETURN decode_table(index).single END is_single --- This removes the specified instruction from the IW. --PROCEDURE iw_remove ( VARIABLE iw_index : INOUT INTEGER -- which to remove CHAPTER 2. VHDL SOURCE CODE 136 VARIABLE VARIABLE VARIABLE VARIABLE iw : INOUT iw_type -- IW iw_bottom : INOUT INTEGER -- iw_bottom wat_flag : INOUT BOOLEAN -- wat flag single_flag : INOUT BOOLEAN ) -- single flag IS BEGIN IF iw(iw_index).wat THEN wat_flag := FALSE END IF -- clear WAT if appropriate IF iw(iw_index).single THEN single_flag := FALSE END IF -- clear SINGLE if appropriate --- remove this instruction from the IW, and shift the others up FOR i IN (iw_index + 1) TO (iw_bottom - 1) LOOP iw(i-1) := iw(i) -- copy 'em upward END LOOP iw_bottom := iw_bottom - 1 -- change last pointer iw(iw_bottom).valid := FALSE -- zap old last entry END iw_remove --- determines decode information needed to --PROCEDURE decode ( VARIABLE BR_Max VARIABLE XBR_Max VARIABLE R1_Max CONSTANT iopcode VARIABLE supervisor_mode VARIABLE exceptions_ok VARIABLE r1_count VARIABLE r1_pending VARIABLE br_count VARIABLE xbr_count VARIABLE new_r1_count VARIABLE new_r1_pending VARIABLE new_br_count VARIABLE new_xbr_count VARIABLE status VARIABLE op_type VARIABLE single VARIABLE wat VARIABLE tellme VARIABLE vA VARIABLE srcA VARIABLE vB VARIABLE srcB VARIABLE vD VARIABLE srcD dispatch instructions : : : : : : : : : : : : : : : : : : : : : : : : : IN INTEGER IN INTEGER IN INTEGER IN INTEGER IN BOOLEAN IN BOOLEAN IN INTEGER IN INTEGER IN INTEGER IN INTEGER INOUT INTEGER INOUT INTEGER INOUT INTEGER INOUT INTEGER INOUT INTEGER INOUT INTEGER INOUT BOOLEAN INOUT BOOLEAN INOUT BOOLEAN INOUT BOOLEAN INOUT INTEGER INOUT BOOLEAN INOUT INTEGER INOUT BOOLEAN INOUT INTEGER 2.19. P DISPATCH.VHD 137 VARIABLE dest IS VARIABLE index VARIABLE opcode VARIABLE tmpi BEGIN : INOUT INTEGER ) : INTEGER : VLBIT_1D( 31 DOWNTO 0 ) : INTEGER opcode := int2v1d( iopcode ) index := op2index( opcode ) --- set up default values for outputs new_r1_count := r1_count new_r1_pending := r1_pending new_br_count := br_count new_xbr_count := xbr_count status := STATUS_none op_type := decode_table(index).op_type single := decode_table(index).single wat := decode_table(index).wat tellme := decode_table(index).tellme vA := decode_table(index).rca vB := decode_table(index).rcb vD := decode_table(index).rcd srcA := v1d2int( opcode(20 DOWNTO 16) ) srcB := v1d2int( opcode(4 DOWNTO 0) ) srcD := v1d2int( opcode(25 DOWNTO 21) ) -- operand A -- operand B -- operand D IF decode_table(index).dr THEN dest := srcD ELSE dest := 0 END IF --- do the easy ones first IF decode_table(index).op_type = OP_ill THEN -- unimplemented opcode status := STATUS_illegal RETURN -- so quit END IF IF ( opcode(31) = '1' AND ( index = INDEX_doit OR index = INDEX_rte OR index = INDEX_putcr OR index = INDEX_putcr1 ) ) THEN status := STATUS_illegal RETURN END IF -- inserts extra DOIT -- but that's not allowed for -- these instructions! -- so quit CHAPTER 2. VHDL SOURCE CODE 138 --- test for user mode violations IF (NOT supervisor_mode) AND decode_table(index).usr THEN --------- Memory instructions may or may not be user mode instructions. The .usr flag is encoded with bit 9 of the opcode. It's only a user mode violation if that bit is set for a memory operation. If it's not a memory operation, then it is a user mode violation. IF ( ( decode_table(index).op_type /= OP_load AND -- not memory operation decode_table(index).op_type /= OP_store AND decode_table(index).op_type /= OP_xmem ) OR opcode(9) = '1' ) -- or is mem, and not user THEN status := STATUS_user -- users can't do this RETURN END IF END IF IF decode_table(index).op_type = OP_trap THEN tmpi := v1d2int( opcode(7 DOWNTO 0) ) -- find trap number IF (NOT supervisor_mode) AND tmpi < 128 THEN status := STATUS_user -- users only trap above 127 RETURN END IF status := STATUS_trap + tmpi RETURN -- indicate trap END IF --- check deadlock problems IF decode_table(index).bc THEN -IF ( exceptions_ok OR decode_table(index).op_type = OP_mvbr ) THEN -new_br_count := new_br_count - 1 IF new_br_count < 0 THEN -status := STATUS_lock_b0 new_br_count := br_count new_xbr_count := xbr_count RETURN END IF ELSE -new_xbr_count := new_xbr_count - 1 IF new_xbr_count < 0 THEN -status := STATUS_lock_b0 branch consumer (0 or 1) using normal Branch Queue deadlock using X Branch Queue deadlock 2.19. P DISPATCH.VHD 139 new_br_count := br_count new_xbr_count := xbr_count RETURN END IF END IF END IF IF decode_table(index).bp THEN -IF ( exceptions_ok OR decode_table(index).op_type = OP_ldbr ) THEN -new_br_count := new_br_count + 1 IF new_br_count > BR_Max THEN -status := STATUS_lock_b1 new_br_count := br_count new_xbr_count := xbr_count RETURN END IF ELSE -new_xbr_count := new_xbr_count + 1 IF new_xbr_count > XBR_Max THEN -status := STATUS_lock_b1 new_br_count := br_count new_xbr_count := xbr_count RETURN END IF END IF END IF branch producer (0 or 1) using normal Branch Queue deadlock using X Branch Queue deadlock --- Must look at three fields to determine R1 consumer counts. IF vA AND srcA new_r1_count END IF IF vB AND srcB new_r1_count END IF IF vD AND srcD new_r1_count END IF = 1 THEN := new_r1_count - 1 = 1 THEN := new_r1_count - 1 = 1 THEN := new_r1_count - 1 IF new_r1_count + r1_pending < 0 THEN status := STATUS_lock_r0 new_br_count := br_count new_xbr_count := xbr_count new_r1_count := r1_count RETURN END IF -- deadlock IF decode_table(index).dr AND dest = 1 THEN -- R1 producer tellme := TRUE -- need to know when done new_r1_pending := r1_pending + 1 CHAPTER 2. VHDL SOURCE CODE 140 --- Should I check r1_count or new_r1_count to determine deadlock? I --- think I can check new_r1_count, since nothing can actually issue --- until the pipeline has cleared, and the R1 sources get used before --- the new destinations are produced. IF new_r1_count + new_r1_pending > R1_Max THEN -- deadlock status := STATUS_lock_r1 new_br_count := br_count new_xbr_count := xbr_count new_r1_count := r1_count new_r1_pending := r1_pending RETURN END IF END IF --------------- Now, if the R1 Queue can satisfy the operand requirements NOW, without having to wait for pending operations to complete (because they might not be successful), then I want to go ahead and dispatch instead of blocking on the R1 scoreboard bit. I do this by clearing vA, vB, or vD as needed, so that the scoreboard is not checked by the dispatch routine. This doesn't affect the blocking due to the destination register, which must take place if needed. IF new_r1_count >= IF vA AND srcA = vA := FALSE END IF IF vB AND srcB = vB := FALSE END IF IF vD AND srcD = vD := FALSE END IF END IF 0 THEN 1 THEN 1 THEN 1 THEN --- By getting this far, I've decoded everything with no faults. END decode --- packs variable values into RF operand request vector ----17 operand S requested --- 16-12 operand S register number --11 operand A requested --- 10-6 operand A register number --5 operand B requested --4-0 operand B register number --FUNCTION rf_encode ( CONSTANT vA : BOOLEAN CONSTANT srcA : INTEGER CONSTANT vB : BOOLEAN 2.19. P DISPATCH.VHD 141 CONSTANT srcB CONSTANT vD CONSTANT srcD : INTEGER : BOOLEAN : INTEGER ) RETURN VLBIT_1D IS VARIABLE result : VLBIT_1D( 17 DOWNTO 0 ) VARIABLE tmpv : VLBIT_1D( 31 DOWNTO 0 ) BEGIN result( 17 ) := boo2vlb( vD ) tmpv := int2v1d( srcD ) result( 16 DOWNTO 12 ) := tmpv( 4 DOWNTO 0 ) result( 11 ) := boo2vlb( vA ) tmpv := int2v1d( srcA ) result( 10 DOWNTO 6 ) := tmpv( 4 DOWNTO 0 ) result( 5 ) := boo2vlb( vB ) tmpv := int2v1d( srcB ) result( 4 DOWNTO 0 ) := tmpv( 4 DOWNTO 0 ) RETURN result END rf_encode END p_dispatch CHAPTER 2. VHDL SOURCE CODE 142 2.20 p memory unit.vhd USE work.p_constants.ALL PACKAGE p_memory_unit IS PROCEDURE mem_decode( opcode imm opsize scaled do_sign_ext force_usr_mode do_load do_store : : : : : : : : IN VLBIT_1D (31 DOWNTO 0) INOUT BOOLEAN INOUT INTEGER INOUT BOOLEAN INOUT BOOLEAN INOUT BOOLEAN INOUT BOOLEAN INOUT BOOLEAN ) : : : : : : : : IN VLBIT_1D (31 DOWNTO 0) INOUT BOOLEAN INOUT INTEGER INOUT BOOLEAN INOUT BOOLEAN INOUT BOOLEAN INOUT BOOLEAN INOUT BOOLEAN ) END p_memory_unit PACKAGE BODY p_memory_unit IS PROCEDURE mem_decode( opcode imm opsize scaled do_sign_ext force_usr_mode do_load do_store IS TYPE retval_type IS RECORD imm : BOOLEAN opsize : INTEGER scaled : BOOLEAN do_sign_ext : BOOLEAN force_usr_mode : BOOLEAN do_load : BOOLEAN do_store : BOOLEAN END RECORD VARIABLE retval VARIABLE index BEGIN : retval_type : INTEGER index := op2index( opcode ) --------- This stuff had to be encoded by hand. I could have written a Perl script to do it, but it would have taken longer than doing it manually. This stuff shouldn't change that much (I hope). I also made some assumptions about unused bits, which is probably okay. CASE index IS 2.20. P MEMORY UNIT.VHD WHEN 22 => retval := WHEN 24 => retval := WHEN 25 => retval := WHEN 26 => retval := WHEN 27 => retval := WHEN 28 => retval := WHEN 29 => retval := WHEN 30 => retval := WHEN 31 => retval := -- xmem rs,ra,imm16 ( TRUE, 4, FALSE, FALSE, FALSE, TRUE, TRUE ) -- ld.bu rd,ra,imm16 ( TRUE, 1, FALSE, FALSE, FALSE, TRUE, FALSE ) -- ld.b rd,ra,imm16 ( TRUE, 1, FALSE, TRUE, FALSE, TRUE, FALSE ) -- ld.hu rd,ra,imm1 ( TRUE, 2, FALSE, FALSE, FALSE, TRUE, FALSE ) -- ld.h rd,ra,imm16 ( TRUE, 2, FALSE, TRUE, FALSE, TRUE, FALSE ) -- ld rd,ra,imm16 ( TRUE, 4, FALSE, FALSE, FALSE, TRUE, FALSE ) -- st.b rs,ra,imm16 ( TRUE, 1, FALSE, FALSE, FALSE, FALSE, TRUE ) -- st.h rs,ra,imm16 ( TRUE, 2, FALSE, FALSE, FALSE, FALSE, TRUE ) -- st rs,ra,imm16 ( TRUE, 4, FALSE, FALSE, FALSE, FALSE, TRUE ) WHEN 54 => -- xmem.usr] rs,ra,rb retval := ( FALSE, 4, FALSE, FALSE, FALSE, TRUE, TRUE ) retval.scaled := vlb2boo( opcode(5) ) IF opcode(9) = '1' THEN retval.force_usr_mode := TRUE END IF WHEN 56 => -- flavors of triadic load retval.imm := FALSE retval.force_usr_mode := vlb2boo( opcode(9) ) retval.scaled := vlb2boo( opcode(5) ) retval.opsize := 4 -- default size IF opcode(8) = '1' THEN -- half retval.opsize := 2 END IF IF opcode(7) = '1' THEN -- byte overrides half retval.opsize := 1 END IF retval.do_sign_ext := vlb2boo( opcode(6) ) -- doesn't matter for word retval.do_load := TRUE retval.do_store := FALSE WHEN 57 => -- lda rd,rarb] retval := ( FALSE, 4, TRUE, FALSE, FALSE, FALSE, FALSE ) WHEN 58 => -- lda.h rd,rarb] retval := ( FALSE, 2, TRUE, FALSE, FALSE, FALSE, FALSE ) WHEN 60 => -- flavors of triadic store retval.imm := FALSE retval.force_usr_mode := vlb2boo( opcode(9) ) retval.scaled := vlb2boo( opcode(5) ) retval.opsize := 4 -- default size IF opcode(8) = '1' THEN -- half retval.opsize := 2 143 CHAPTER 2. VHDL SOURCE CODE 144 END IF IF opcode(7) = '1' THEN retval.opsize := 1 END IF retval.do_sign_ext := FALSE retval.do_load := FALSE retval.do_store := TRUE -- byte overrides half WHEN OTHERS => putline("*** Illegal Opcode for Memory Unit ***") retval := ( FALSE, 0, FALSE, FALSE, FALSE, FALSE, FALSE ) END CASE imm := retval.imm opsize := retval.opsize scaled := retval.scaled do_sign_ext := retval.do_sign_ext force_usr_mode := retval.force_usr_mode do_load := retval.do_load do_store := retval.do_store END mem_decode END p_memory_unit 2.21. P OUTPUT.VHD 145 2.21 p output.vhd ---------------------------------------------------------------------------------- output utilities ------------------------------------------------------------------------------- PACKAGE p_output IS -- package declaration --- function to print 32-bit integer values in hex PROCEDURE puthex ( stuff : IN character_1d val : IN INTEGER ) --- function to print 32-bit integer values in hex followed by newline PROCEDURE puthexline ( stuff : IN character_1d val : IN INTEGER ) END p_output -- end of package declaration ------------------------------------------------------------------------------------------------------------------------------------------------------------PACKAGE BODY p_output IS -- package body is here --- local function to print one hex digit --PROCEDURE puthexdigit (VARIABLE val : IN vlbit_vector( 3 DOWNTO 0) ) IS VARIABLE dummy : INTEGER BEGIN dummy := v1d2int(val) CASE dummy IS WHEN 0 => put("0") WHEN 1 => put("1") WHEN 2 => put("2") WHEN 3 => put("3") WHEN 4 => put("4") WHEN 5 => put("5") WHEN 6 => put("6") WHEN 7 => put("7") WHEN 8 => put("8") WHEN 9 => put("9") WHEN 10 => put("A") WHEN 11 => put("B") WHEN 12 => put("C") WHEN 13 => put("D") WHEN 14 => put("E") WHEN 15 => put("F") WHEN OTHERS => put("?") END CASE END puthexdigit --- package function to print integers as hex values --- 146 CHAPTER 2. VHDL SOURCE CODE PROCEDURE puthex ( stuff : IN character_1d val : IN INTEGER ) IS VARIABLE dummy : vlbit_vector (31 DOWNTO 0) VARIABLE stupid : vlbit_vector (3 DOWNTO 0) BEGIN put(stuff) dummy := int2v1d( val ) stupid := dummy(31 DOWNTO 28) -- this is stupid, but it puthexdigit( stupid ) -- complains if I don't do it. stupid := dummy(27 DOWNTO 24) puthexdigit( stupid ) stupid := dummy(23 DOWNTO 20) puthexdigit( stupid ) stupid := dummy(19 DOWNTO 16) puthexdigit( stupid ) stupid := dummy(15 DOWNTO 12) puthexdigit( stupid ) stupid := dummy(11 DOWNTO 8) puthexdigit( stupid ) stupid := dummy(7 DOWNTO 4) puthexdigit( stupid ) stupid := dummy(3 DOWNTO 0) puthexdigit( stupid ) END puthex --- package function to print integers as hex values, followed by newline --PROCEDURE puthexline ( stuff : IN character_1d val : IN INTEGER ) IS VARIABLE dummy : vlbit_vector (31 DOWNTO 0) VARIABLE stupid : vlbit_vector (3 DOWNTO 0) BEGIN put(stuff) dummy := int2v1d( val ) stupid := dummy(31 DOWNTO 28) -- this is stupid, but it puthexdigit( stupid ) -- complains if I don't do it. stupid := dummy(27 DOWNTO 24) puthexdigit( stupid ) stupid := dummy(23 DOWNTO 20) puthexdigit( stupid ) stupid := dummy(19 DOWNTO 16) puthexdigit( stupid ) stupid := dummy(15 DOWNTO 12) puthexdigit( stupid ) stupid := dummy(11 DOWNTO 8) puthexdigit( stupid ) stupid := dummy(7 DOWNTO 4) puthexdigit( stupid ) stupid := dummy(3 DOWNTO 0) puthexdigit( stupid ) putline("") END puthexline END p_output 2.22. QFLOP.VHD 147 2.22 qop.vhd ------------- A Q-flop allows a signal to be sampled on request. It generates an acknowledge when the signal is no longer metastable. This implementation is a little sloppy, but it will work for VHDL, since VHDL doesn't have metastability problems. This cheats in some ways, since the input is passed straight through to the output. That means you don't have to probe if you don't want to. ENTITY qflop IS GENERIC( delay: TIME := 100 ps ) PORT (SIGNAL r : IN VLBIT SIGNAL a : OUT VLBIT SIGNAL i : IN VLBIT SIGNAL o : OUT VLBIT) END qflop ARCHITECTURE behavior OF qflop IS BEGIN main : PROCESS BEGIN IF bitunknown(r) THEN a <= '0' ELSIF r'EVENT THEN -- probe request IF bitunknown(i) THEN WAIT UNTIL NOT bitunknown(i) END IF o <= i a <= r AFTER delay ELSE o <= i END IF WAIT ON r,i END PROCESS main END behavior -- input change CHAPTER 2. VHDL SOURCE CODE 148 2.23 registers.vhd USE work.p_output.ALL ------------- This implements the register bank. Incoming values are updated on the outputs, and the scoreboard is cleared. I don't have to worry about arbitration, since the scoreboard will prevent any outstanding registers from being read. ENTITY registers IS GENERIC( delay: TIME := 100 ps ) PORT( SIGNAL clr : IN SIGNAL clr_sb : OUT SIGNAL clr_sb_ack : IN SIGNAL clr_sb_req : OUT SIGNAL r02 : OUT SIGNAL r03 : OUT SIGNAL r04 : OUT SIGNAL r05 : OUT SIGNAL r06 : OUT SIGNAL r07 : OUT SIGNAL r08 : OUT SIGNAL r09 : OUT SIGNAL r10 : OUT SIGNAL r11 : OUT SIGNAL r12 : OUT SIGNAL r13 : OUT SIGNAL r14 : OUT SIGNAL r15 : OUT SIGNAL r16 : OUT SIGNAL r17 : OUT SIGNAL r18 : OUT SIGNAL r19 : OUT SIGNAL r20 : OUT SIGNAL r21 : OUT SIGNAL r22 : OUT SIGNAL r23 : OUT SIGNAL r24 : OUT SIGNAL r25 : OUT SIGNAL r26 : OUT SIGNAL r27 : OUT SIGNAL r28 : OUT SIGNAL r29 : OUT SIGNAL r30 : OUT SIGNAL r31 : OUT SIGNAL rt0_a : OUT SIGNAL rt0_r : IN SIGNAL rt0_v : IN SIGNAL rt1_a : OUT SIGNAL rt1_r : IN SIGNAL rt1_v : IN SIGNAL rt2_a : OUT SIGNAL rt2_r : IN VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT VLBIT (4 DOWNTO 0) (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) (36 DOWNTO 0) (36 DOWNTO 0) 2.23. REGISTERS.VHD SIGNAL SIGNAL SIGNAL SIGNAL END registers 149 rt2_v rt3_a rt3_r rt3_v : : : : IN OUT IN IN VLBIT_1D (36 DOWNTO 0) VLBIT VLBIT VLBIT_1D (36 DOWNTO 0)) ARCHITECTURE behavior OF registers IS BEGIN main : PROCESS --- type definitions TYPE register_type IS ARRAY ( 0 TO 31 ) OF VLBIT_1D (31 DOWNTO 0) --- internal variables VARIABLE reg : register_type -- registers VARIABLE debug VARIABLE trace : BOOLEAN := FALSE : BOOLEAN := FALSE --- Input signal event variables. These are the events which wake up this --- process, for various reasons. VARIABLE VARIABLE VARIABLE VARIABLE l_rt0_r l_rt1_r l_rt2_r l_rt3_r : : : : VLBIT VLBIT VLBIT VLBIT --- output signal value variables VARIABLE v_clr_sb_req : VLBIT --- scratch variables VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE which_result dest stuff tmpv tmpi : : : : : INTEGER INTEGER VLBIT_1D (36 DOWNTO 0) VLBIT_1D (31 DOWNTO 0) INTEGER BEGIN ----- If clear is asserted, reset everything and stick here. --IF clr /= '1' THEN FOR i IN 0 TO 31 LOOP reg(i) := int2v1d( 0 ) -- reset to beginning -- clear registers CHAPTER 2. VHDL SOURCE CODE 150 END LOOP which_result := 0 l_rt0_r := '0' l_rt1_r := '0' l_rt2_r := '0' l_rt3_r := '0' v_clr_sb_req := '0' clr_sb_req <= v_clr_sb_req clr_sb <= ('0','0','0','0','0') rt0_a <= '0' rt1_a <= '0' rt2_a <= '0' rt3_a <= '0' r02 r03 r04 r05 r06 r07 r08 r09 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 r30 r31 <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= reg(2) reg(3) reg(4) reg(5) reg(6) reg(7) reg(8) reg(9) reg(10) reg(11) reg(12) reg(13) reg(14) reg(15) reg(16) reg(17) reg(18) reg(19) reg(20) reg(21) reg(22) reg(23) reg(24) reg(25) reg(26) reg(27) reg(28) reg(29) reg(30) reg(31) WAIT UNTIL clr = '1' ELSE ---- Normal running condition -- wait till ready to run -- unit is running 2.23. REGISTERS.VHD ----------- 151 The process loses events if I'm busy elsewhere, so I need to make my own virtual wait statement, instead of relying on the actual wait from VHDL. I'll just sample by hand, and only wait if there are no pending requests. Since the REQ/ACK is paired, this will work fine. WHILE ( rt0_r rt1_r rt2_r rt3_r LOOP /= /= /= /= l_rt0_r l_rt1_r l_rt2_r l_rt3_r OR OR OR ) --- All result queues have this format: ----- 36-32 destination register --- 31-0 value --IF rt0_r /= l_rt0_r THEN l_rt0_r := rt0_r stuff := rt0_v which_result := 0 ELSIF rt1_r /= l_rt1_r THEN l_rt1_r := rt1_r stuff := rt1_v which_result := 1 ELSIF rt2_r /= l_rt2_r THEN l_rt2_r := rt2_r stuff := rt2_v which_result := 2 ELSIF rt3_r /= l_rt3_r THEN l_rt3_r := rt3_r stuff := rt3_v which_result := 3 ELSE putline("*** What Happened? ***") END IF dest := v1d2int( stuff(36 DOWNTO 32) ) -- see where it goes IF dest /= 0 AND dest /= 1 THEN tmpv := stuff(31 DOWNTO 0) reg(dest) := tmpv IF debug OR trace THEN tmpi := v1d2int(tmpv) put("R",dest) puthexline(" <= ",tmpi) END IF -- ignore writes to r0 and r1 -- write the new value CHAPTER 2. VHDL SOURCE CODE 152 CASE dest IS WHEN 2 => r02 <= tmpv WHEN 3 => r03 <= tmpv WHEN 4 => r04 <= tmpv WHEN 5 => r05 <= tmpv WHEN 6 => r06 <= tmpv WHEN 7 => r07 <= tmpv WHEN 8 => r08 <= tmpv WHEN 9 => r09 <= tmpv WHEN 10 => r10 <= tmpv WHEN 11 => r11 <= tmpv WHEN 12 => r12 <= tmpv WHEN 13 => r13 <= tmpv WHEN 14 => r14 <= tmpv WHEN 15 => r15 <= tmpv WHEN 16 => r16 <= tmpv WHEN 17 => r17 <= tmpv WHEN 18 => r18 <= tmpv WHEN 19 => r19 <= tmpv WHEN 20 => r20 <= tmpv WHEN 21 => r21 <= tmpv WHEN 22 => r22 <= tmpv WHEN 23 => r23 <= tmpv WHEN 24 => r24 <= tmpv WHEN 25 => r25 <= tmpv WHEN 26 => r26 <= tmpv WHEN 27 => r27 <= tmpv WHEN 28 => 2.23. REGISTERS.VHD 153 r28 <= tmpv WHEN 29 => r29 <= tmpv WHEN 30 => r30 <= tmpv WHEN 31 => r31 <= tmpv WHEN OTHERS => NULL END CASE --- clear the scoreboard IF debug THEN tmpi := v1d2int(stuff(36 DOWNTO 32)) putline("clearing scoreboard bit ",tmpi) END IF clr_sb <= stuff(36 DOWNTO 32) v_clr_sb_req := NOT v_clr_sb_req clr_sb_req <= v_clr_sb_req AFTER delay WAIT ON clr_sb_ack END IF IF which_result = 0 THEN rt0_a <= rt0_r AFTER delay ELSIF which_result = 1 THEN rt1_a <= rt1_r AFTER delay ELSIF which_result = 2 THEN rt2_a <= rt2_r AFTER delay ELSIF which_result = 3 THEN rt3_a <= rt3_r AFTER delay ELSE putline("*** What Happened? ***") END IF END LOOP END IF WAIT ON clr, rt0_r, rt1_r, rt2_r, rt3_r END PROCESS main END behavior -- main process loop -- CLR not asserted CHAPTER 2. VHDL SOURCE CODE 154 2.24 regselect.vhd USE work.p_constants.ALL USE work.p_output.ALL ---- This module puts together the operands for the EX Unit in response to the ---- requests from the IF Unit. If R1 operands are requested, I need to gather ---- them in the correct order. ENTITY regselect IS GENERIC( delay: TIME := 100 ps ) PORT( SIGNAL clr : IN SIGNAL op : OUT SIGNAL op_ack : IN SIGNAL op_req : OUT SIGNAL r1_q_ack : OUT SIGNAL r1_q : IN SIGNAL r1_q_req : IN SIGNAL rf : IN SIGNAL rf_ack : OUT SIGNAL rf_req : IN SIGNAL r02 : IN SIGNAL r03 : IN SIGNAL r04 : IN SIGNAL r05 : IN SIGNAL r06 : IN SIGNAL r07 : IN SIGNAL r08 : IN SIGNAL r09 : IN SIGNAL r10 : IN SIGNAL r11 : IN SIGNAL r12 : IN SIGNAL r13 : IN SIGNAL r14 : IN SIGNAL r15 : IN SIGNAL r16 : IN SIGNAL r17 : IN SIGNAL r18 : IN SIGNAL r19 : IN SIGNAL r20 : IN SIGNAL r21 : IN SIGNAL r22 : IN SIGNAL r23 : IN SIGNAL r24 : IN SIGNAL r25 : IN SIGNAL r26 : IN SIGNAL r27 : IN SIGNAL r28 : IN SIGNAL r29 : IN SIGNAL r30 : IN SIGNAL r31 : IN END regselect VLBIT VLBIT_1D VLBIT VLBIT VLBIT VLBIT_1D VLBIT VLBIT_1D VLBIT VLBIT VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D (95 DOWNTO 0) (31 DOWNTO 0) (17 DOWNTO 0) (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 (31 DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) ) 2.24. REGSELECT.VHD 155 ARCHITECTURE behavior OF regselect IS BEGIN main : PROCESS --- output signal value variables VARIABLE v_op_req VARIABLE v_r1_q_ack : VLBIT : VLBIT --- scratch variables VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE sel tmpi tmpv op_a op_b op_s : : : : : : INTEGER INTEGER VLBIT_1D VLBIT_1D VLBIT_1D VLBIT_1D (31 (31 (31 (31 DOWNTO DOWNTO DOWNTO DOWNTO 0) 0) 0) 0) --- internal variables VARIABLE debug : BOOLEAN := FALSE BEGIN ----- If clear is asserted, reset everything and stick here. --IF clr /= '1' THEN -- reset to beginning v_op_req := '0' v_r1_q_ack := '0' rf_ack <= '0' op_req <= v_op_req r1_q_ack <= v_r1_q_ack op_s := ZERO(31 DOWNTO 0) op_a := ZERO(31 DOWNTO 0) op_b := ZERO(31 DOWNTO 0) op <= ( op_s & op_a & op_b ) WAIT UNTIL clr = '1' ELSE -- wait till ready to run -- unit is running ---- Normal running condition --- RF operand request queue has this format: ----17 operand S requested --- 16-12 operand S register number CHAPTER 2. VHDL SOURCE CODE 156 ----------- 11 10-6 5 4-0 operand operand operand operand A A B B requested register number requested register number --- Operand A. IF rf(11) = '1' THEN sel := v1d2int( rf(10 DOWNTO 6) ) CASE sel IS WHEN 1 => IF r1_q_req = v_r1_q_ack THEN WAIT UNTIL r1_q_req /= v_r1_q_ack END IF op_a := r1_q v_r1_q_ack := r1_q_req r1_q_ack <= v_r1_q_ack AFTER delay WHEN 2 => op_a := r02 WHEN 3 => op_a := r03 WHEN 4 => op_a := r04 WHEN 5 => op_a := r05 WHEN 6 => op_a := r06 WHEN 7 => op_a := r07 WHEN 8 => op_a := r08 WHEN 9 => op_a := r09 WHEN 10 => op_a := r10 WHEN 11 => op_a := r11 WHEN 12 => op_a := r12 WHEN 13 => op_a := r13 WHEN 14 => op_a := r14 WHEN 15 => op_a := r15 WHEN 16 => op_a := r16 WHEN 17 => op_a := r17 WHEN 18 => op_a := r18 -- wait for it to be available -- get it -- ack it 2.24. REGSELECT.VHD 157 WHEN 19 => op_a := r19 WHEN 20 => op_a := r20 WHEN 21 => op_a := r21 WHEN 22 => op_a := r22 WHEN 23 => op_a := r23 WHEN 24 => op_a := r24 WHEN 25 => op_a := r25 WHEN 26 => op_a := r26 WHEN 27 => op_a := r27 WHEN 28 => op_a := r28 WHEN 29 => op_a := r29 WHEN 30 => op_a := r30 WHEN 31 => op_a := r31 WHEN OTHERS => op_a := ZERO(31 DOWNTO 0) END CASE IF debug THEN put("op_a <= r",sel) tmpi := v1d2int(op_a) puthexline(" = ",tmpi) END IF END IF --- Operand B. IF rf(5) = '1' THEN sel := v1d2int( rf(4 DOWNTO 0) ) CASE sel IS WHEN 1 => IF r1_q_req = v_r1_q_ack THEN WAIT UNTIL r1_q_req /= v_r1_q_ack END IF op_b := r1_q v_r1_q_ack := r1_q_req r1_q_ack <= v_r1_q_ack AFTER delay WHEN 2 => -- wait for it to be available -- get it -- ack it CHAPTER 2. VHDL SOURCE CODE 158 op_b := r02 WHEN 3 => op_b := r03 WHEN 4 => op_b := r04 WHEN 5 => op_b := r05 WHEN 6 => op_b := r06 WHEN 7 => op_b := r07 WHEN 8 => op_b := r08 WHEN 9 => op_b := r09 WHEN 10 => op_b := r10 WHEN 11 => op_b := r11 WHEN 12 => op_b := r12 WHEN 13 => op_b := r13 WHEN 14 => op_b := r14 WHEN 15 => op_b := r15 WHEN 16 => op_b := r16 WHEN 17 => op_b := r17 WHEN 18 => op_b := r18 WHEN 19 => op_b := r19 WHEN 20 => op_b := r20 WHEN 21 => op_b := r21 WHEN 22 => op_b := r22 WHEN 23 => op_b := r23 WHEN 24 => op_b := r24 WHEN 25 => op_b := r25 WHEN 26 => op_b := r26 WHEN 27 => op_b := r27 WHEN 28 => op_b := r28 WHEN 29 => 2.24. REGSELECT.VHD 159 op_b := r29 WHEN 30 => op_b := r30 WHEN 31 => op_b := r31 WHEN OTHERS => op_b := ZERO(31 DOWNTO 0) END CASE IF debug THEN put("op_b <= r",sel) tmpi := v1d2int(op_b) puthexline(" = ",tmpi) END IF END IF --- Operand S. IF rf(17) = '1' THEN sel := v1d2int( rf(16 DOWNTO 12) ) CASE sel IS WHEN 1 => IF r1_q_req = v_r1_q_ack THEN WAIT UNTIL r1_q_req /= v_r1_q_ack END IF op_s := r1_q v_r1_q_ack := r1_q_req r1_q_ack <= v_r1_q_ack AFTER delay WHEN 2 => op_s := r02 WHEN 3 => op_s := r03 WHEN 4 => op_s := r04 WHEN 5 => op_s := r05 WHEN 6 => op_s := r06 WHEN 7 => op_s := r07 WHEN 8 => op_s := r08 WHEN 9 => op_s := r09 WHEN 10 => op_s := r10 WHEN 11 => op_s := r11 WHEN 12 => op_s := r12 WHEN 13 => -- wait for it to be available -- get it -- ack it CHAPTER 2. VHDL SOURCE CODE 160 op_s := r13 WHEN 14 => op_s := r14 WHEN 15 => op_s := r15 WHEN 16 => op_s := r16 WHEN 17 => op_s := r17 WHEN 18 => op_s := r18 WHEN 19 => op_s := r19 WHEN 20 => op_s := r20 WHEN 21 => op_s := r21 WHEN 22 => op_s := r22 WHEN 23 => op_s := r23 WHEN 24 => op_s := r24 WHEN 25 => op_s := r25 WHEN 26 => op_s := r26 WHEN 27 => op_s := r27 WHEN 28 => op_s := r28 WHEN 29 => op_s := r29 WHEN 30 => op_s := r30 WHEN 31 => op_s := r31 WHEN OTHERS => op_s := ZERO(31 DOWNTO 0) END CASE IF debug THEN put("op_s <= r",sel) tmpi := v1d2int(op_s) puthexline(" = ",tmpi) END IF END IF op <= ( op_s & op_a & op_b ) v_op_req := NOT v_op_req op_req <= v_op_req AFTER delay -- send operands out 2.24. REGSELECT.VHD 161 WAIT ON op_ack -- wait for ACK rf_ack <= rf_req AFTER delay -- done with this event END IF WAIT ON clr, rf_req END PROCESS main END behavior -- CLR not asserted CHAPTER 2. VHDL SOURCE CODE 162 2.25 scoreboard.vhd ------------------------------------- The scoreboard is a shared resource, so it is necessary for read and write access to be mutually exclusive. This module contains the scoreboard values, and enforces the exclusion. Read operations are three-phase: a transition on RD_R requests a lock on the register, and is granted by a transition on RD_G, indicating that the OUT data is valid. The lock is released by a transition on RD_D. While the read lock is granted, the BITS output is stable and valid. Write operations are two-phase. The bit number of placed on the NUM input bus, the value is placed on the SET port, and a transition is sent to WR_R. A transition on WR_A indicates that the write is completed. ENTITY scoreboard IS GENERIC(delay: TIME := 100 ps ) PORT( SIGNAL clr : IN VLBIT SIGNAL rd_r : IN VLBIT SIGNAL rd_g : OUT VLBIT SIGNAL rd_d : IN VLBIT SIGNAL wr_r : IN VLBIT SIGNAL wr_a : OUT VLBIT SIGNAL set : IN VLBIT SIGNAL num : IN VLBIT_1D (4 DOWNTO 0) SIGNAL bits : OUT VLBIT_1D (31 DOWNTO 0)) END scoreboard ARCHITECTURE state_behavior OF scoreboard IS TYPE states IS (wait_any,wait_done,wait_done_write) BEGIN main : PROCESS ( rd_r, wr_r, rd_d, clr ) VARIABLE state : states := wait_any VARIABLE v_bits : VLBIT_1D (31 DOWNTO 0) VARIABLE tmpi : INTEGER VARIABLE s_reads : INTEGER VARIABLE s_sets : INTEGER VARIABLE s_clears : INTEGER VARIABLE s_conflicts : INTEGER BEGIN IF ( clr /= '1' ) THEN state := wait_any v_bits := ( '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0', '0','0','0','0','0','0','0','0' ) bits <= v_bits rd_g <= '0' wr_a <= '0' 2.25. SCOREBOARD.VHD 163 s_reads := 0 s_sets := 0 s_clears := 0 s_conflicts := 0 ELSE CASE state IS WHEN wait_any => IF (rd_r'EVENT AND wr_r'EVENT) THEN rd_g <= rd_r AFTER delay state := wait_done_write s_reads := s_reads + 1 s_conflicts := s_conflicts + 1 ELSIF (rd_r'EVENT) THEN rd_g <= rd_r AFTER delay state := wait_done s_reads := s_reads + 1 ELSIF (wr_r'EVENT) THEN tmpi := v1d2int(num) v_bits(tmpi) := set bits <= v_bits wr_a <= wr_r AFTER delay IF ( set = '1' ) THEN s_sets := s_sets + 1 ELSE s_clears := s_clears + 1 END IF END IF WHEN wait_done => IF (rd_d'EVENT AND wr_r'EVENT) THEN tmpi := v1d2int(num) v_bits(tmpi) := set bits <= v_bits wr_a <= wr_r AFTER delay state := wait_any IF ( set = '1' ) THEN s_sets := s_sets + 1 ELSE s_clears := s_clears + 1 END IF ELSIF (rd_d'EVENT) THEN state := wait_any ELSIF (wr_r'EVENT) THEN state := wait_done_write s_conflicts := s_conflicts + 1 END IF WHEN wait_done_write => IF (rd_d'EVENT) THEN tmpi := v1d2int(num) v_bits(tmpi) := set ----- waiting for any request got both, do read first grant read permission and wait for it to finish -- else got rd_r only -- send grant signal -- wait for release ------ or got wr_r only see which bit to write change it and update output and return ack -------- waiting for rd_d got both, done with read see which bit to write change it and update output and return ack wait for more stuff ----- else wait else wait ----- wait for rd_d, then write got rd_d, done with read see which bit to write change it got for got for rd_d only more stuff wr_r only release CHAPTER 2. VHDL SOURCE CODE 164 bits <= v_bits wr_a <= wr_r AFTER delay state := wait_any IF ( set = '1' ) THEN s_sets := s_sets + 1 ELSE s_clears := s_clears + 1 END IF END IF END CASE END IF END PROCESS main END state_behavior -- and update output -- and return ack -- wait for more stuff -- state 2.26. VDELAY.VHD 2.26 vdelay.vhd ENTITY vdelay IS GENERIC( delay: TIME := 100 PS ) PORT (SIGNAL i :IN VLBIT SIGNAL o :OUT VLBIT := '0') END vdelay ARCHITECTURE behavior OF vdelay IS BEGIN main : PROCESS ( i ) BEGIN o <= i AFTER delay END PROCESS main END behavior 165 CHAPTER 2. VHDL SOURCE CODE 166 2.27 verify address.vhd --- This verifies memory addresses. All it does it check to see if the --- byte-address is greater than the limit, and if so it sets bit 0 in --- the status output. ----- In an actual memory system, this could signal cache misses, write --- protection, segment violation, and lots of other things. For my --- purposes I just need some kind of memory fault to test. ----- Actually, there is some special behavior. This unit intercepts memory --- requests, so that it can implement some special I/O functions. Any memory --- access with address bit 31 set is used for some special I/O behavior. This --- behavior is not part of the Fred architecture. I just added it so that I'd --- have a simple way to generate circuit events from within an assembly --- language program. I can use this to read and write from files, or to --- wiggle a debugging pin. --ENTITY verify_address IS GENERIC( delay: TIME := 100 PS maxaddr: INTEGER := 65535 ) PORT (SIGNAL clr :IN VLBIT SIGNAL reqi :IN VLBIT SIGNAL addr :IN VLBIT_VECTOR (31 downto 2) SIGNAL acki :IN VLBIT SIGNAL reqo :OUT VLBIT SIGNAL acko :OUT VLBIT := '0' SIGNAL s :OUT VLBIT_VECTOR (3 downto 0) := ('0','0','0','0') SIGNAL wdata :IN VLBIT_1D(31 DOWNTO 0) -- write input data SIGNAL read :IN VLBIT -- read/write direction SIGNAL mdata :IN VLBIT_1D(31 DOWNTO 0) -- memory read data in SIGNAL xdata :OUT VLBIT_1D(31 DOWNTO 0) -- memory read data out SIGNAL x_debug :OUT VLBIT -- for debugging only SIGNAL y_debug :OUT VLBIT) -- for debugging only END verify_address ARCHITECTURE behavior OF verify_address IS BEGIN main : PROCESS VARIABLE num : INTEGER := 0 VARIABLE tmpi : INTEGER VARIABLE v_reqo : VLBIT VARIABLE v_x_debug : VLBIT VARIABLE v_y_debug : VLBIT VARIABLE bo : BOOLEAN VARIABLE rt : TIME FILE stdin : TEXT IS IN "Stdin.dat" FILE stdout : TEXT IS OUT "Stdout.dat" FILE rtdelay : TEXT IS IN "Random.dat" VARIABLE trace_out : BOOLEAN := FALSE -- display output VARIABLE trace_in : BOOLEAN := FALSE -- display output BEGIN IF clr /= '1' THEN -- clear is asserted 2.27. VERIFY ADDRESS.VHD 167 num := 0 acko <= '0' v_reqo := '0' reqo <= v_reqo s <= ('0','0','0','0') v_x_debug := '0' x_debug <= v_x_debug v_y_debug := '0' y_debug <= v_y_debug -- reset outputs WAIT ON reqi, acki, clr -- wait for inputs ELSE -- running normally WAIT ON reqi -- wait for REQI event num := v1d2int( addr ) * 4 -- get byte-address value IF addr(31) = '1' THEN -- special syscall behavior num := v1d2int( addr(31 DOWNTO 28) ) -- get syscall number CASE num IS WHEN 8 => v_x_debug := NOT v_x_debug x_debug <= v_x_debug WHEN 9 => --------- -- 0x80000000 is times() -- just wiggle a pin -- 0x90000000 is interrupts Anything to this address will generate an external interrupt after an amount of time determined by reading the delay from an external file. There should be enough random numbers in the file to account for the needs of any simulation run. freadline( rtdelay, tmpi, bo ) -- try to read it ASSERT bo REPORT "Couldn't read random.dat" SEVERITY FAILURE rt := 1 NS * tmpi -- determine the time putline("generating interrupt in ",rt) v_y_debug := NOT v_y_debug y_debug <= v_y_debug AFTER rt WHEN 12 => -- 0xC0000000 is file I/O --- The data that is read or written appears in the file as decimal --- integers, one per line. The value read is a signed 32-bit CHAPTER 2. VHDL SOURCE CODE 168 --- quantity. I ignore the byte strobes and read or write the --- entire 32-bit value. I essentially treat the file access as --- the implementation of the getc() and putc() functions. IF read = '1' THEN -- read a byte from the file freadline( stdin, tmpi, bo ) -- try to read it IF bo THEN xdata <= int2v1d( tmpi ) ELSE xdata <= int2v1d( -1 ) END IF -- it worked -- so return the byte value -- return EOF on failure IF (trace_in) THEN putline("STDIN = ",tmpi) END IF ELSE -- write a byte to the file tmpi := v1d2int( wdata(7 DOWNTO 0) ) -- this value fwriteline( stdout, tmpi, bo ) -- write it and make sure ASSERT bo REPORT "Couldn't write stdout" SEVERITY FAILURE IF (trace_out) THEN putline("STDOUT = ",tmpi) END IF END IF WHEN OTHERS => putline("Unimplemented system call ",num) END CASE s <= ('0','0','0','0') -- memory status is okay acko <= reqi AFTER delay -- send ACKO ELSIF ( num > maxaddr ) THEN -- invalid address s <= ('0','0','0','1') acko <= reqi AFTER delay ELSE -- report memory status -- valid address --- Pass request on to memory immediately. The zero delay is not --- realistic, but there's already enough delay in the memory system 2.27. VERIFY ADDRESS.VHD 169 --- so that this doesn't make any difference. v_reqo := NOT v_reqo reqo <= v_reqo s <= ('0','0','0','0') -- memory status is okay WAIT ON acki -- wait for ACKI xdata <= mdata -- pass data through, too --- This would be the perfect place to put in some unexpected random --- delay to model a cache miss. acko <= reqi END IF END IF END PROCESS main END behavior -- send ACKO CHAPTER 2. VHDL SOURCE CODE 170 2.28 zdelay.vhd ------- This is a simple delay module. The delay time can be changed at ---- simulation run-time. The default delay is zero. ---ENTITY zdelay IS PORT (SIGNAL i :IN SIGNAL o :OUT END zdelay VLBIT VLBIT := '0') ARCHITECTURE behavior OF zdelay IS BEGIN main : PROCESS ( i ) VARIABLE delay : TIME := 0 NS BEGIN o <= i AFTER delay END PROCESS main END behavior 2.29. ZXOR.VHD 171 2.29 zxor.vhd ------- This is an XOR with no delay. ---- wire-or. ---ENTITY zxor IS PORT (SIGNAL a :IN SIGNAL b :IN SIGNAL y :OUT END zxor It is the self-timed equivalent of a VLBIT VLBIT VLBIT := '0') ARCHITECTURE behavior OF zxor IS BEGIN main : PROCESS ( a, b ) VARIABLE delay : TIME := 0 NS BEGIN y <= a XOR b AFTER delay END PROCESS main END behavior 172 CHAPTER 2. VHDL SOURCE CODE Chapter 3 Schematic Diagrams 173 174 A1 R1 CLR CLR G1 R1 D1 A1 G0 R2 D0 A2 Figure 3.1: arbcall R1 Arb ARBITER RS RS AS AS Call R0 W W R0 A0 Processor William F. Design Richardson Arbitrated Call Element CHAPTER 3. SCHEMATIC DIAGRAMS Fred A1 R1 CLR CLR G1 R1 D1 A1 G0 R2 D0 A2 AS RS AS Y[79:64] R0 A[15:0] W W X[79:64] R0 A0 OUT[15:0] O Vdelay Call B[15:0] I RS ARBITER Z[79:64] SEL Arb MUX-2x16 R1 Figure 3.2: arbcallx88 X[87:0] S Y[87:0] Y[87:80] B[7:0] Y[7:0] Z[87:80] Z[87:0] MUX2x8 X[87:80] A[7:0] Y[63:32] B[31:0] S Y[31:0] Z[63:32] MUX2x32 X[63:32] A[31:0] S Y[31:0] B[31:0] Y[31:0] Z[31:0] MUX2x32 X[31:0] Fred Processor William F. Design Richardson A[31:0] Arbitrated Call with 88-bit Data 175 176 I31 A I30 A I29 A Y O31 Y O30 Y O29 Y O28 Y O27 Y O26 Y O25 Y O24 Y O23 Y O22 Y O21 Y O20 Y O19 Y O18 Y O17 Y O16 Y O15 Y O14 Y O13 Y O12 Y O11 Y O10 Y O9 Y O8 Y O7 Y O6 Y O5 Y O4 Y O3 Y O2 Y O1 Y O0 BUF BUF BUF I28 A I27 A I26 A I25 A I24 A BUF BUF BUF BUF I[31:0] O[31:0] BUF I23 A I22 A I21 A I20 A I19 A BUF BUF BUF BUF BUF Figure 3.3: buf32 I18 A I17 A I16 A I15 A I14 A BUF BUF BUF BUF BUF A I12 A I11 A I10 A I9 A BUF BUF BUF BUF BUF I8 A I7 A I6 A I5 A I4 A BUF BUF BUF BUF BUF Fred Processor William F. Design Richardson I3 A I2 A I1 A I0 A 32-bit BUF BUF BUF BUF buffer [for aliasing] CHAPTER 3. SCHEMATIC DIAGRAMS I13 I[3:0] Figure 3.4: buf4 I3 A I2 A I1 A I0 A Y O3 Y O2 Y O1 Y O0 BUF BUF BUF O[3:0] Fred Processor William F. Design Richardson 4-bit buffer BUF [for aliasing] 177 178 I7 A I6 A I5 A I4 A I3 A I2 A I1 A I0 A Y O7 Y O6 Y O5 Y O4 Y O3 Y O2 Y O1 Y O0 BUF BUF BUF BUF I[7:0] BUF Figure 3.5: buf8 BUF BUF O[7:0] Processor William F. Design Richardson 8-bit buffer [for aliasing] CHAPTER 3. SCHEMATIC DIAGRAMS Fred BUF R1 R1 A1 A1 RS Call I O Vdelay R2 A0 A2 RS AS AS R0 A B Figure 3.6: callx32 XOR Y S Y[31:0] B[31:0] Y[31:0] Z[31:0] MUX2x32 X[31:0] Fred Processor William F. Design Richardson A[31:0] Non-Arbitrated Call with 32-bit Data 179 180 RI RO A B CLR Delay1 OUT IN OUT Delay1 IN OUT MC C Figure 3.7: cp-delay AO AI This Fred Processor William F. Design Richardson is does used not to model actually Capture-Pass the delay of latch any data latch a Capture/Pass on delay its latch. own. circuit. CHAPTER 3. SCHEMATIC DIAGRAMS It RX14 RX13 CLR CLR A RX15 RI RO AX15 AI AO RX12 B Z CLR A Y RI RO AI AO B AX14 Z A Y RI RO AI AO B AX13 Z Y AX12 CLR TAP CLR Delay Tap RX11 RIN RIN RX[15:0] RX[15:0] AIN AIN AX[15:0] AX[15:1],AOUT RX10 CLR CLR A Figure 3.8: delaychain RI RO AI AO B Z Y RI RO AI AO B RX7 AI AO B Z RI RO AI AO B Z Processor William F. Design Richardson Delay Chain for RI RO AI AO A Y RI RO AI AO B Z RI RO AI AO B Z A Y RI RO AI AO AX5 AX2 RI RO AI AO Z Y RX0 CLR A Y B AX4 CLR Z Y RX4 RX1 B Z CLR A Y B AX8 RX5 A Y Z AX9 CLR AX3 Fred AO RX2 A AO AI B AX6 CLR AI RO CLR A Y RX3 RO RI RX6 AX7 RI Y CLR A RO Z CLR A AX10 CLR RX8 CLR A AX11 RI RX9 B Z A Y RI RO AI AO B Z Y ROUT AOUT AX1 FIFO 181 182 REQ S0 S4 SEL SEL A OUTF B SELECT XOR Y Y A XOR OUTF B SELECT IN IN OUTT OUTT CLR CLR R0 A0 A CLR B A C OUT OUT C A4 R4 CLR B S1 S5 SEL SEL B XOR Y Y A XOR OUTF B SELECT IN IN OUTT OUTT CLR CLR R1 A1 A5 R5 CLR CLR A B A C OUT OUT C B S2 S6 SEL SEL XOR Y A B B A OUTF Y A XOR OUTF B SELECT C SELECT IN IN OUT OUTT CLR R2 A2 OUTT CLR A CLR B A C OUT OUT C A6 R6 CLR B S3 S7 SEL OUTF A SELECT B XOR Y Y XOR A SEL OUTF B SELECT ACK IN IN OUTT OUTT CLR CLR R3 A3 A7 CLR Fred Processor William F. Design Richardson Distributor R7 CLR Circuit CHAPTER 3. SCHEMATIC DIAGRAMS Figure 3.9: distributor A OUTF SELECT EX[127:0] OP[95:0] FU_A CLR CLR FU_arith D_REQ DT0_R D_ACK DT0_A RIN AIN DONE[87:0] EX[90:87] EX86 Operand DT0_T[87:0] EXTRA[3:0] TELLME EX[76:69] TAG[7:0] EX[68:64] DEST[4:0] Select ROUT RT0_R AOUT RT0_A RES[36:0] EX[31:0] RT0_V[36:0] OPCODE[31:0] EX85 XOP[63:32] RQ_REQ RQ0_R RQ_ACK RQ0_A OP_A[31:0] OP[31:0] OP_B[31:0] RQ[31:0] RQ0_V[31:0] CLR SEL OUTF R1 FU_L CLR SELECT EX_REQ CLR CLR A1 IN RS REQ R0 AS ACK A0 FU_logic Call OUTT A CLR C B OUT R2 Figure 3.10: ex-unit1 CLR OP_REQ Functional OP_ACK EX_ACK EX77 EX78 EX79 S0 S1 S2 Unit EX80 S3 EX81 S4 EX82 S5 EX83 S6 EX84 S7 Distributor A2 R1 RIN A1 AIN D_REQ DT1_R D_ACK DT1_A DONE[87:0] R2 EX[90:87] A2 EX86 TELLME R3 MEM_UNIT_REQ EX[76:69] TAG[7:0] A3 MEM_UNIT_ACK EX[68:64] DEST[4:0] R4 BR_UNIT_REQ EX[31:0] A4 BR_UNIT_ACK XOP[63:32] OP_A[31:0] OP[31:0] OP_B[31:0] ROUT RT1_R AOUT RT1_A RES[36:0] R5 DT1_T[87:0] EXTRA[3:0] RT1_V[36:0] OPCODE[31:0] RQ_REQ RQ1_R RQ_ACK RQ1_A RQ[31:0] RQ1_V[31:0] A5 R6 A6 FU_C CLR CLR R7 FU_control A7 ZeroA RIN D_REQ DT2_R AIN D_ACK DT2_A EX90 EX[90:87] ZZZOP[63:32] S EX86 B[31:0] Zerox32 Y[31:0] DONE[87:0] EX[76:69] TAG[7:0] EX[68:64] DEST[4:0] EX[63:32] PC[31:0] ROUT RT2_R AOUT RT2_A EX[31:0] A[31:0] RES[36:0] Processor William F. Design Richardson Execution Unit Dispatching RT2_V[36:0] OPCODE[31:0] RQ_REQ RQ2_R XOP[63:32] OP_A[31:0] RQ_ACK RQ2_A OP[31:0] OP_B[31:0] RQ[31:0] RQ2_V[31:0] PUTCR_REQ PUTCR_REQ PUTCR_ACK PUTCR_ACK PUTCR[31:0] PUTCR[31:0] CR_NUM[9:0] CR_NUM[9:0] GETCR_REQ GETCR_REQ GETCR_ACK GETCR_ACK GETCR[31:0] Fred DT2_T[87:0] TELLME XOP[63:32] MUX2x32 OP[63:32] EXTRA[3:0] GETCR[31:0] Logic 183 184 CLR FU_M CLR CLR CLR DT0_R R1 DT0_A A1 DT0_T[87:0] Y DT1_R R0 DT1_A A0 DT1_T[87:0] X FU_memory MEM_UNIT_REQ RIN MEM_UNIT_ACK AIN Arb Call x88 RS AS EX[90:87] EX86 EXTRA[3:0] Z CLR TELLME EX[76:69] TAG[7:0] EX[68:64] DEST[4:0] CR0[31:0] CR0[31:0] CLR R1 W EX[31:0] OPCODE[31:0] OP[95:64] OP_S[31:0] XOP[63:32] OP_A[31:0] OP[31:0] OP_B[31:0] A1 AA[87:0] R0 D_REQ DT3_R DT3_A DATA_REQ DATA_REQ D_ACK DATA_ACK DATA_ACK DONE[87:0] DATA_ACK_ACK READ CLR Figure 3.11: ex-unit2 D_WRITE[31:0] READ REG_Q_REQ RT3_R BYTE_STROBE[3:0] REG_Q_ACK RT3_A R1 DT2_A A1 DT2_T[87:0] Y CLR D_ADDR[31:0] REG_Q[36:0] RT3_V[36:0] DONE[87:0] W Arb Call x88 D_WRITE[31:0] R1_Q_REQ RQ3_R D_READ[31:0] R1_Q_ACK RQ3_A D_STATUS[3:0] R1_Q[31:0] RS AS Arb Y Call x88 R0 D_STATUS[3:0] DONE_ACK Z A0 CLR DT2_R RS R0 Z Z A0 AS D_READ[31:0] DONE_REQ AS BB[87:0]X CLR DT3_T[87:0] A1 D_ADDR[31:0] RS DATA_ACK_ACK R1 BYTE_STROBE[3:0] Arb Y Call x88 CC[87:0] X RQ3_V[31:0] A0 W X W FU_B CLR CLR FU_branch BR_UNIT_REQ RIN BR_UNIT_ACK AIN EX[90:87] EXTRA[3:0] TAG[7:0] EX[68:64] DEST[4:0] EX[63:32] PC[31:0] RQ0_R R1 D_REQ DT4_R RQ0_A A1 D_ACK DT4_A RQ0_V[31:0] Y The DONE[87:0] EX[31:0] CR0[31:0] TELLME EX[76:69] Call x32 DT4_T[87:0] OP_A[31:0] OP[31:0] OP_B[31:0] Queue arbitrated, doesn’t since have to be that is done by RS R1_Q_REQ AS R1_Q_ACK Z R1_Q[31:0] AS OPCODE[31:0] XOP[63:32] R1 RS the RQ1_R R0 BR_REQ BR_REQ RQ1_A A0 BR_ACK BR_ACK RQ1_V[31:0] X Dispatch Unit. Z R1 BR[31:0] BR[31:0] A1 PREFETCH_REQ PF_REQ XBR_REQ XBR_REQ PREFETCH_ACK PF_ACK XBR_ACK XBR_ACK PREFETCH[31:0] Fred Processor William F. Design Richardson PF[31:0] XBR[31:0] Execution Unit RQ2_R R1 RQ2_A A1 RQ2_V[31:0] Y AAR1_Q[31:0] Y Call x32 XBR[31:0] Completion Routing RQ3_R R0 RQ3_A A0 RQ3_V[31:0] X Call x32 RS R0 AS A0 Z BBR1_Q[31:0] X CHAPTER 3. SCHEMATIC DIAGRAMS CR0[31:0] EX86 RIN OUT Delay2 IN MC OUT OUT Delay1 C AIN A B CLR AOUT IN Rin fanin is 1 Ain drives 0 ROUT P Aout fanin is 5 OUT[31:0] C IN[31:0] IN[31:0] TLNT Figure 3.12: fo-32 Rout drives 0 OUT[31:0] Clr fanin is 1 In fanin is 2 Out drives 2 Total Modules: 47 Fred Processor William F. Design Richardson 32-bit FIFO 185 186 RIN OUT Delay2 MC OUT OUT Delay1 C AIN A B CLR AOUT IN IN ROUT IN35 IN[35:32] D Q TLNT C OUT35 P Figure 3.13: fo-36 OUT[35:32] IN34 D Q TLNT C OUT34 P IN33 D Q TLNT C OUT33 P IN32 D Q TLNT C OUT32 Processor William F. Design Richardson 36-bit FIFO, divided into P a OUT[31:0] C Fred TLNT IN[31:0] IN[31:0] OUT[31:0] 32-bit input and a 4-bit input CHAPTER 3. SCHEMATIC DIAGRAMS P VERIFY_ADDRESS VHDL=VERIFY_ADDRESS MAXADDR=65535 Y_DEBUG Y_DEBUG X_DEBUG X_DEBUG Memory Latches S[3:0] XSTATUS[3:0] XI_A INST_REQ REQO REQI ACKI ACKO INST_REQ OUT Delay1 IN XI_AA I INST_ACK O IDELAY INST_ACK CLR RAM INST_ACK_ACK INST_ACK_ACK I_ADDR[31:0] I_ADDR[31:0] I_DATA[31:0] I_DATA[31:0] MDATA[31:0] RAM 64K (16Kx32) CLR XDATA[31:0] XDATA[31:0] WDATA[31:0] XD_WRITE[31:0] R1 G1 A1 D1 R2 G0 A2 D0 R1 READ XI_R Arb RS Call AS REQ ADDR[31:2] I_STATUS[3:0] CLR R0 ACK I_STATUS[3:0] XD_R W READ[31:0] MDATA[31:0] CLR DATA_REQ DATA_REQ ADDR[31:2] MEM_ARBITER RD XD_AA I DATA_ACK O DDELAY DATA_ACK BYTES[3:0] Figure 3.14: fred-memory XD_A WRITE[31:0] DATA_ACK_ACK DATA_ACK_ACK XD_WRITE[31:0] S READ B[31:2] READ XI_ADDR[31:2] BYTE_STROBE[3:0] BYTE_STROBE[3:0] Y[31:2] XI_ADDR[31:0] A[31:2] XIA[31:0] D_ADDR[31:0] MUX2x30 XD_ADDR[31:0] A[31:2] D_ADDR[31:0] XDA[31:0] XD_ADDR[31:2] D_WRITE[31:0] XSTATUS[3:0] D_WRITE[31:0] XS[3:0] D_READ[31:0] XDATA[31:0] D_READ[31:0] XDATA[31:0] D_STATUS[3:0] D_STATUS[3:0] VDD XD_WRITE[31:0] B XDW[31:0] MX2 Y XREAD A S XBS[3:0] CLR S VDD,VDD,VDD,VDD B[3:0] CLR Y[3:0] B[3:0] MUX2x4 XBYTE_STROBE[3:0] A[3:0] The prefetch since data the controller the Delay Address times: Minimum memory Increase IDELAY delay and delay with DDELAY is 2ns. variable Bits inside modules. best is not used, memory is fast. A would be needed to use of OUT Delay1 IN the prefetch cache make data. bits: are the word Bit 1 31-2 is used for the Bit 0 is currently address. User/Supervisor unused. PREFETCH_REQ mode. PREFETCH_ACK PREFETCH[31:0] Fred Processor William F. Design Richardson System Memory 187 188 MEMORY FRED Memory Fred Processor INST_REQ INST_REQ INST_REQ INST_ACK INST_ACK INST_ACK INST_ACK_ACK INST_ACK_ACK INST_ACK_ACK I_ADDR[31:0] I_ADDR[31:0] I_ADDR[31:0] I_DATA[31:0] I_DATA[31:0] I_DATA[31:0] I_STATUS[3:0] I_STATUS[3:0] I_STATUS[3:0] Figure 3.15: fred-with-mem PREFETCH_REQ PREFETCH_REQ PREFETCH_REQ PREFETCH_ACK PREFETCH_ACK PREFETCH_ACK PREFETCH[31:0] purposes. PREFETCH[31:0] PREFETCH[31:0] Y_DEBUG DATA_REQ DATA_REQ DATA_REQ DATA_ACK DATA_ACK DATA_ACK testing DATA_ACK_ACK DATA_ACK_ACK READ READ DATA_ACK_ACK READ BYTE_STROBE[3:0] BYTE_STROBE[3:0] BYTE_STROBE[3:0] D_ADDR[31:0] D_ADDR[31:0] D_WRITE[31:0] just D_WRITE[31:0] D_WRITE[31:0] D_READ[31:0] D_READ[31:0] D_READ[31:0] D_STATUS[3:0] D_STATUS[3:0] D_STATUS[3:0] This is CLR INT CLR A B XOR CLR Y INT SYNC_REQ SYNC_REQ SYNC_ACK SYNC_ACK SYNC_NACK Fred Processor William F. SYNC_NACK Design Richardson Complete Fred System with Memory CHAPTER 3. SCHEMATIC DIAGRAMS for D_ADDR[31:0] CLR IF_UNIT CLR IF INST_REQ INST_REQ INST_ACK INST_ACK Unit CR0[31:0] CR0[31:0] PUTCR_REQ PUTCR_REQ PUTCR_ACK PUTCR_ACK PUTCR[31:0] PUTCR[31:0] CR_NUM[9:0] CR_NUM[9:0] GETCR_REQ GETCR_REQ GETCR_ACK GETCR_ACK GETCR[31:0] INST_ACK_ACK INST_ACK_ACK I_ADDR[31:0] I_ADDR[31:0] I_DATA[31:0] I_DATA[31:0] I_STATUS[3:0] GETCR[31:0] I_STATUS[3:0] Figure 3.16: fred1 INT CLR_SB_REQ CLR_SB_REQ CLR_SB_ACK CLR_SB_ACK INT CLR_SB[4:0] CLR_SB[4:0] CLR PIPE_RF SYNC_REQ SYNC_REQ SYNC_ACK SYNC_ACK SYNC_NACK CLR RF_REQ RIN RF_ACK AIN PIPE_Nx18 ROUT RF_REQ AOUT RF_ACK SYNC_NACK RF[17:0] BR_REQ BR_REQ BR_ACK BR_ACK O[17:0] RF[17:0] AAARF[17:0] XBR_ACK XBR_ACK XBR[31:0] XBR[31:0] EX[127:0] XBR_REQ EX_ACK BR[31:0] XBR_REQ EX_REQ BR[31:0] I[17:0] DONE_REQ DONE_REQ DONE_ACK DONE_ACK DONE[87:0] DONE[87:0] CLR PIPE_EX CLR EX_REQ ROUT EX_ACK AOUT EX[127:0] RIN PIPE_Nx128 O[127:0] AIN I[127:0] AAAEX[127:0] Fred Processor William F. Design Richardson Instruction Fetch Unit. 189 190 CLR RF_UNIT CLR CLR Register File PIPE_CLR CLR CLR_SB_REQ ROUT CLR_SB_ACK AOUT CLR_SB[4:0] RIN PIPE_Nx5 O[4:0] CLR_SB_REQ AIN I[4:0] CLR_SB_ACK AAACLR_SB[4:0] CLR_SB[4:0] RF_REQ RF_REQ RF_ACK RF_ACK CLR RF[17:0] RF[17:0] PIPE_OP CLR OP_REQ RIN Figure 3.17: fred2 OP_ACK RT0_R RT0_R RT0_A RT0_A RT0_V[36:0] RT1_A RT1_A RT1_R RT2_A RT2_A RT2_R Processor William F. Design Richardson Register File ROUT OP_REQ AOUT OP_ACK O[95:0] OP[95:0] RT3_R RT3_V[36:0] R1_Q_REQ R1_Q_REQ R1_Q_ACK R1_Q_ACK R1_Q[31:0] CHAPTER 3. SCHEMATIC DIAGRAMS RT3_A RT3_A R1_Q[31:0] Fred RT2_V[36:0] RT3_R RT3_V[36:0] PIPE_Nx96 I[95:0] RT1_V[36:0] RT2_R RT2_V[36:0] AIN AAAOP[95:0] RT0_V[36:0] RT1_R RT1_V[36:0] OP[95:0] CLR EX_UNIT CLR Execute Unit CR0[31:0] CR0[31:0] EX_REQ EX_REQ OP_REQ OP_REQ EX_ACK EX_ACK OP_ACK OP_ACK EX[127:0] EX[127:0] CLR Figure 3.18: fred3 PIPE_BR OP[95:0] OP[95:0] PUTCR_REQ PUTCR_REQ PUTCR_ACK PUTCR_ACK PUTCR[31:0] PUTCR[31:0] CR_NUM[9:0] CR_NUM[9:0] GETCR_REQ GETCR_REQ GETCR_ACK GETCR_ACK GETCR[31:0] GETCR[31:0] CLR BR_REQ ROUT BR_ACK AOUT CLR PIPE_Nx32 RIN BR_REQ AIN BR_ACK PIPE_DONE BR[31:0] O[31:0] I[31:0] AAABR[31:0] BR[31:0] CLR CLR DONE_REQ RIN DONE_ACK AIN DONE[87:0] AAADONE[87:0] PIPE_Nx88 I[87:0] ROUT DONE_REQ AOUT DONE_ACK O[87:0] DONE[87:0] PIPE_XBR CLR XBR_REQ ROUT XBR_ACK AOUT XBR[31:0] RIN AIN PIPE_Nx32 O[31:0] XBR_REQ I[31:0] XBR_ACK AAAXBR[31:0] XBR[31:0] RT0_R RT0_R RT0_A RT0_A RT0_V[36:0] RT0_V[36:0] PREFETCH_REQ PREFETCH_REQ RT1_R RT1_R PREFETCH_ACK PREFETCH_ACK RT1_A RT1_A PREFETCH[31:0] PREFETCH[31:0] RT1_V[36:0] RT2_R RT2_A RT2_A RT2_V[36:0] DATA_REQ DATA_REQ DATA_ACK DATA_ACK DATA_ACK_ACK READ BYTE_STROBE[3:0] D_ADDR[31:0] DATA_ACK_ACK READ RT1_V[36:0] RT2_R RT2_V[36:0] RT3_R RT3_R RT3_A RT3_A RT3_V[36:0] RT3_V[36:0] CLR BYTE_STROBE[3:0] D_ADDR[31:0] PIPE_R1 CLR D_WRITE[31:0] D_READ[31:0] D_STATUS[3:0] Fred Processor William F. Design Richardson Execute D_WRITE[31:0] D_READ[31:0] D_STATUS[3:0] R1_Q_REQ RIN R1_Q_ACK R1_Q[31:0] AIN AAR1Q[31:0] PIPE_Nx32 I[31:0] ROUT R1_Q_REQ AOUT R1_Q_ACK O[31:0] R1_Q[31:0] Unit 191 192 ARITH CLR CLR Arith CLR Unit VHDL=ARITH_UNIT Figure 3.19: fu-arith PIPE D_REQ D_REQ RIN RIN ROUT RIN D_ACK D_ACK AIN AIN PIPE_Nx3op AOUT AIN DONE[87:0] CLR EXTRA[3:0] TELLME Processor William F. Design Richardson TMIN EOUT[3:0] AAE[3:0] TMOUT TAG[7:0] TIN[7:0] TOUT[7:0] AATAG[7:0] DEST[4:0] DIN[4:0] DOUT[4:0] AADEST[4:0] OPCODE[31:0] WI[31:0] WO[31:0] AAOPCODE[31:0] OP_A[31:0] XI[31:0] XO[31:0] OP_B[31:0] YI[31:0] YO[31:0] Arithmetic Unit DONE[87:0] EXTRA[3:0] TELLME ROUT ROUT TAG[7:0] AOUT AOUT DEST[4:0] RES[36:0] RES[36:0] OPCODE[31:0] RQ_REQ RQ_REQ AAOP_A[31:0] OP_A[31:0] RQ_ACK RQ_ACK AAOP_B[31:0] OP_B[31:0] RQ[31:0] RQ[31:0] CHAPTER 3. SCHEMATIC DIAGRAMS Fred EIN[3:0] BRANCH CLR CLR CLR Branch Unit VHDL=BRANCH_UNIT PIPE CLR RIN RIN ROUT AIN AIN PIPE_Nx4op AOUT EXTRA[3:0] EIN[3:0] EOUT[3:0] RIN AIN AAE[3:0] EXTRA[3:0] CR0[31:0] TELLME TMIN TMOUT Figure 3.20: fu-branch TAG[7:0] TIN[7:0] TOUT[7:0] AATAG[7:0] DEST[4:0] DIN[4:0] DOUT[4:0] AADEST[4:0] PC[31:0] WI[31:0] WO[31:0] AAPC[31:0] TAG[7:0] D_REQ D_REQ D_ACK D_ACK DEST[4:0] PC[31:0] DONE[87:0] OPCODE[31:0] XI[31:0] XO[31:0] AAOPCODE[31:0] OP_A[31:0] YI[31:0] YO[31:0] AAOP_A[31:0] OP_A[31:0] OP_B[31:0] ZI[31:0] ZO[31:0] AAOP_B[31:0] OP_B[31:0] BR_REQ BR_REQ BR_ACK BR_ACK Processor F. Design Richardson Branch BR[31:0] PF_REQ PF_REQ XBR_REQ XBR_REQ PF_ACK PF_ACK XBR_ACK XBR_ACK PF[31:0] William DONE[87:0] OPCODE[31:0] BR[31:0] Fred CR0[31:0] TELLME PF[31:0] XBR[31:0] XBR[31:0] Unit 193 194 CTRL CLR CLR Control CLR Unit VHDL=CONTROL_UNIT PIPE D_REQ D_REQ ROUT RIN D_ACK D_ACK AOUT AIN DONE[87:0] CLR RIN RIN AIN AIN TELLME EIN[3:0] TMIN EOUT[3:0] AAE[3:0] TMOUT TELLME TAG[7:0] TIN[7:0] TOUT[7:0] AATAG[7:0] DEST[4:0] DIN[4:0] DOUT[4:0] AADEST[4:0] TAG[7:0] PC[31:0] WI[31:0] WO[31:0] AAPC[31:0] OPCODE[31:0] XI[31:0] XO[31:0] AAOPCODE[31:0] OP_A[31:0] YI[31:0] YO[31:0] AAOP_A[31:0] OP_A[31:0] OP_B[31:0] ZI[31:0] ZO[31:0] AAOP_B[31:0] OP_B[31:0] DEST[4:0] ROUT ROUT AOUT AOUT RES[36:0] Processor William F. Design Richardson Control Unit RES[36:0] PC[31:0] RQ_REQ RQ_REQ OPCODE[31:0] RQ_ACK RQ_ACK RQ[31:0] RQ[31:0] PUTCR_REQ PUTCR_REQ PUTCR_ACK PUTCR_ACK PUTCR[31:0] PUTCR[31:0] CR_NUM[9:0] CR_NUM[9:0] GETCR_REQ GETCR_REQ GETCR_ACK GETCR_ACK GETCR[31:0] Fred DONE[87:0] EXTRA[3:0] GETCR[31:0] CHAPTER 3. SCHEMATIC DIAGRAMS Figure 3.21: fu-control EXTRA[3:0] PIPE_Nx4op LOGIC CLR CLR Logic CLR Unit VHDL=LOGIC_UNIT PIPE D_REQ D_REQ RIN D_ACK D_ACK AIN DONE[87:0] CLR Figure 3.22: fu-logic RIN RIN ROUT AIN AIN PIPE_Nx3op AOUT EXTRA[3:0] TELLME Fred Processor William F. Design Richardson Logic EIN[3:0] TMIN EOUT[3:0] AAE[3:0] TMOUT TAG[7:0] TIN[7:0] TOUT[7:0] AATAG[7:0] DEST[4:0] DIN[4:0] DOUT[4:0] AADEST[4:0] OPCODE[31:0] WI[31:0] WO[31:0] AAOPCODE[31:0] OP_A[31:0] XI[31:0] XO[31:0] AAOP_A[31:0] OP_B[31:0] YI[31:0] YO[31:0] AAOP_B[31:0] DONE[87:0] EXTRA[3:0] TELLME ROUT ROUT TAG[7:0] AOUT AOUT DEST[4:0] OPCODE[31:0] RES[36:0] RES[36:0] RQ_REQ RQ_REQ OP_A[31:0] RQ_ACK RQ_ACK OP_B[31:0] RQ[31:0] RQ[31:0] Unit 195 196 CLR MEM CLR CLR Memory PIPE Unit CLR RIN RIN ROUT RIN AIN AIN PIPE_Nx4op AOUT AIN EXTRA[3:0] TELLME EIN[3:0] TMIN EOUT[3:0] AAE[3:0] TMOUT TOUT[7:0] AATAG[7:0] DEST[4:0] DIN[4:0] DOUT[4:0] AADEST[4:0] OPCODE[31:0] WI[31:0] WO[31:0] AAOPCODE[31:0] OP_S[31:0] XI[31:0] XO[31:0] AAOP_S[31:0] OP_S[31:0] OP_A[31:0] YI[31:0] YO[31:0] AAOP_A[31:0] OP_A[31:0] OP_B[31:0] ZI[31:0] ZO[31:0] AAOP_B[31:0] OP_B[31:0] D_REQ D_ACK D_ACK DATA_ACK DATA_ACK DONE[87:0] D_READ[31:0] D_STATUS[3:0] Design Memory Unit OPCODE[31:0] D_REQ D_WRITE[31:0] Richardson CR0[31:0] DATA_REQ D_ADDR[31:0] F. CR0[31:0] DEST[4:0] DATA_REQ BYTE_STROBE[3:0] Processor TAG[7:0] DONE[87:0] DATA_ACK_ACK READ REG_Q_REQ REG_Q_REQ BYTE_STROBE[3:0] REG_Q_ACK REG_Q_ACK D_ADDR[31:0] D_WRITE[31:0] D_READ[31:0] D_STATUS[3:0] REG_Q[36:0] REG_Q[36:0] R1_Q_REQ R1_Q_REQ R1_Q_ACK R1_Q_ACK R1_Q[31:0] R1_Q[31:0] CHAPTER 3. SCHEMATIC DIAGRAMS Figure 3.23: fu-memory TIN[7:0] READ William EXTRA[3:0] TELLME TAG[7:0] DATA_ACK_ACK Fred VHDL=MEMORY_UNIT CLR Figure 3.24: gate GND G S1 S0 D0 D1 MX4 D2 I Fred Processor William F. Design Richardson When G is high, When G is low, A gated the the Y O D3 input input passes is directly to the output. latched. latch. 197 198 CLR DISPATCH CLR Dispatch VHDL=DISPATCH X_DEBUG SYNC_REQ SYNC_REQ SYNC_ACK SYNC_ACK SYNC_NACK X_DEBUG PF_DEBUG SYNC_NACK PF_DEBUG X_CR0[31:0] CR0[31:0] PUTCR_REQ PUTCR_REQ PUTCR_ACK PUTCR_ACK SB_R_R SB_R_R PUTCR[31:0] PUTCR[31:0] SB_R_G SB_R_G CR_NUM[9:0] CR_NUM[9:0] SB_R_D SB_R_D GETCR_REQ GETCR_REQ SB[31:0] GETCR_ACK GETCR_ACK SB[31:0] GETCR[31:0] Figure 3.25: if-unit1 SB_W_R SB_W_R SB_W_A SB_W_A SB_SET SB_SET GETCR[31:0] BR_P_REQ R BR_REQ SB_NUM[4:0] SB_NUM[4:0] BR_P Q BR_P_ACK A BR_ACK INST_REQ INST_REQ INST_ACK INST_ACK BR_ACK BR[31:0] BR[31:0] XBR_P_REQ INST_ACK_ACK INST_ACK_ACK I_ADDR[31:0] I_ADDR[31:0] I_DATA[31:0] I_DATA[31:0] R XBR_REQ XBR_P Q XBR_P_ACK A XBR_ACK I_STATUS[3:0] XBR_ACK I_STATUS[3:0] XBR[31:0] XBR[31:0] RF_REQ DONE_REQ RF_P_REQ DONE_ACK DONE_ACK RF_P DONE[87:0] DONE[87:0] RF_REQ R Q RF_ACK RF_P_ACK A RF[17:0] RF[17:0] EX_REQ EX_REQ EX_P_REQ INT A B XOR Y EXTERNAL_INT REPLY_HAZY R EX_P REPLY_HAZY Q EX_ACK EX_P_ACK A CLR FAULT_PENDING FAULT_PENDING EX[127:0] EX[127:0] CLR O Gate I G A Y Fred Processor William F. Design Richardson Dispatch AND2A Unit, B with This signal INTs are is tied to the CR0’s INT enable bit. CR05 FIFOs disabled and while exceptions arbiter. are in progress. CHAPTER 3. SCHEMATIC DIAGRAMS DONE_REQ The CLR_SB_REQ can be pipelined, but setting or reading the Scoreboard can’t, or the Dispatch Unit might see the wrong value. CLR CLR CLR SB_W_R R1 SB_W_A A1 SCOREBOARD CLR Figure 3.26: if-unit2 Arb Call CLR_SB_REQ R0 CLR_SB_ACK A0 RS WR_R AS WR_A Scoreboard RD_R SB_R_R SET RD_G SB_R_G NUM[4:0] RD_D SB_R_D BITS[31:0] W NUM[4:0] SB[31:0] GND A SB_SET B S Y Fred Processor William F. Design Richardson Scoreboard and SEL OUT[4:0] MUX-2x5 SB_NUM[4:0] B[4:0] CLR_SB[4:0] A[4:0] MX2 wake-up arbitration for Dispatch Unit. 199 200 CLR FIFO-32 XI_R R INST_REQ A XIA[31:0] D I_ADDR[31:0] XI_A CLR A XDATA[31:0] I FIFO-36 R XI_AA INST_ACK DELAY=4 total I_DATA[31:0] D32 XS[3:0] O Vdelay INST_ACK_ACK is 1.6 + Figure 3.27: memory-latches 0.1 * DELAY (ns) 0.1 * DELAY (ns) I_STATUS[3:0] D4 CLR FIFO-32 XD_R R DATA_REQ A XDA[31:0] D D_ADDR[31:0] XD_A CLR A XREAD BYTE_STROBE[3:0] 4 Y Imem this D_WRITE[31:0] A READ BUF Processor William F. Design Richardson Memory 1.6 Latches to allow and Dmem does not requests + from reads are independent, but handle multiple outstanding each. the address REQ, Dmem write data. own Fred is D_STATUS[3:0] 32 XBS[3:0] total D_READ[31:0] D4 XDW[31:0] DATA_ACK DELAY=4 D32 XS[3:0] O Vdelay DATA_ACK_ACK There and no Write risk! interleaved memory access. is no ACK for buffering of the to Imem at your CHAPTER 3. SCHEMATIC DIAGRAMS XDATA[31:0] I FIFO-36 R XD_AA S A31 A A30 S MX2 Figure 3.28: mux2x30 A22 S MX2 A S MX2 A14 S MX2 A21 A S MX2 B B15 A S MX2 MX2 A A20 MX2 A S MX2 A12 A19 A MX2 A S MX2 A11 A18 A MX2 A S MX2 A10 A17 A MX2 A S MX2 A9 A16 A Y Y17 S MX2 Y Y16 B A A8 S MX2 A Y Y9 S MX2 B B9 Y Y24 B16 Y Y10 B10 S MX2 B S A B B17 Y Y11 A24 Y Y25 B24 Y Y18 B B11 S MX2 B S A B B18 Y Y12 A25 Y Y26 B25 Y Y19 B B12 S MX2 B S A B B19 Y Y13 A26 Y Y27 B26 Y Y20 B B13 S MX2 B S A B27 Y Y21 B B14 A27 Y Y28 B B20 Y Y14 B S B28 Y Y22 A13 A B B21 Y Y15 A28 Y Y29 B B22 A MX2 B B23 S B29 Y Y23 B A B B30 A A29 Y Y30 B B31 A15 S MX2 B A23 A Y Y31 Y Y8 B B8 A[31:2] B[31:2] A7 A A6 S MX2 Processor William F. Design Richardson A Y Y6 A4 S MX2 B B6 MUX A5 S MX2 B B7 Fred A Y Y7 A3 S MX2 B B5 A Y Y5 A2 S MX2 B B4 A Y Y4 S MX2 B B3 A Y Y3 B Y Y2 Y[31:2] B2 2x30 201 202 S A31 A A30 S MX2 B A A22 S A S A14 MX2 A S MX2 A6 S MX2 A20 S MX2 A A MX2 A12 A5 A Processor William F. Design Richardson MUX 2x32 MX2 A A4 B5 S MX2 A11 A A18 S MX2 A10 B4 A MX2 A2 A Y[31:0] A24 A17 A9 A S MX2 A16 A A8 S S MX2 Y Y16 A Y Y9 S MX2 Y Y8 B B8 A A0 S MX2 A Y Y1 S MX2 B B1 Y Y24 B MX2 Y Y2 B A Y Y17 B A1 MX2 B16 Y Y10 S S B B9 A A Y Y25 B24 Y Y18 S MX2 B2 MX2 B MX2 Y Y3 B S B17 Y Y11 S B3 B[31:0] S B MX2 B A B10 Y Y4 A B25 B B11 A3 A25 Y Y26 B B18 Y Y12 S S MX2 Y Y19 B MX2 B A Y Y20 S A B26 B MX2 A A26 Y Y27 B B19 Y Y5 A[31:0] Fred A19 S B MX2 B A Y Y13 S MX2 B27 B12 Y Y6 S B B S A Y Y28 B20 Y Y14 S MX2 Y Y21 B MX2 B6 A B13 Y Y7 B B7 A13 A27 S B B B14 A A21 A Y Y29 B28 Y Y22 B B15 MX2 B21 Y Y15 B A28 S B B0 Y Y0 CHAPTER 3. SCHEMATIC DIAGRAMS Figure 3.29: mux2x32 MX2 B22 S A B B B23 A A29 Y Y30 B29 Y Y23 B A7 MX2 B30 MX2 A15 S B B31 A23 A Y Y31 B[3:0] A[3:0] Y[3:0] S A3 Figure 3.30: mux2x4 A A2 S Y A B3 Fred Processor William F. Design Richardson Mux B A1 S Y3 Y MX2 A B2 B A0 S Y2 Y MX2 A B1 B S Y1 Y MX2 Y0 MX2 B0 B 2x4 203 204 B[4:0] B4 B3 B2 B1 B0 A[4:0] A4 A3 A2 A1 A0 SEL A Y BUF A MX2 S MX2 S Y Y OUT1 B A Y OUT2 B MX2 S OUT0 OUT[4:0] CHAPTER 3. SCHEMATIC DIAGRAMS mux A bit OUT3 B 5 Y Design Richardson MX2 F. S Y Processor William A MX2 S Fred B A B Figure 3.31: mux2x5 OUT4 B[7:0] A[7:0] Y[7:0] Figure 3.32: mux2x8 S A7 A A6 S Y A B7 A3 Y B6 A2 S Y Fred Processor William F. Design Richardson Mux B Y A B5 A1 S Y3 Y B A Y A A0 S Y B A B S Y1 Y MX2 B1 Y4 MX2 B4 Y2 S Y5 B MX2 B2 A4 S MX2 B MX2 B3 A Y6 MX2 B A A5 S Y7 MX2 Y0 MX2 B0 B 2x8 205 206 CLR DC CLR Figure 3.33: pipe-nx128 RIN RIN AIN AIN Delay Chain ROUT ROUT AOUT AOUT CLR CP CLR C P CPx128 I[127:0] Processor William F. Design Richardson Variable-length FIFO pipeline O[127:0] O[127:0] CHAPTER 3. SCHEMATIC DIAGRAMS Fred I[127:0] CLR DC CLR Figure 3.34: pipe-nx18 RIN RIN AIN AIN Delay Chain ROUT ROUT AOUT AOUT CLR CP CLR C P CPx18 I[17:0] Fred Processor William F. Design Richardson Variable-length FIFO I[17:0] O[17:0] O[17:0] pipeline 207 208 CLR DC CLR Figure 3.35: pipe-nx32 RIN RIN AIN AIN Delay Chain ROUT ROUT AOUT AOUT CLR CP CLR C P CPx32 I[31:0] Processor William F. Design Richardson Variable-length FIFO pipeline O[31:0] O[31:0] CHAPTER 3. SCHEMATIC DIAGRAMS Fred I[31:0] EIN[3:0] EOUT[3:0] TIN[7:0] TOUT[7:0] DIN[4:0] DOUT[4:0] WI[31:0] CLR XI[31:0] WO[31:0] DC XO[31:0] CLR Figure 3.36: pipe-nx3op RIN RIN AIN AIN ROUT ROUT AOUT AOUT YI[31:0] YO[31:0] Delay Chain CLR CP CLR C P CPx3op EIN[3:0],TMIN,TIN[7:0],DIN[4:0],WI[31:0],XI[31:0],YI[31:0] I[113:0] TMIN Fred Processor William F. Design Richardson Variable-length FIFO EOUT[3:0],TMOUT,TOUT[7:0],DOUT[4:0],WO[31:0],XO[31:0],YO[31:0] O[113:0] TMOUT pipeline 209 210 EIN[3:0] EOUT[3:0] TIN[7:0] TOUT[7:0] DIN[4:0] DOUT[4:0] WI[31:0] CLR XI[31:0] WO[31:0] DC XO[31:0] CLR RIN RIN AIN AIN ROUT ROUT AOUT AOUT Figure 3.37: pipe-nx4op YI[31:0] YO[31:0] Delay Chain ZI[31:0] ZO[31:0] CLR CP CLR C P CPx4op EIN[3:0],TMIN,TIN[7:0],DIN[4:0],WI[31:0],XI[31:0],YI[31:0],ZI[31:0] EOUT[3:0],TMOUT,TOUT[7:0],DOUT[4:0],WO[31:0],XO[31:0],YO[31:0],ZO[31:0] I[145:0] TMIN Processor William F. Design Richardson Variable-length FIFO pipeline TMOUT CHAPTER 3. SCHEMATIC DIAGRAMS Fred O[145:0] CLR DC CLR Figure 3.38: pipe-nx5 RIN RIN AIN AIN Delay Chain ROUT ROUT AOUT AOUT CLR CP CLR P C CPx5 I[4:0] Fred Processor William F. Design Richardson Variable-length FIFO I[4:0] O[4:0] O[4:0] pipeline 211 212 CLR DC CLR Figure 3.39: pipe-nx88 RIN RIN AIN AIN Delay Chain ROUT ROUT AOUT AOUT CLR CP CLR C P CPx88 I[87:0] Processor William F. Design Richardson Variable-length FIFO pipeline O[87:0] O[87:0] CHAPTER 3. SCHEMATIC DIAGRAMS Fred I[87:0] CLR DC CLR Figure 3.40: pipe-nx96 RIN RIN AIN AIN Delay Chain ROUT ROUT AOUT AOUT CLR CP CLR C P CPx96 I[95:0] Fred Processor William F. Design Richardson Variable-length FIFO I[95:0] O[95:0] O[95:0] pipeline 213 214 O A Fred Processor William F. Design Richardson Returns 1 when both R Q Y XNOR A I0 B I1 A inputs are equal. CHAPTER 3. SCHEMATIC DIAGRAMS Figure 3.41: qop-even R Figure 3.42: qop-odd R O A Fred Processor William F. Design Richardson Returns 1 when R Q Y XOR A I0 B I1 A inputs are different. 215 B1 A B0 B B0 A B2 B B1 A B3 B B0 A B1 B B3 C OR2 OR2 Processor William F. Design Richardson Y Y NOR2 Y OA1B Byte Order for Memory Read B[3:0] OUT[31:0] C[7:0] D[7:0] OUT[7:0] MUX - 4x8 OUT[7:0] S1 IN[7:0] S0 OUT[7:0] IN[15:8] A[7:0] B[7:0] C[7:0] D[7:0] OUT[15:8] Y IN[31:0] Fred IN[23:16] S1 IN[7:0] MUX - 4x8 OUT[7:0] IN[15:8] IN[31:24] S0 C[7:0] D[7:0] OUT[23:16] A[7:0] B[7:0] S1 IN[7:0] IN[23:16] S1 IN[15:8] MUX - 4x8 OUT[31:24] S0 OUT[7:0] IN[23:16] IN[31:24] CHAPTER 3. SCHEMATIC DIAGRAMS Figure 3.43: ram-byte-order IN[7:0] MUX - 4x8 IN[15:8] S0 A[7:0] B[7:0] IN[23:16] IN[31:24] A[7:0] B[7:0] C[7:0] D[7:0] 216 IN[31:24] This determines The Don’t It is RAM change tuned for system models memory have the memory the delay response zero delay delay here, of the time though. calling circuit. This I REQ O ACK Vdelay ADDR[31:2] orders the bytes according Delay is about to the byte strobes 3ns TMP[31:0] IN[31:0] DELAY=5 Byte order READ[31:0] OUT[31:0] BYTES[3:0] WRITE[31:0] This delay Read outputs is only for writes B[3:0] IN are always Delay4 OUT A active Q B XOR2 B RD AND2A Y A BYTES1 DSBL DO7 DO6 DO5 DO4 DO3 DO2 DO1 DO0 TMP23 TMP22 TMP21 TMP20 TMP19 TMP18 TMP17 TMP16 WRITE15 WRITE14 WRITE13 WRITE12 WRITE11 WRITE10 WRITE9 WRITE8 R/W* ADDR15 ADDR14 ADDR13 ADDR12 ADDR11 ADDR10 ADDR9 ADDR8 ADDR7 ADDR6 ADDR5 ADDR4 ADDR3 ADDR2 16Kx8 A13 A12 A11 SEG1 A10 A9 A8 MODEL=RAM A7 A6 A5 WIDTH=8 A4 LENGTH=16384 A3 A2 A1 A0 DI7 DI6 DI5 DI4 DI3 DI2 DI1 DI0 DSBL QN A2 A1 A0 DI7 DI6 DI5 DI4 DI3 DI2 DI1 DI0 NAND2 R/W* ADDR15 ADDR14 ADDR13 ADDR12 ADDR11 ADDR10 ADDR9 ADDR8 ADDR7 ADDR6 ADDR5 ADDR4 ADDR3 ADDR2 16Kx8 A13 A12 A11 SEG2 A10 A9 A8 MODEL=RAM A7 A6 A5 WIDTH=8 A4 LENGTH=16384 A3 A WRITE23 WRITE22 WRITE21 WRITE20 WRITE19 WRITE18 WRITE17 WRITE16 B DO7 DO6 DO5 DO4 DO3 DO2 DO1 DO0 TMP31 TMP30 TMP29 TMP28 TMP27 TMP26 TMP25 TMP24 BYTES3 QN NAND2 DSBL B A2 A1 A0 DI7 DI6 DI5 DI4 DI3 DI2 DI1 DI0 QN NAND2 QN NAND2 R/W* ADDR15 ADDR14 ADDR13 ADDR12 ADDR11 ADDR10 ADDR9 ADDR8 ADDR7 ADDR6 ADDR5 ADDR4 ADDR3 ADDR2 16Kx8 A13 A12 A11 SEG3 A10 A9 A8 MODEL=RAM A7 A6 A5 WIDTH=8 A4 LENGTH=16384 A3 WRITE31 WRITE30 WRITE29 WRITE28 WRITE27 WRITE26 WRITE25 WRITE24 A B A B R/W* ADDR15 ADDR14 ADDR13 ADDR12 ADDR11 ADDR10 ADDR9 ADDR8 ADDR7 ADDR6 ADDR5 ADDR4 ADDR3 ADDR2 BYTES2 A Figure 3.44: ram16kx32 BYTES0 DO7 DO6 DO5 DO4 DO3 DO2 DO1 DO0 TMP15 TMP14 TMP13 TMP12 TMP11 TMP10 TMP9 TMP8 WRITE7 WRITE6 WRITE5 WRITE4 WRITE3 WRITE2 WRITE1 WRITE0 16Kx8 A13 A12 A11 SEG0 A10 A9 A8 MODEL=RAM A7 A6 A5 WIDTH=8 A4 LENGTH=16384 A3 A2 A1 A0 DI7 DI6 DI5 DI4 DI3 DI2 DI1 DI0 DSBL DO7 DO6 DO5 DO4 DO3 DO2 DO1 DO0 TMP7 TMP6 TMP5 TMP4 TMP3 TMP2 TMP1 TMP0 GND Fred Processor William F. Design Richardson 32-bit RAM, Req/Ack model 217 218 CLR CLR REGISTERS REGSELECT CLR CLR Registers Reg VHDL=REGSELECT VHDL=REGISTERS Figure 3.45: rf-unit R05[31:0] RF_REQ RF_REQ CLR_SB_ACK R06[31:0] R06[31:0] R06[31:0] RF_ACK RF_ACK CLR_SB[4:0] R07[31:0] R07[31:0] R07[31:0] RF[17:0] R08[31:0] R08[31:0] R08[31:0] R09[31:0] R09[31:0] R09[31:0] RF[17:0] R10[31:0] R10[31:0] R10[31:0] RT0_R RT0_R R11[31:0] R11[31:0] R11[31:0] OP_REQ OP_REQ RT0_A RT0_A R12[31:0] R12[31:0] R12[31:0] OP_ACK OP_ACK RT0_V[36:0] R13[31:0] R13[31:0] R13[31:0] OP[95:0] OP[95:0] R14[31:0] R14[31:0] R14[31:0] RT1_R RT1_A R15[31:0] R15[31:0] R15[31:0] RT1_A RT1_R R16[31:0] R16[31:0] R16[31:0] RT1_V[36:0] R17[31:0] R17[31:0] R17[31:0] R1_Q_REQ R1_Q_REQ R18[31:0] R18[31:0] R18[31:0] R1_Q_ACK R1_Q_ACK R1_Q[31:0] RT2_R RT2_A R19[31:0] R19[31:0] R19[31:0] RT2_A RT2_R R20[31:0] R20[31:0] R20[31:0] RT2_V[36:0] R21[31:0] R21[31:0] R21[31:0] R22[31:0] R22[31:0] R22[31:0] RT3_R RT3_A R23[31:0] R23[31:0] R23[31:0] RT3_A RT3_R R24[31:0] R24[31:0] R24[31:0] RT3_V[36:0] R25[31:0] R25[31:0] R25[31:0] R26[31:0] R26[31:0] R26[31:0] R27[31:0] R27[31:0] R27[31:0] R28[31:0] R28[31:0] R28[31:0] R29[31:0] R29[31:0] R29[31:0] R30[31:0] R30[31:0] R30[31:0] R31[31:0] R31[31:0] R31[31:0] Register Bank Implementation R1_Q[31:0] CHAPTER 3. SCHEMATIC DIAGRAMS Design R04[31:0] CLR_SB_ACK RT3_V[36:0] Richardson R03[31:0] R04[31:0] R05[31:0] RT2_V[36:0] F. R02[31:0] R03[31:0] R04[31:0] R05[31:0] RT1_V[36:0] Processor R02[31:0] R03[31:0] CLR_SB_REQ RT0_V[36:0] William R02[31:0] CLR_SB_REQ CLR_SB[4:0] Fred Select IN[31:0] IN[31:24] IN[23:16] IN[7:0] C C Figure 3.46: tlnt-32 P P IN[15:8] IN[7:0] C TLNT OUT[7:0] OUT[31:24] P IN[7:0] IN[7:0] C TLNT OUT[7:0] OUT[23:16] P IN[7:0] C TLNT OUT[7:0] OUT[15:8] P TLNT OUT[7:0] OUT[7:0] OUT[31:0] C fanin is 8 P fanin is 4 In fanin is 2 Out drives 2 Total Modules: 44 Fred Processor William F. Design Richardson 32-bit TLNT 219 220 Z[31:0] GND,GND,GND,GND,GND,GND,GND,GND GND,GND,GND,GND,GND,GND,GND,GND Figure 3.47: zerox32 GND,GND,GND,GND,GND,GND,GND,GND GND,GND,GND,GND,GND,GND,GND,GND Processor William F. Design Richardson Zero bus 8 8 8 Z[7:0] Z[15:8] Z[23:16] Z[31:24] CHAPTER 3. SCHEMATIC DIAGRAMS Fred 8