Department of Electrical and Computer Engineering The University of Texas at Austin ECE 382N, Spring 2002 Y. N. Patt, D. N. Armstrong Exam 1 Solution Sheet 27 March 2002 1. Part a. module TOP(z[3:0], // output a[3:0], // input b[3:0], // input c[3:0]); // input output [3:0] z; input [3:0] a, b, c; reg clock; nand2$ n2gate(t[0], a[0], b[0]); // each gate needs a nand2$ n2gate(t[1], a[1], b[1]); // different name nand2$ n2gate(t[2], a[2], b[2]); nand2$ n2gate(t[3], a[3], b[3]); // Signal t is undeclared nand3$ n3gate(z[0], t[0], c[0], 1'b1); // each gate needs a nand3$ n3gate(z[1], t[1], 1'b1, c[1]); // different name nand3$ n3gate(z[2], 1'b1, t[2], c[2]); nand3$ n3gate(1'b1, z[0], t[3], c[3]); // Wrong output // z is output nor3$ n3gate(z, 4'b0, 4'b0, 4'b0); // Bit-widths always begin clock = ~clock; // need delay here end endmodule; // TOP // no semi-colon here 1. Part b. Use this version of XOR: 83 /6 ib XOR r/m32, imm8 r/m32 XOR imm8 (sign-extended) Xor with an immediate FFFFFFFFH is equivalent to NOT. Use the 8-bit immediate because the immediate is always constant (all 1's) and also is shorter than using the imm32 version. The shorter instruction is more desirable because it takes up less room in your Icache, is faster to decode, etc. 2. module regfile32_4 (clk, // input - the clock read_select0, // input - select line for 1st read port read_select1, // input - select line for 2nd read port read_select2, // input - select line for 3rd read port read_select3, // input - select line for 4th read port write_select, // input - select line for write port write_enable, // input - write enable for write port write_data, // input - data to write to regfile read_port0, // output - data from 1st read port read_port1, // output - data from 2nd read port read_port2, // output - data from 3rd read port read_port3); // output - data from 4th read port input clk; input [1:0] read_select0, read_select1, read_select2, read_select3; input [1:0] write_select, input write_enable; input [31:0] write_data; output [31:0] read_port0, read_port1, read_port2, read_port3; wire [3:0] decoded_we; wire R0_we, R1_we, R2_we, R3_we; decoder2_4$ write_decoder(write_select, decoded_we, ); and2 write_and0(RO_we, decoded_we[0], write_enable); and2 write_and1(R1_we, decoded_we[1], write_enable); and2 write_and2(R2_we, decoded_we[2], write_enable); and2 write_and3(R3_we, decoded_we[3], write_enable); reg32e$ R0(clk, write_data, R0_out, R0_we); reg32e$ R1(clk, write_data, R1_out, R1_we); reg32e$ R2(clk, write_data, R2_out, R2_we); reg32e$ R3(clk, write_data, R3_out, R3_we); mux4_32 read_mux0(read_port0, R0_out, R1_out, R2_out, R3_out, read_select0); mux4_32 read_mux1(read_port1, R0_out, R1_out, R2_out, R3_out, read_select1); mux4_32 read_mux2(read_port2, R0_out, R1_out, R2_out, R3_out, read_select2); mux4_32 read_mux3(read_port3, R0_out, R1_out, R2_out, R3_out, read_select3); endmodule module and2 (out, in1, in2); output out; input in1, in2; wire temp; nand2$ n0(temp, in1, in2); nand2$ n1(out, temp, temp); endmodule module mux4_32 (out, in0, in1, in2, in3, s); output [31:0] out; input [31:0] in0, in1, in2, in3; input [1:0] s; mux2$ muxes[31:0](out, in0, in1, in2, in3, s); endmodule module mux4 (out, in0, in1, in2, in3, s) output out; input in0, in1, in2, in3; input [1:0] s; wire temp0, temp1; mux2$ mux0(temp0, in0, in1, s[0]); mux2$ mux1(temp1, in2, in3, s[0]); mux2$ mux2(out, temp0, temp1, s[1]); endmodule 3. Critical idea is that the next fetch address must use the results of the current fetch. That means either a long cycle time (unacceptable to Alpha designers) or a bubble in the pipeline. Alpha designers chose a bubble in the pipeline on every predicted taken branch. Bubble = bad cosequence. They could have added a BTB, indexed by the address of the branch instruction itself, so that during the cycle a branch is fetched from the ICache, the target is fetched from the BTB. If the prediction is taken this target is latched at the end of the fetch cycle. Ergo, no more bubbble. 4. SPEC is a measure of the average execution time of benchmarks, which is determined by instructions executed, IPC, and frequency. By normalizing out frequency, SPEC/MHz is effectively about cycles required to execute the program. Critical idea here is that IPC and frequency always work against each other; you optimize one at the expense of the other. Removing one from the formula distorts the metric. It makes it desirable to maximize IPC, independent of what that does to cycle time. That usually results in a bad design having a good figure of merit. If told that SPEC/MHz would be used to evaluate your design, your major design decision is to make cycle time as large as necessary to maximize IPC. 5. A split cache has the property that if the next PC points to the second half of a cache line, you get the second half of that line and the first half of the next line in one cycle. Critical idea is that x86 instructions starting toward the end of a cache line are likely to spill into the next cache line. With split-line cache, one fethes the whole instruction with a single fetch. Without, one requires two fetches to get the instruction. 6. Critical idea here that exceptions can happen in an instruction after some number of writes have already happened in THAT instruction. Other problems like flow dependencies are no different for this design decision than for other pipelines that don't have this design decision. The problem is what to do if such an exception happens. Two simple solutions. a. Test to be sure cycles 8,9, and 10 will execute to completion BEFORE doing the write in cycle 7. Thus, you know at the time you start the write in cycle 7 that the problem will not happen. b. save the old value of the locations written in cycles 7,8,9 before doing each corresponding write so that if an exception occurs you can return the old values to those locations before you take the exception. 7. Processor A runs at 5000 MIPS, Processor B runs at 1200 MIPS. However, the critical idea that is missing here is that since we have different ISAs, we have no idea what an instruction does or how much work 1 MIPS corresponds to. So, without knowing how many instructions in each of the compiled programs, we don't know which machine has the higher performance. 8. With 12 stages and 3 instructions fetched each cycle, you could have 36 instructions in flight (fetched, but not retired). Number 1 would throw away too much performance. Number 2 is not a good idea because it bases the prediction NOT on the recent behavior since the recent behavior is still pending. Two critical ideas: (a) we want to use recent behavior, and (b) the two-level predictor's prediction accuracy is high (more than 90% for the Pentium-Pro, and more than 95% for us in our more aggressive studies), so the speculatively updated BHR is likely to actually be correct. If it is incorrect, we will have trashed everything before we reach that point anyway, so the incorrect prediction there won't matter a lot. Ergo, Choice 3. 9. The question was what would you do to the ISA to improve performance if you did not have to worry about compatibility. So, all improvements to the microarchitecture didn't answer the question. They would probably go in regardless. Also, many of you invoked some very nice concepts we have covered in class as things we will see downstream, and I was delighted with that: trace cache, Blockstructured-ISA, hint bits, cache management instructions, for example. However, I believe all of those are secondary to three other pretty fundamental notions, IN ORDER: (a) One wants to be able to do wide issue. Multiple decode is hurt terribly by the variable length instruction. Ergo, fixed length, uniform decode. (b) path to memory is slow. Caches and cache management instructions will help. First clear step should be to increase size of register file. (c) baggage chews up transistors. Those opcodes, addressing modes, data types that have not been used in a very long time -- if we did not have to worry about compatibility -- should be trashed. By the way, if we do have to worry about compatibility, "bread&butter" kicks in and we implement, although keep them out of the critical path and implement them as cheaply as we can -- within reason.