본문으로 건너뛰기
code0.HDL

값으로 다루는 rule

rule을 Rules 값으로 만들어 addRules로 모듈에 추가하고, elaboration에서 한 번 일어나는 호출과 추가된 rule이 실행되는 여러 사이클을 구분합니다.

이 장에서 배울 내용

  • Rules 값을 반환하는 함수를 쓰고 addRules로 모듈에 추가할 수 있습니다
  • 추가된 rule 하나에 대해 elaboration에서 일어나는 일과 시뮬레이션에서 일어나는 일을 구분할 수 있습니다
  • Rules 값을 만들고 추가하지 않아 카운터가 움직이지 않는 상황을 진단할 수 있습니다
이 장에서 배우는 개념
  • 값으로 다루는 rule
먼저 알아야 할 개념

1. rules 블록은 값입니다

지금까지 쓴 rule은 모두 모듈 본문에 직접 쓴 것이었습니다. BSV에서는 rule을 값으로 만들어 elaboration 중에 주고받다가 모듈에 추가할 수도 있습니다. rules ... endrules 블록의 타입은 Rules이고, addRules가 그 안의 rule을 현재 모듈에 추가합니다.

형식

rules
  rule 이름 (조건);
    Action;
  endrule
endrules

addRules(Rules_식);

Rules 값은 설계를 elaboration하는 동안에는 다른 값과 똑같이 다룹니다. 함수가 반환할 수 있고, 변수에 담을 수 있고, 반복문이 반복마다 하나씩 만들 수도 있습니다. 다만 값 자체는 실행되지 않습니다. addRules로 모듈에 추가하기 전까지 Rules 안의 rule은 한 번도 실행되지 않습니다.

단계Rules 값에 일어나는 일
elaborationrules ... endrules 식이 평가되고, 이 값을 반환하는 함수가 호출되며, addRules가 결과를 elaboration 중인 모듈에 추가합니다
시뮬레이션추가된 rule은 모듈 본문에 직접 쓴 rule과 똑같이 동작합니다. 매 사이클 조건이 참인 rule이 실행될 수 있습니다

이 구분 때문에 함수 호출 한 번이 여러 사이클에 걸쳐 동작하는 하드웨어가 됩니다. 호출은 한 번 일어나고, 반환된 rule은 그때부터 모듈의 일부입니다.

확인 문제

함수가 Rules 값을 반환하고 모듈이 그 값으로 addRules를 호출합니다. 이 함수는 몇 번 실행될까요?

답

2. 증가 rule 추가하기

RuleExpression.bsv의 incrementRules는 레지스터를 3까지 증가시키는 rule을 반환합니다. incrementRules에서 인자로 받는 레지스터와 반환되는 Rules 안의 조건을 먼저 확인하세요. 그다음 rule을 추가하고 별도의 finish를 가진 mkTop을 읽으세요.

시뮬레이션은 count = 0에서 시작합니다. 추가된 rule은 시작 상태가 0, 1, 2인 사이클에 실행되어 1, 2, 3을 예약합니다. 시작 상태가 3이 되면 count < 3이 거짓이 되고 finish가 실행될 수 있습니다.

실행하기 전에 예측해 보세요.

  1. finish는 count를 얼마로 출력할까요?
  2. incrementRules는 몇 번 호출되고, 반환된 rule은 몇 번 실행될까요?
RuleExpression.bsv
package RuleExpression;

function Rules incrementRules(Reg#(UInt#(4)) count);
  // 이 함수는 elaboration 중에 재사용할 수 있는 Rules 값을 만든다.
  return rules
    rule increment (count < 3);
      count <= count + 1;
    endrule
  endrules;
endfunction

(* synthesize *)
module mkTop(Empty);
  Reg#(UInt#(4)) count <- mkReg(0);

  // addRules가 반환된 rule을 이 모듈에 추가한다.
  addRules(incrementRules(count));

  rule finish (count == 3);
    $display("count=%0d", count);
    $finish(0);
  endrule
endmodule

endpackage

이 개념 실습하기

다음 단계로 짧은 BSV 문제에 이 개념을 적용해 보세요.

결과 확인. finish는 count=3을 출력합니다. 이 한 줄에 시간 단위 두 개가 드러납니다. incrementRules(count)는 모듈을 elaboration할 때 한 번 실행되었고, 반환된 rule은 세 사이클에 걸쳐 실행되었습니다.

직접 바꿔 보세요.

  1. 조건을 count < 2로 바꾸어 보세요. rule은 2에서 멈추고 finish는 정확히 3을 기다리므로 실행할 수 있는 rule이 남지 않습니다. 아무것도 출력되지 않고 $finish에도 도달하지 않으므로, 실행 시간 제한에 걸려야 실행이 끝납니다.
  2. 조건을 count <= 3으로 바꾸어 보세요. 시작 상태 3에서 두 rule이 같은 사이클에 실행됩니다. finish가 3을 출력하고 시뮬레이션을 끝내는 동안 increment는 4를 예약합니다. 출력은 여전히 count=3이므로 이 테스트벤치로는 초과를 볼 수 없습니다. 한 사이클 더 관찰하는 테스트가 있어야 드러납니다.

함수가 반환한 rule도 모듈의 나머지 상태를 함께 사용하므로, 모듈에 직접 쓴 rule과 같은 방식으로 스케줄링됩니다. 어떤 rule이 한 사이클을 공유하는지는 상태를 공유하는 rule 장의 관계표를 보세요.

레지스터마다 rule을 하나씩 추가하는 반복문에 두 시간 축을 적용해 보세요.

Vector#(3, Reg#(UInt#(4))) counts <- replicateM(mkReg(0));
Reg#(UInt#(8)) cycle <- mkReg(0);

for (Integer i = 0; i < 3; i = i + 1)
  addRules(incrementRules(counts[i]));

rule tick;
  cycle <= cycle + 1;
endrule

rule finish (counts[0] == 3 && counts[1] == 3 && counts[2] == 3);
  $display("cycle=%0d counts=%0d %0d %0d", cycle, counts[0], counts[1], counts[2]);
  $finish(0);
endrule

확인 문제

모듈에는 증가 rule이 몇 개 있고, finish는 무엇을 출력할까요?

답

3. 자주 하는 실수

3.1 Rules를 만들고 추가하지 않기

// 잘못된 코드: Rules 값을 만들고 버립니다
Rules r = incrementRules(count);

// 바른 코드: 모듈에 rule을 추가합니다
addRules(incrementRules(count));

확인 문제

RuleExpression.bsv의 addRules 줄을 Rules r = incrementRules(count); 로 바꾸면 bsc와 시뮬레이션에서 무엇이 보일까요?

답

잘못된 코드도 컴파일되지만 증가 rule이 존재하지 않으므로 count는 바뀌지 않습니다. 카운터가 멈춰 있으면 조건, 호출한 method의 준비 조건, addRules 호출 여부를 차례로 확인하세요.

4. 정리

질문답
rules ... endrules의 타입은 무엇인가요?Rules
무엇이 모듈에 추가하나요?elaboration 중인 모듈에서 호출한 addRules(Rules_식)
Rules를 만드는 함수는 언제 실행되나요?elaboration 중에 한 번
그 안의 rule은 언제 실행되나요?시뮬레이션에서 guard, method의 준비 조건, 스케줄링이 허용할 때
addRules를 빠뜨리면 어떻게 되나요?값이 버려집니다. 컴파일은 되지만 그 rule은 존재하지 않습니다

5. 확인 문제

  1. Rules 식 예제에서 elaboration 중에 일어나는 일과 시뮬레이션 중에 일어나는 일은 각각 무엇일까요?

    정답 보기

    elaboration 중에는 incrementRules(count)가 한 번 실행되고 addRules가 반환된 rule을 추가합니다. 시뮬레이션 중에는 그 rule이 조건 count < 3이 참인 사이클마다 실행됩니다.

  2. 조건을 count <= 3으로 바꾸어도 3이 출력됩니다. 이 결과로 알 수 있는 테스트벤치의 한계는 무엇일까요?

    정답 보기

    finish가 3을 출력하고 멈추는 사이클에 증가 rule도 한 번 더 실행되어 4를 예약합니다. 테스트벤치가 너무 일찍 끝나서 초과를 관찰하지 못하므로, 출력이 맞아 보여도 경계 조건이 옳다는 증거가 되지 않습니다.

  3. 한 모듈에서 레지스터를 달리하여 incrementRules를 두 번 호출하고 각 결과를 addRules에 넘기면 모듈에는 rule이 몇 개 있을까요?

    정답 보기

    두 개입니다. 호출마다 elaboration 중에 자기 Rules 값이 만들어지고, addRules가 각각 그 안의 rule을 추가합니다. 같은 함수에서 나왔을 뿐 서로 다른 rule입니다.

확인 지점

예제를 실행해 예측과 비교합니다

참고 자료

참고한 자료의 라이선스와 고지