Single-Cycle MIPS #1

charrrming·2022년 4월 14일

Computer Architecture

목록 보기
10/17

1. Introduction

micro-architecture: datapath, controller

single-cycle: 한 사이클에 하나의 명령어
pipeline: 실행하는 동안 여러 명령어가 오버랩, 실행이 여러 단계로 쪼개짐

cpu time: #insts * CPI * clock cycle time = #insts * cpi / f
(cpi는 명령어 1개에 필요한 평균 사이클 수)
- combitnaional logic: 아웃풋이 현재 인풋에 의해 바로 튀어나옴
					   ex) and, add, mux, alu                      
- sequential logic: 아웃풋은 현재 인풋 + 이전 인풋 같은 것들도 고려하여 결정
  				    -> flip-flop을 상태 정보를 저장하기 위해 사용
  
register store data in a circuit (by flip-flop)
-> 클락 신호가 언제 값을 업데이트 하는지 결정
	- rising edge(0->1), falling edge(1->0)
-> 데이터 인풋이 무엇을 업데이트 하는지 결정 (0 or 1)
-> write 컨트롤이 있다면 얘도 1이여야 업데이트

clk이 rising edge일 때 D 값이 있으면 Q에 복사, 다음 rising edge까지 값 유지
조합 회로는 두 state element(플립플롭) 사이에 위치
여러 조합 회로 중 가장 긴 애가 주파수를 결정
메모리에서 명령어, 데이터를 주고 받는 포트를 분리함

- behavioral modeling: 모듈을 있는 그대로 기술
- structural modeling: 이미 정의해놓은 module들을 가져다씀
microarchitecture는 datapath와 contorl로 구성

- datapath: data가 흘러가는 경로, used to operate or hold data
			ex) register file(hold data), ALU(operate), mux, memory
- contorl: datapath element를 제어, datapath가 어떻게 명령어를 실행해야하는지 알려줌
			ex) mux select, register enable, ALU control, memory write signals ...

2. Instruction Execution in CPU

1) Fetch: pc를 이용하여 명령어 주소를 제공받고 메모리에서 명령어를 fetch 한다.
2) Decoding: 명령어를 해석하고 operand를 읽는다.
3) Execution: 계산을 위해 ALU를 사용한다.
	ex) 산술/논리 연산, 접근하고자 하는 메모리 주소 계산, 분기하고자 하는 주소 계산
    
Next Fetch: pc <- pc+4

1) Instruction Fetch

외부에서 reset, clock 신호가 생성되어 들어온다. pc는 32비트 레지스터임. 
pc를 이용하여 메모리에 접근하여 32비트 명령어를 cpu로 fetch해온다. 
pc는 다음 명령어를 가져오기 위해 pc+4를 계산하여 다시 pc로 돌아옴.
module pcreg	(
			input clk,
            input reset,
            input [31:0] pcnext,
            output reg [31:0] pc);		// 입출력 포트 기술, 
            							   always 구문에 사용 시 reg 키워드 추가
            
	always @ (posedge clk, posedge reset)	// reset or clk이 0->1
    begin
      if	(reset) pc <= 32'h00000000;	// reset이 0->1이면 0으로 초기화
      else			pc <= pcnext;		// clk이 0->1이면 pcnext로 초기화
    end
    
    endmodule
module myadder	(
			input [31:0] a,
            input [31:0] b,
            output [31:0] y);
            
		assign y = a + b;	// 간단한 조합회로는 assign으로 기술
    
    endmodule
module mips	(
		input clk,
        input reset,
        output [31:0] pc);
        
wire [31:0] pecnext;	// 내부적으로 생성하고 사용

// pcreg 인스턴스화
  pcreg mips_pc (.clk (clk),
  			.reset (reset),
            .pc (pc),
            .pcnext(pcnext));

// adder 인스턴스화
  myadder pcadd4 (.a (pc),
  			.b (32'b100), // 상수 4
            .y (pcnext));
            
endmodule
// generic memory model in verilog


module mem	(input clk, MemWrite,
			 input [7:2] Address,	// word 단위로 읽을거라 하위 2비트는 버림
             input [31:0] WriteData,
             output [31:0] ReadData);
             
	reg [31:0] RAM[63:0];
    
// Memory Initialization
initial
begin
	$readmemh("memfile.dat",RAM);
end

// Memory Read
assign ReadData = RAM[Address[7:2]];	// 간단한 조합 회로

// Memory Write
always @(posedge clk)
begin
  if (MemWrite)
  	RAM[Address[7:2]] <= WriteData;
end

endmodule

2) Instruction Decoding (32비트 명령어 해석)

control logic은 opcode, fucnt 필드 읽어들임 -> datapath control 제공
operand는 명령어의 register number 또는 immediate field를 32비트로 확장해서 사용
module regfile	(input clk,
				 input RegWrite,
                 input [4:0] ra1, ra2, wa,
                 input [31:0] wd,
                 output [31:0] rd1, rd2);
                 
  reg [31:0] rf[31:0];	// 32비트 32개
  
  always @ (posedge clk)
    if (RegWrite) rf[wq] <= wd;
    
  assign rd1 = (ra1 != 0) ? rf[ra1] : 0;  // ra가 0이면 0, 아니면 rf[ra]
  assign rd2 = (ra2 != 0) ? rf[ra2] :0;
  
endmodule
module sign_zero_ext (input	sign_ext,
					  input [15:0] a,
                      output reg [31:0] y);
                      
  always @(*)	// 항상 들여다봄
  begin
    if (sign_ext) y <= {{16{a[15]}}, a};
    else		  y <= {{16{1'b0}}, a};
  end
  
endmodule

3-1) Instruction Execution #1

- R-type: 산술, 논리 연산 ex) add, sub, and, or
		  레지스터 파일에서 2개의 피연산자를 가져옴 rs, rt, rd
          
- I-type: 산술, 논리 연산 ex) addi, andi, ori
		  피연산자 1개는 레지스터 파일에서, 다른 1개는 상수 필드에서 가져옴
          rs(소스1), rt, immediate(소스2)
          
* destination register의 위치가 다르다 (rd vs rt)
  소스1은 동일하고, 소스2는 rt vs immediate, 목적지는 rd vs rt
module mux2 (input [31:0] d0,
			 input [31:0] d1,
             input s,	// ALUSrc (1이면 d1, 0이면 d0)
             output [31:0] y);
             
	assign y = s ? d1 : d0;

endmodule
// 범용적인 사용
module mux2 #(parameter WIDTH = 8)
		(input [WIDTH-1:0] d0, d1;
    	input s,
    	output [WIDTH-1:0] y);
    
    assign y = s ? d1 : d0;
endmodule

...

// 인스턴스화
mux2 #32 	mymux(
  .d0 (writedata),
  .d1 (signimm),
  .s (alusrc),
  .y (result));
  
...

3-2) Instruction Execution #2

lw, sw 명령어 -> I-type
opcode rs, rt, imm

3-3) Instruction Execution #3

beq, bne <- R-format
opcode rs, rt ,imm		# destination = (pc+4) + imm<<2

j <- J-format
opcode jump-target 		# destination = {(pc+4)[31:28], jump-target, 2'b00}

0개의 댓글