This shows you the differences between two versions of the page.
cn1:laboratoare:10 [2020/04/27 00:55] adina.smeu Adaugare laborator. |
— (current) | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ===== Laboratorul 10 - Recapitulare ===== | ||
- | |||
- | ==== 1. Obiective ==== | ||
- | |||
- | În acest laborator ne propunem să definitivăm conceptele învățate pe parcursul semestrului, reamintindu-ne etapele prin care am trecut în construirea UAL-ului și miniprocesorului nostru. Recapitularea va fi făcută sub forma unui joc pe echipe. Va exista un număr prestabilit de taskuri (întrebări sau cerințe), iar echipa care va răspunde corect prima va primi punctajul pe acea întrebare. La final, punctajul se va împărți între echipe, conform numărului de taskuri la care a răspuns în mod corect fiecare. | ||
- | |||
- | ==== 2. Taskuri ==== | ||
- | |||
- | Acestea vor fi făcute publice de asistent în timpul laboratorului, unul câte unul. Dacă taskul implică scriere de cod, acesta va fi verificat în simulator de către toți studenții înainte de trecerea la exercițiul următor. | ||
- | |||
- | <note warning> | ||
- | Echipa care răspunde la o întrebare este responsabilă și cu lămurirea întrebărilor din partea colegilor. Dacă echipa nu poate motiva, sau nu poate da un răspuns corect la o întrebare a colegilor/asistentului, atunci va primi punctaj parțial pe task. | ||
- | </note> | ||
- | |||
- | === Task 1 === | ||
- | |||
- | Avem următorul modul definit (un mux 2:1): | ||
- | |||
- | <code verilog> | ||
- | module mux2to1 (input [1:0] in, input sel, output out); | ||
- | assign out = in[sel]; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | Creați un modul care să reprezinte un mux 4:1 folosindu-vă de declarări repetate ale modului mux2to1. | ||
- | |||
- | === Task 2 === | ||
- | |||
- | Este implementat bine următorul modul? Dacă nu de ce? MyAnd este o poartă **and**, iar MyUal este un mini-ual care pentru sel == 0 face **and** pe intrări, iar pentru 1 face **or**. | ||
- | |||
- | * **2.a** | ||
- | <code verilog> | ||
- | module MyAnd(input a, input b, output c) | ||
- | assign c = a & b; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | * **2.b** | ||
- | <code verilog> | ||
- | module MyAnd (input a, input b, output c); | ||
- | reg regc; | ||
- | |||
- | always @(*) begin | ||
- | regc = a & b; | ||
- | end | ||
- | |||
- | assign c = regc; | ||
- | end | ||
- | </code> | ||
- | |||
- | * **2.c** | ||
- | <code verilog> | ||
- | module MyAnd(input a, input b, output c); | ||
- | if (a == 1 & b == 1) begin | ||
- | c = 1; | ||
- | end else begin | ||
- | c = 0; | ||
- | end | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | * **2.d** | ||
- | <code verilog> | ||
- | module MyUal(input a, input b, input sel, output out); | ||
- | always @(*) begin | ||
- | if (sel == 0) begin | ||
- | and(c,a,b); | ||
- | end else begin | ||
- | or(c,a,b); | ||
- | end | ||
- | end | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | * **2.e** | ||
- | <code verilog> | ||
- | module MyUal(input a, input b, input sel, output out); | ||
- | always @(*) begin | ||
- | if (sel == 0) begin | ||
- | assign out = a & b; | ||
- | end else begin | ||
- | assign out = a | b; | ||
- | end | ||
- | end | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | * **2.f** | ||
- | <code verilog> | ||
- | module MyUal(input a, input b, input sel, output out); | ||
- | always @(*) begin | ||
- | if (sel == 0) begin | ||
- | out = a & b; | ||
- | end else begin | ||
- | out = a | b; | ||
- | end | ||
- | end | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | * **2.g** | ||
- | <code verilog> | ||
- | module MyUal(input a, input b, input sel, output out); | ||
- | reg rego; | ||
- | |||
- | always @(*) begin | ||
- | rego <= a & b; | ||
- | if (sel == 1) begin | ||
- | rego <= a | b; | ||
- | end | ||
- | end | ||
- | |||
- | assign out = rego; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | * **2.h** | ||
- | <code verilog> | ||
- | module MyUal(input a, input b, input sel, output out); | ||
- | reg rego; | ||
- | |||
- | always @(*) begin | ||
- | rego = a & b; | ||
- | |||
- | if (sel == 1) begin | ||
- | rego = a | b; | ||
- | end | ||
- | end | ||
- | |||
- | assign out = rego; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | * **2.i** | ||
- | <code verilog> | ||
- | module MyUal(input a, input b, input sel, output out); | ||
- | reg rego; | ||
- | |||
- | always @(*) begin | ||
- | assign rego = (sel == 0) ? a & b : a | b; | ||
- | end | ||
- | |||
- | assign out = rego; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | * **2.j** | ||
- | <code verilog> | ||
- | module MyAnd(input[3:0] a, input[3:0] b, output[3:0] c); | ||
- | and(c, a, b); | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | === Task 3 === | ||
- | |||
- | Care dintre următoarele secvenţe de cod sunt greșite? De ce? | ||
- | |||
- | <code verilog> | ||
- | module MyAndXor(input a, input b, output oand, output oxor); | ||
- | assign oand = a & b; | ||
- | assign oxor = a ^ b; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | MyMod face operatia a ^ (a & b). | ||
- | |||
- | * **3.a** | ||
- | <code verilog> | ||
- | module Mymod(input a, input b, output c); | ||
- | wire o1; | ||
- | |||
- | MyAndXor (a, b, o1); | ||
- | MyAndXor(.oxor(c), .a(a), .b(o1)); | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | * **3.b** | ||
- | <code verilog> | ||
- | module Mymod(input a, input b, output c); | ||
- | wire o1, o2; | ||
- | |||
- | MyAndXor m1 (.a(a), .oand(o1), .oxor(o2)); | ||
- | MyAndXor m2 (o1, a, o2, c); | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | * **3.c** | ||
- | <code verilog> | ||
- | module Mymod(input a, input b, output c); | ||
- | reg o1, o2; | ||
- | |||
- | MyAndXor m1 (.a(a), .b(b), .oand(o1)); | ||
- | MyAndXor m2 (o1, a, o2, c); | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | === Task 4 === | ||
- | |||
- | Este vreo diferență între comportamentele următoarelor module? | ||
- | |||
- | <code verilog> | ||
- | module mux2to1 (input [1:0] in, input sel, output out); | ||
- | wire notsel, and1, and2; | ||
- | |||
- | not(notsel, sel); | ||
- | and(and1, in[0], notsel); | ||
- | and(and2, in[1], sel); | ||
- | or(out, and1, and2); | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | <code verilog> | ||
- | module mux2to1 (input [1:0] in, input sel, output out); | ||
- | assign out = (sel == 0) ? in[0] : in[1]; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | <code verilog> | ||
- | module mux2to1 (input [1:0] in, input sel, output out); | ||
- | reg rego; | ||
- | |||
- | always @(*) begin | ||
- | case (sel) | ||
- | 1’b0: rego =in[0]; | ||
- | 1’b1: rego =in[1]; | ||
- | default rego = 1’bx; | ||
- | endcase | ||
- | end | ||
- | |||
- | assign out = rego; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | === Task 5 === | ||
- | |||
- | Este vreo diferență între comportamentele următoarelor module? | ||
- | |||
- | <code verilog> | ||
- | module Mymod(input a, input b, output c); | ||
- | reg op1, op2; | ||
- | |||
- | initial begin | ||
- | op1 = 0; | ||
- | op2 = 0; | ||
- | end | ||
- | |||
- | always @(*) begin | ||
- | op1 = a & b; | ||
- | op2 = a ^ op1; | ||
- | end | ||
- | |||
- | assign c = op2; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | <code verilog> | ||
- | module Mymod(input a, input b, output c); | ||
- | reg op1, op2; | ||
- | |||
- | initial begin | ||
- | op1 = 0; | ||
- | op2 = 0; | ||
- | end | ||
- | |||
- | always @(*) begin | ||
- | op1 <= a & b; | ||
- | op2 <= a ^ op1; | ||
- | end | ||
- | |||
- | assign c = op2; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | <code verilog> | ||
- | module Mymod(input a, input b, output c); | ||
- | assign c = a ^ (a & b); | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | <code verilog> | ||
- | module Mymod(input a, input b, output c); | ||
- | reg op1, op2; | ||
- | |||
- | initial begin | ||
- | op1 = 0; | ||
- | op2 = 0; | ||
- | end | ||
- | |||
- | always @(a,b) begin | ||
- | op1 = a & b; | ||
- | op2 = a ^ op1; | ||
- | end | ||
- | |||
- | assign c = op2; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | === Task 6 === | ||
- | |||
- | Creați un debouncer în Verilog. | ||
- | |||
- | === Task 7 === | ||
- | |||
- | Faceți un automat Moore pentru următorul fsm implementat în Verilog: | ||
- | |||
- | <code verilog> | ||
- | `timescale 1ns / 1ps | ||
- | module fsm( | ||
- | input clk, | ||
- | input reset, | ||
- | input in, | ||
- | output out | ||
- | ); | ||
- | reg [1:0] currentState; | ||
- | reg [1:0] nextState; | ||
- | localparam STATE_Initial = 2'd0, | ||
- | STATE_1 = 2'd1, | ||
- | STATE_2 = 2'd2, | ||
- | STATE_3 = 2'd3; | ||
- | |||
- | assign out = (currentState == STATE_3); | ||
- | |||
- | always@ ( posedge clk ) begin | ||
- | if ( reset ) | ||
- | currentState <= STATE_Initial; | ||
- | else | ||
- | currentState <= nextState; | ||
- | end | ||
- | end | ||
- | |||
- | always@ ( * ) begin | ||
- | nextState = currentState; | ||
- | |||
- | case ( currentState ) | ||
- | STATE_Initial : begin | ||
- | if(in == 0) begin | ||
- | nextState = STATE_1; | ||
- | end else begin | ||
- | nextState = STATE_2; | ||
- | end | ||
- | end | ||
- | STATE_1 : begin | ||
- | if(in == 0) begin | ||
- | nextState = STATE_1; | ||
- | end else begin | ||
- | nextState = STATE_2; | ||
- | end | ||
- | end | ||
- | STATE_2 : begin | ||
- | if(in == 0) begin | ||
- | nextState = STATE_2; | ||
- | end else begin | ||
- | nextState = STATE_3; | ||
- | end | ||
- | end | ||
- | STATE_3 : begin | ||
- | if(in == 0) begin | ||
- | nextState = STATE_1; | ||
- | end else begin | ||
- | nextState = STATE_2; | ||
- | end | ||
- | end | ||
- | default: begin | ||
- | nextState = STATE_Initial; | ||
- | end | ||
- | endcase | ||
- | end | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | === Task 8 === | ||
- | |||
- | Este următorul modul o implementare corectă al unui sumator ripple carry? Modulul FullAdder este implementat corect și face ce îi spune numele. | ||
- | |||
- | <code verilog> | ||
- | module RippleCarry( | ||
- | input[7:0] A, | ||
- | input[7:0] B, | ||
- | input Cin, | ||
- | output[7:0] S, | ||
- | output Cout | ||
- | ); | ||
- | wire[6:0] C; | ||
- | |||
- | FullAdder fa0(.A(A[0]),.B(B[0]),.Cin(Cin),.S(S[0]),.Cout(C[0])); | ||
- | FullAdder fa4(.A(A[4]),.B(B[4]),.Cin(C[3]),.S(S[4]),.Cout(C[4])); | ||
- | FullAdder fa5(.A(A[5]),.B(B[5]),.Cin(C[4]),.S(S[5]),.Cout(C[5])); | ||
- | FullAdder fa6(.A(A[6]),.B(B[6]),.Cin(C[5]),.S(S[6]),.Cout(C[6])); | ||
- | FullAdder fa1(.A(A[1]),.B(B[1]),.Cin(C[0]),.S(S[1]),.Cout(C[1])); | ||
- | FullAdder fa2(.A(A[2]),.B(B[2]),.Cin(C[1]),.S(S[2]),.Cout(C[2])); | ||
- | FullAdder fa3(.A(A[3]),.B(B[3]),.Cin(C[2]),.S(S[3]),.Cout(C[3])); | ||
- | FullAdder fa7(.A(A[7]),.B(B[7]),.Cin(C[6]),.S(S[7]),.Cout(Cout)); | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | === Task 9 === | ||
- | |||
- | Este implementat corect următorul modul de FullAdder? | ||
- | |||
- | <code verilog> | ||
- | module FullAdder( | ||
- | input A, | ||
- | input B, | ||
- | input Cin, | ||
- | output S, | ||
- | output Cout | ||
- | ); | ||
- | wire S1, C1, C2; | ||
- | |||
- | HalfAdder ha1(.A(A),.B(B),.S(S1),.C(C1)); | ||
- | HalfAdder ha2(.A(S1),.B(Cin),.S(S),.C(C2)); | ||
- | xor(Cout, C1, C2); | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | === Task 10 === | ||
- | |||
- | Este implementat corect următorul modul de HalfAdder? | ||
- | |||
- | <code verilog> | ||
- | module HalfAdder( | ||
- | input A, | ||
- | input B, | ||
- | output S, | ||
- | output C | ||
- | ); | ||
- | assign S = A | B; | ||
- | assign C = A & B; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | === Task 11 === | ||
- | |||
- | Este implementat corect următorul modul de scăzător? | ||
- | |||
- | <code verilog> | ||
- | module Scazator( | ||
- | input[7:0] A, | ||
- | input[7:0] B, | ||
- | output[7:0] D, | ||
- | output Neg | ||
- | ); | ||
- | wire Cout; | ||
- | |||
- | Exercitiu_2_RippleCarry rc(.A(A),.B(~B),.Cin(1),.S(D),.Cout(Cout)); | ||
- | assign Neg = D[7]; | ||
- | |||
- | endmodule | ||
- | </code> | ||
- | |||
- | === Task 12 === | ||
- | |||
- | Este bine implementat următorul modul de FullAdder pentru CarryLookAhead? | ||
- | |||
- | <code verilog> | ||
- | module FullAdder( | ||
- | input A, | ||
- | input B, | ||
- | input Cin, | ||
- | output S, | ||
- | output P, | ||
- | output G | ||
- | ); | ||
- | wire S1, C1, C2; | ||
- | HalfAdder ha1(.A(A),.B(B),.S(S1)); | ||
- | HalfAdder ha2(.A(S1),.B(Cin),.S(S)); | ||
- | assign P = A | B; | ||
- | assign G = A ^ B; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | === Task 13 === | ||
- | |||
- | Care din implementările următoare ale operației **MUL** sunt corecte? | ||
- | |||
- | * **13.a** | ||
- | <code verilog> | ||
- | module POARTA_MUL( | ||
- | input[3:0] A, | ||
- | input[3:0] B, | ||
- | output[7:0] out | ||
- | ); | ||
- | |||
- | reg[8:0] P; | ||
- | reg[8:0] Aux; | ||
- | reg[8:0] S; | ||
- | reg[3:0] negA; | ||
- | reg var_aux; | ||
- | integer i; | ||
- | |||
- | always @(*) begin | ||
- | P = {4'b0000, B, 1'b0}; | ||
- | negA = ~A + 1; | ||
- | Aux = {A, 5'b00000}; | ||
- | S = {negA, 5'b00000}; | ||
- | |||
- | for (i = 0; i < 4; i = i + 1) begin | ||
- | case (P[1:0]) | ||
- | 2'b00: begin | ||
- | end | ||
- | 2'b01: begin | ||
- | P = P + Aux; | ||
- | end | ||
- | 2'b10: begin | ||
- | P = P + S; | ||
- | end | ||
- | 2'b11: begin | ||
- | end | ||
- | endcase | ||
- | |||
- | var_aux = P[8]; | ||
- | P = P >> 1; | ||
- | P[8] = var_aux; | ||
- | end | ||
- | end | ||
- | |||
- | assign out = P[8:1]; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | * **13.b** | ||
- | <code verilog> | ||
- | module POARTA_MUL( | ||
- | input[3:0] A, | ||
- | input[3:0] B, | ||
- | output[7:0] out | ||
- | ); | ||
- | |||
- | reg[8:0] P; | ||
- | reg[8:0] Aux; | ||
- | reg[8:0] S; | ||
- | reg[3:0] negA; | ||
- | reg var_aux; | ||
- | integer i; | ||
- | |||
- | always @(*) begin | ||
- | P = {4'b0000, B, 1'b0}; | ||
- | negA = ~A + 1; | ||
- | Aux = {A, 5'b00000}; | ||
- | S = {negA, 5'b00000}; | ||
- | |||
- | for (i = 0; i < 4; i = i + 1) begin | ||
- | case (P[1:0]) | ||
- | 2'b00: begin | ||
- | end | ||
- | 2'b01: begin | ||
- | P = P + Aux; | ||
- | end | ||
- | 2'b10: begin | ||
- | P = P + S; | ||
- | end | ||
- | 2'b11: begin | ||
- | end | ||
- | endcase | ||
- | |||
- | P = P >>> 1; | ||
- | end | ||
- | end | ||
- | |||
- | assign out = P[8:1]; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | * **13.c** | ||
- | <code verilog> | ||
- | module POARTA_MUL( | ||
- | input[3:0] A, | ||
- | input[3:0] B, | ||
- | output[7:0] out | ||
- | ); | ||
- | |||
- | reg[8:0] P; | ||
- | reg[8:0] Aux; | ||
- | reg[8:0] S; | ||
- | reg[3:0] negA; | ||
- | reg var_aux; | ||
- | integer i; | ||
- | |||
- | always @(*) begin | ||
- | P = {4'b0000, B, 1'b0}; | ||
- | negA = ~A + 1; | ||
- | Aux = {A, 5'b00000}; | ||
- | S = {negA, 5'b00000}; | ||
- | |||
- | for (i = 0; i < 4; i = i + 1) begin | ||
- | case (P[1:0]) | ||
- | 2'b00: begin | ||
- | end | ||
- | 2'b01: begin | ||
- | P = P + Aux; | ||
- | end | ||
- | 2'b10: begin | ||
- | P = P + S; | ||
- | end | ||
- | 2'b11: begin | ||
- | end | ||
- | endcase | ||
- | |||
- | P = P >> 1; | ||
- | end | ||
- | end | ||
- | |||
- | assign out = P[8:1]; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | * **13.d** | ||
- | <code verilog> | ||
- | module POARTA_MUL( | ||
- | input[3:0] A, | ||
- | input[3:0] B, | ||
- | output[7:0] out | ||
- | ); | ||
- | |||
- | reg[8:0] P; | ||
- | reg[8:0] Aux; | ||
- | reg[8:0] S; | ||
- | reg[3:0] negA; | ||
- | reg var_aux; | ||
- | integer i; | ||
- | |||
- | always @(*) begin | ||
- | P = {4'b0000, B, 1'b0}; | ||
- | negA = ~A + 1; | ||
- | Aux = { 5'b00000, A}; | ||
- | S = {,5'b00000, negA}; | ||
- | |||
- | for (i = 0; i < 4; i = i + 1) begin | ||
- | case (P[1:0]) | ||
- | 2'b00: begin | ||
- | end | ||
- | 2'b01: begin | ||
- | P = P + Aux; | ||
- | end | ||
- | 2'b10: begin | ||
- | P = P + S; | ||
- | end | ||
- | 2'b11: begin | ||
- | end | ||
- | endcase | ||
- | |||
- | var_aux = P[8]; | ||
- | P = P >> 1; | ||
- | P[8] = var_aux; | ||
- | end | ||
- | end | ||
- | |||
- | assign out = P[8:1]; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | * **13.e** | ||
- | <code verilog> | ||
- | module POARTA_MUL( | ||
- | input[3:0] A, | ||
- | input[3:0] B, | ||
- | output[7:0] out | ||
- | ); | ||
- | |||
- | reg[8:0] P; | ||
- | reg[8:0] Aux; | ||
- | reg[8:0] S; | ||
- | reg[3:0] negA; | ||
- | reg var_aux; | ||
- | integer i; | ||
- | |||
- | always @(*) begin | ||
- | P = {4'b0000, B, 1'b0}; | ||
- | negA = ~A + 1; | ||
- | Aux = {negA, 5'b00000}; | ||
- | S = {A, 5'b00000}; | ||
- | |||
- | for (i = 0; i < 4; i = i + 1) begin | ||
- | case (P[1:0]) | ||
- | 2'b00: begin | ||
- | end | ||
- | 2'b01: begin | ||
- | P = P + Aux; | ||
- | end | ||
- | 2'b10: begin | ||
- | P = P + S; | ||
- | end | ||
- | 2'b11: begin | ||
- | end | ||
- | endcase | ||
- | |||
- | var_aux = P[8]; | ||
- | P = P >> 1; | ||
- | P[8] = var_aux; | ||
- | end | ||
- | end | ||
- | |||
- | assign out = P[8:1]; | ||
- | endmodule | ||
- | </code> | ||
- | |||
- | ==== 3. Problemă examen ==== | ||
- | |||
- | În vederea pregătirii problemei pentru examen (a.k.a proba numita “problema”), trebuie să aveți în vedere cele 2 mari tipuri de probleme prezentate la curs: | ||
- | * BRANCH PREDICTOR | ||
- | * DATA HAZARDS IN PIPELINE | ||
- | |||
- | Pentru ambele tipuri de probleme, găsiți teoria necesara în cursul de CN de pe moodle. | ||
- | *Pentru primul tip de problema, pe lângă exemplele din curs, atașăm mai jos un model complet de redactare a acestui subiect. | ||
- | *Pentru tipul al doilea, aveți numeroase exemple (figuri) în curs care ilustrează cum sunt rezolvate aceste tipuri de hazarde. | ||
- | In plus, puteți consulta următoarele link-uri: | ||
- | * [[https://en.wikipedia.org/wiki/Branch_predictor#One-level_branch_prediction|Branch predictor]] | ||
- | * [[http://web.cs.iastate.edu/~prabhu/Tutorial/PIPELINE/hazards.html|Hazard in pipeline]] | ||
- | * [[http://web.cs.iastate.edu/~prabhu/Tutorial/PIPELINE/dataHaz.html|Data hazards in pipeline]] | ||
- | * [[https://en.wikipedia.org/wiki/Amdahl%27s_law|Amdahl's law]] | ||
- | * [[https://en.wikipedia.org/wiki/Speedup|Speedup]] | ||
- | |||
- | <note tip> | ||
- | **ATENȚIE!** Vă rugăm ca în redactarea problemelor să folositi notațiile/convențiile prezentate la curs și la laborator. | ||
- | </note> | ||
- | |||
- | == Exemplu problemă BRANCH PREDICTOR == | ||
- | |||
- | Fie următorul cod în assembly (simplificat): | ||
- | <code asm> | ||
- | mov ax, $a | ||
- | mov bx, $b | ||
- | |||
- | _while: | ||
- | cmp ax, bx ; ax ? bx | ||
- | |||
- | jg _greater ; ax > bx ? | ||
- | jl _less ; ax < bx ? | ||
- | je _pwp ; ax == bx ? | ||
- | |||
- | jmp _while | ||
- | |||
- | _greater: | ||
- | sub ax, bx ; ax = ax - bx | ||
- | jmp _while | ||
- | |||
- | _less: | ||
- | sub bx, ax ; bx = bx - ax | ||
- | jmp _while | ||
- | |||
- | _pwp: ;se afiseaza conținutul lui ax | ||
- | |||
- | </code> | ||
- | |||
- | <note tip> | ||
- | **Observații** | ||
- | - Recapitulare assembly | ||
- | * ''jmp'' este instrucțiune ce implementează un salt necondiționat | ||
- | * ''jg'', ''jl'', ''je'' sunt instrucțiuni ce implementează salturi CONDITIONATE (doar pentru acestea Branch Predictorul poate optimiza lucruri) | ||
- | * ''add''/''sub'', ''cmp'' sunt folosite pentru adunare/scadere și comparare | ||
- | * ''mov'' este instrucțiunea care copiază în destinație (primul operand), conținutul sursei (al doilea operand) | ||
- | - În acest exemplu, instrucțiunile au fost explicate, atat în această secțiune cat și în cod (prin comentarii). Ne așteptăm ca la examen să știți ce fac instrucțiunile: ''add''/''sub'', ''je''/''jg''/''jl''/''jmp'', ''cmp'', ''inc'', load (''ld'') /store (''st'')/''mov''. De asemenea, ce este un registru (ex. ''ax''/''eax'', ''bx''/''ebx'', ''cx''/''ecx'', ''dx''/''edx'' sau ''r1'', ''r2'', ''r3'' …), cum luăm valoarea de la o adresa (''b''), sintaxa pentru instrucțiuni (ex. ''mov reg destinație reg_sursa''). | ||
- | </note> | ||
- | |||
- | Avem 2 procesoare, fiecare având frecvența de 1Ghz, care execută acest cod, procesoarele A și B. Metoda de branch prediction folosită de fiecare este: | ||
- | |||
- | **A.** 1-bit counter (taken/not taken) | ||
- | |||
- | **B.** 2-bit counter (strongly taken/weak taken/weak not taken/strongly not taken) | ||
- | |||
- | Ambele pornesc cu o abordare pesimistă, counterul/state machine-ul fiecăreia având starea inițială pentru procesorul A not taken și pentru B strongly not taken. De altfel, ambele implementează un branch predictor global, astfel că există un singur counter/state machine global, pentru toate branch-urile. Se știu numărul de cicli de ceas pentru fiecare tip de instrucțiune: mov - 1 ciclu, cmp - 1 ciclu, sub - 1 ciclu, branch - 20 cicli (dacă nu a fost prezis corect) sau 2 cicli (dacă a fost prezis corect). | ||
- | |||
- | Se cer următoarele: | ||
- | |||
- | **1.** Pentru input-ul a=26 și b=34 să se evidențieze prin ce stări trec branch-predictor-ele celor 2 procesoare, semnalându-se și care branch-uri au fost prezise corect, respectiv incorect. (4p) | ||
- | |||
- | **2.** Să se calculeze timpul de rulare al programului pe cele 2 procesoare, pentru input-ul de la punctul 1. (3p) | ||
- | |||
- | **3.** FIe un procesor C, cu frecvență de 1Ghz, care are aceeași metoda de branch prediction pe 2 biți ca procesorul B, implementând însă un branch predictor local (câte un counter/state machine pentru fiecare branch). Execută procesorul C codul dat mai repede decât procesorul A sau B, pentru input-ul de la punctul 1? Argumentați. Care este speed-up față de B? (3p) | ||
- | |||
- | <spoiler Rezolvare> | ||
- | [[https://docs.google.com/spreadsheets/d/1VR7XeqPSfzxMAJiE3ClhReDBkI_NgrWj0_gOplrMnFU/edit#gid=0|Rezolvare problema]] | ||
- | </spoiler> | ||
- | |||
- | ==== 4. Model colocviu ==== | ||
- | |||
- | Colocviul va fi scris (nu există probă practică pe calculator). Acesta este closed book. Regulamentul se află [[https://ocw.cs.pub.ro/courses/cn1/regulament|aici]]. | ||
- | |||
- | Formatul acestuia va fi următorul: | ||
- | * 4 subiecte de câte 2.5 puncte | ||
- | * Timp de lucru 50 min. Fără documentații. Totul se redactează pe foaie. | ||
- | * Colocviul verifică toate cunoștințele din materia predată la laborator, printre care și noțiuni de Verilog (veți scrie cod pe foaie). | ||
- | |||
- | Exemple de subiecte: | ||
- | * Subiectul 1 va fi o întrebare de teorie/o comparație/o definiție/un algoritm/o idee/un principiu/etc din materia de laborator. | ||
- | * Subiectul 2 poate sa ceară corectarea unui cod Verilog dat, menționarea unor concepte + exemplificare prin cod Verilog (ex. semnătură module, instanțiere module), etc. | ||
- | * Subiectul 3 va presupune scrierea unui modul/o secvență de cod Verilog. Acesta va fi asemănător cu exercițiile deja codate în laboratoare. | ||
- | * Subiectul 3 va presupune scrierea unui modul/o secvență de cod Verilog. Acesta va fi asemănător cu exercițiile deja codate în laboratoare. | ||
- | * Indicii 1, 2, 3, 4 sunt orientativi. (Ex. Subiectul 1 poate sa fie FSM Moore, iar subiectul 4 poate sa fie o întrebare. Ați prins ideea. :D) | ||
- | |||
- | Mai jos puteți consulta un model. | ||
- | |||
- | <code verilog> | ||
- | Vineri 10-12 26.05.2017 | ||
- | Colocviu CN1 | ||
- | (2.5p) Care este diferența dintre un half adder și un full adder? De ce avem nevoie de ambele? | ||
- | |||
- | |||
- | (2.5p) Implementați în Verilog un sumator pe 2 biți. Sumatorul NU are intrare de carry. NU puteți folosi | ||
- | operatorul +. | ||
- | |||
- | (2.5p) Pornind de la următoarea descriere la nivel procedural al unui modul în Verilog scrieți descrierea | ||
- | la nivel structural al aceluiași modul. | ||
- | module foo(input a, input b, input c, output reg out); | ||
- | always @(*) begin | ||
- | case (b) | ||
- | 1’b0: begin | ||
- | out <= a | c; | ||
- | end | ||
- | 1’b1: begin | ||
- | out <= 0; | ||
- | end | ||
- | endcase | ||
- | end | ||
- | endmodule | ||
- | |||
- | (2.5p) Creați diagrama pentru un automat cu stări de tip Moore care primește intrările '1' și '0' și are ca | ||
- | ieșire "da" sau "nu". Automatul trebuie să recunoască secvențe care conțin subsecvența "1010". | ||
- | Exemplu: intrare "1010" => ieșire "da"; intrare "111010" => ieșire "da"; intrare "101001" => ieșire "da"; | ||
- | intrare "1111" => ieșire "nu"; intrare "1011" => ieșire "nu"; intrare "10010" => ieșire "nu". | ||
- | </code> | ||
- | |||
- | |||
- | ==== 5. Linkuri utile ==== | ||
- | |||
- | [[https://ocw.cs.pub.ro/courses/cn1]] | ||