tip.crowny.org 기록 — 2026-04-03 대상 독자: Crowny 팀원, 다른 클로드 세션, 한선씨 라이브러리 개발자
CrownyTVM v10.0 / crownyc v9.6→10.0 업데이트 이후 ISA729 옵코드 공간에 세 가지 버그가 발견됐다. 이 문서는 버그 원인, 수정 내용, 현재 옵코드 배치를 기록한다.
증상
삼진누산, 제로스킵, 방사전파, 삼진벡터, 희소행렬곱, 삼진합성곱, 삼진풀링을
463~469번에 배정했는데, 이 범위는 이미 TREE_INORDER(463)~HEAP_PUSH(469)가 선점하고 있었다.
트리/힙 자료구조 사용 시 신경망 명령이 실행되는 사고 발생.
원인 AI 텐서 연산을 추가할 때 기존 ISA729 배치표를 확인하지 않음.
수정
| 키워드 | 이전 | 이후 |
|---|---|---|
삼진누산 | 463 | 741 |
제로스킵 | 464 | 742 |
방사전파 | 465 | 743 |
삼진벡터 | 466 | 744 |
희소행렬곱 | 467 | 745 |
삼진합성곱 | 468 | 746 |
삼진풀링 | 469 | 747 |
opcode.rs에 상수 추가, engine.rs에 핸들러 구현.증상
삼진인코딩(n)이 균형3진이 아닌 일반 3진수(0,1,2)를 반환. 음수는 부호 반전으로 처리해 디코딩이 깨졌다.
원인
c// 구형 — 불균형 (0,1,2)
for i in (0..6).rev() { trits[i] = v % 3; v /= 3; }
if neg { for t in &mut trits { *t = match *t { 0=>0, 1=>2, _=>1 }; } }
균형3진은 각 자리가 -1, 0, +1(Ta/Om/Ti)이어야 한다.수정
rust// 균형3진 알고리즘: 나머지 2 → -1, 몫+1 carry
for i in (0..6).rev() {
let mut r = n % 3;
n /= 3;
if r == 2 { r = -1; n += 1; }
else if r == -2 { r = 1; n -= 1; }
trits[i] = r as i8;
}
TRIT_DECODE도 acc * 3 + t.signum() 방식으로 수정.
TRIT_MUL: 단순 곱셈 → signum 정규화 후 곱 (trit × trit ∈ {-1, 0, +1}).
검증
삼진디코딩(삼진인코딩(10)) = 10 ✓
삼진디코딩(삼진인코딩(-5)) = -5 ✓
삼진디코딩(삼진인코딩(0)) = 0 ✓
삼진디코딩(삼진인코딩(42)) + 삼진디코딩(삼진인코딩(-42)) = 0 ✓
증상
다수결(+1, -1, 0) → 항상 Ti 또는 Ta만 반환. Om(0) 출력 불가.
원인
rust// 구형 — 이진 다수결 로직
let cnt = [a,b,c].iter().filter(|&&t| t == Trit::Ti).count();
self.stack.push(Value::Trit(if cnt >= 2 { Trit::Ti } else { Trit::Ta }));
수정
rust// 균형3진: 합의 부호
let sum = a.val() + b.val() + c.val(); // -3 ~ +3
self.stack.push(Value::Trit(
if sum > 0 { Trit::Ti }
else if sum < 0 { Trit::Ta }
else { Trit::Om }
));
진리표:
| a | b | c | 합 | 결과 |
|---|---|---|---|---|
| +1 | +1 | +1 | +3 | Ti |
| +1 | +1 | 0 | +2 | Ti |
| +1 | -1 | 0 | 0 | Om |
| -1 | -1 | -1 | -3 | Ta |
증상
나중에 추가된 셀 DB 연산이 기존 셀 연산 번호를 덮어쓰고, 큐브생성과 문서주석이 모두 TIME_SECOND(624) 자리를 차지.
충돌 목록 및 해결
| 옵코드 | 기존 (opcode.rs 기준) | 이전 hanseonc | 수정 후 |
|---|---|---|---|
| 624 | TIME_SECOND (초 반환) | 큐브생성, 문서주석 이중 충돌 | 큐브생성→751, 문서주석→752 |
| 703 | CELL_EVID (셀근거) | 셀리트릿 충돌 | 셀리트릿→748 |
| 704 | CELL_DECIDE (셀결정) | 셀시냅스 충돌 | 셀시냅스→749 |
| 706 | CELL_PATH (셀경로) | 셀통계 충돌 | 셀통계→750 |
opcode.rs가 정답. hanseonc_high.c의 구형 항목을 옮김.741 TMAC 삼진누산(가중치[], 입력[]) → MAC 합계
742 ZSKP 제로스킵(배열) → [비제로합, 0개수]
743 RBCS 방사전파(값, n) → [값; n]
744 TVEC 삼진벡터(a[], b[]) → 균형3진 내적
745 SMAT 희소행렬곱(a_flat, b_flat, cols)
746 TCONV 삼진합성곱(input, kernel) → 1D valid conv
747 TPOOL 삼진풀링(arr, stride) → max pool
748 CELL_RETREAT 셀리트릿(셀맵) → 신뢰도 -0.1
749 CELL_SYNAPSE 셀시냅스(from, to) → 시냅스 연결
750 CELL_STATS 셀통계() → [셀수, 연결수, 평균신뢰도]
751 CUBE_NEW 큐브생성() → [0×27] trit 배열
752 DOC_COMMENT 문서주석(텍스트) → 런타임 무시
703 CELL_EVID 셀근거(셀, 근거값)
704 CELL_DECIDE 셀결정(셀) → Claim
705 CELL_SEARCH 셀검색(패턴)
706 CELL_PATH 셀경로(from, to) → 배열
707 CELL_SUBGRAPH 셀부분그래프(루트, 깊이)
708 CELL_EXPORT 셀내보내기(셀) → JSON
709 CELL_IMPORT 셀가져오기(JSON) → 셀
아래는 같은 opcode를 가리키는 정상 별칭이다. 충돌 아님.
| 별칭 A | 별칭 B | opcode | 비고 |
|---|---|---|---|
비트곱 | 트릿곱 | 90 | trit-wise MIN |
비트합 | 트릿합 | 91 | trit-wise MAX |
소켓보내기 | 소켓전송 | 375 | SOCK_SEND |
소켓받기 | 소켓수신 | 376 | SOCK_RECV |
버퍼잘라 | 버퍼자르기 | 395 | BUF_SLICE |
파일쓰기 | 쓰기 | 620 | FILE_WRITE |
파일덧쓰기 | 덧쓰기 | 622 | FILE_APPEND |
| 파일 | 역할 |
|---|---|
/Users/ef/Downloads/CrownyTVM/src/vm/opcode.rs | 정답 opcode 상수. 충돌 기준표 |
/Users/ef/Downloads/CrownyTVM/src/vm/engine.rs | VM 핸들러. TRIT_, CELL_, TMAC~TPOOL |
/Users/ef/CrownyOS/crownyc/hanseonc_high.c | 고수준 컴파일러 키워드→opcode 매핑 |
/Users/ef/CrownyOS/crownyc/pkg/hanseonc_high.c | npm 패키지 사본 (동일하게 수정) |
opcode.rs에서 빈 번호 확인 (현재 최고: 752)opcode.rs에 상수 추가 + name() 함수에 등록engine.rs match 블록에 핸들러 추가hanseonc_high.c 키워드 테이블에 한글명 추가pkg/hanseonc_high.c에 동일하게 반영cargo test 통과 확인cargo test (CrownyTVM) — 219개 전부 통과
- vm_tests: 67개 (균형3진 encode/decode 5, majority 3 포함)
- trit_tests: 43개
- compiler_tests: 37개
- 기타: 72개
작성: Claude Sonnet 4.6 — 2026-04-03