진실 표를 vpternlog
명령 시퀀스로 변환하는 방법.
- 진리표를 논리적 공식으로 변환합니다. 예 : Logic Friday를 사용합니다.
- 논리 공식을 Synopsys 방정식 형식 (.eqn)으로 저장하십시오. 예를 들어, 6 개의 입력 노드 A ~ F, 2 개의 출력 노드 F0 및 F1 및 다소 복잡한 (부 논리가 아닌) 부울 함수가있는 네트워크를 사용했습니다. BF_Q6.eqn의
내용 :
INORDER = A B C D E F;
OUTORDER = F0 F1;
F0 = (!A*!B*!C*!D*!E*F) + (!A*!B*!C*!D*E*!F) + (!A*!B*!C*D*!E*!F) + (!A*!B*C*!D*!E*!F) + (!A*B*!C*!D*!E*!F) + (A*!B*!C*!D*!E*!F);
F1 = (!A*!B*!C*!D*E) + (!A*!B*!C*D*!E) + (!A*!B*C*!D*!E) + (!A*B*!C*!D*!E) + (A*!B*!C*!D*!E);
- 사용 : 버클리 검증 및 합성 연구 센터에서 "ABC를 순차 합성 및 검증을위한 시스템". Windows 버전을 사용했습니다. ABC here을 받으십시오. ABC에서
나는 실행
abc 01> read_eqn BF_Q6.eqn
abc 02> choice; if -K 3; ps
abc 03> lutpack -N 3 -S 3; ps
abc 04> show
abc 05> write_bench BF_Q6.bench
당신은 더 나은 결과를 얻을 수 choice; if -K 3; ps
여러 번 실행해야 할 수도 있습니다.
문제가 남아
__m512i not(__m512i a) { return _mm512_xor_si512(a, _mm512_set1_epi32(-1)); }
__m512i binary(__m512i a, __m512i b, int i) {
switch (i)
{
case 0: return _mm512_setzero_si512();
case 1: return not(_mm512_or_si512(a, b));
case 2: return _mm512_andnot_si512(a, b);
case 3: return not(a);
case 4: return _mm512_andnot_si512(b, a);
case 5: return not(b);
case 6: return _mm512_xor_si512(a, b);
case 7: return not(_mm512_and_si512(a, b));
case 8: return _mm512_and_si512(a, b);
case 9: return not(_mm512_xor_si512(a, b));
case 10: return b;
case 11: return _mm512_or_si512(not(a), b);
case 12: return a;
case 13: return mm512_or_si512(a, not(b));
case 14: return _mm512_or_si512(a, b);
case 15: return _mm512_set1_epi32(-1);
default: return _mm512_setzero_si512();
}
}
void BF_Q6(const __m512i A, const __m512i B, const __m512i C, const __m512i D, const __m512i E, const __m512i F, __m512i& F0, __m512i& F1) {
const auto n11 = _mm512_ternarylogic_epi64(B, C, D, 0x01);
const auto n12 = binary(A, E, 0x1);
const auto n14 = binary(A, E, 0x9);
const auto n16 = _mm512_ternarylogic_epi64(B, C, D, 0xe9);
const auto n18 = binary(n11, n14, 0x2);
F1 = _mm512_ternarylogic_epi64(n18, n12, n16, 0xae);
const auto n21 = _mm512_ternarylogic_epi64(F, n11, n14, 0xd9);
const auto n22 = _mm512_ternarylogic_epi64(F, n12, n16, 0xd9);
F0 = _mm512_ternarylogic_epi64(F, n21, n22, 0x95);
}
결과 C 여부 ++이 기계적 C++로 번역 될 수
INPUT(A)
INPUT(B)
INPUT(C)
INPUT(D)
INPUT(E)
INPUT(F)
OUTPUT(F0)
OUTPUT(F1)
n11 = LUT 0x01 (B, C, D)
n12 = LUT 0x1 (A, E)
n14 = LUT 0x9 (A, E)
n16 = LUT 0xe9 (B, C, D)
n18 = LUT 0x2 (n11, n14)
F1 = LUT 0xae (n18, n12, n16)
n21 = LUT 0xd9 (F, n11, n14)
n22 = LUT 0xd9 (F, n12, n16)
F0 = LUT 0x95 (F, n21, n22)
4. :
생성 BF_Q6.bench는 FPGA에 대한 3 개의 LUT를 포함 코드가 최적입니다. 나는이 방법이 (종종)이 문제가 NP 하드이기 때문에 3-LUT의 가장 작은 네트워크를 산출한다고 생각하지 않는다. 또한 ABC에 명령 병렬성에 대해 알릴 수 없으며 나중에 사용될 변수가 LUT의 첫 번째 위치에 있지 않도록 변수의 순서를 우선 순위화할 수 없습니다 (첫 번째 소스 피연산자가 결과). 그러나 컴파일러는 그러한 최적화를 수행 할만큼 똑똑 할 수 있습니다.
ICC18는 다음 어셈블리를 제공합니다
00007FF75DCE1340 sub rsp,78h
00007FF75DCE1344 vmovups xmmword ptr [rsp+40h],xmm15
00007FF75DCE134A vmovups zmm2,zmmword ptr [r9]
00007FF75DCE1350 vmovups zmm1,zmmword ptr [r8]
00007FF75DCE1356 vmovups zmm5,zmmword ptr [rdx]
00007FF75DCE135C vmovups zmm4,zmmword ptr [rcx]
00007FF75DCE1362 vpternlogd zmm15, zmm15, zmm15, 0FFh
00007FF75DCE1369 vpternlogq zmm5, zmm1, zmm2, 0E9h
00007FF75DCE1370 vmovaps zmm3, zmm2
00007FF75DCE1376 mov rax, qword ptr[&E]
00007FF75DCE137E vpternlogq zmm3, zmm1, zmmword ptr[rdx], 1
00007FF75DCE1385 mov r11, qword ptr[&F]
00007FF75DCE138D mov rcx, qword ptr[F0]
00007FF75DCE1395 mov r10, qword ptr[F1]
00007FF75DCE139D vpord zmm0, zmm4, zmmword ptr[rax]
00007FF75DCE13A3 vpxord zmm4, zmm4, zmmword ptr[rax]
00007FF75DCE13A9 vpxord zmm0, zmm0, zmm15
00007FF75DCE13AF vpxord zmm15, zmm4, zmm15
00007FF75DCE13B5 vpandnd zmm1, zmm3, zmm15
00007FF75DCE13BB vpternlogq zmm1, zmm0, zmm5, 0AEh
00007FF75DCE13C2 vpternlogq zmm15, zmm3, zmmword ptr[r11], 0CBh
^^^^^ ^^^^^^^^^^^^^^^^
00007FF75DCE13C9 vpternlogq zmm5, zmm0, zmmword ptr[r11], 0CBh
00007FF75DCE13D0 vmovups zmmword ptr[r10], zmm1
00007FF75DCE13D6 vpternlogq zmm5, zmm15, zmmword ptr[r11], 87h
00007FF75DCE13DD vmovups zmmword ptr [rcx],zmm5
00007FF75DCE13E3 vzeroupper
00007FF75DCE13E6 vmovups xmm15,xmmword ptr [rsp+40h]
00007FF75DCE13EC add rsp,78h
00007FF75DCE13F0 ret
ICC18이 const auto n22 = _mm512_ternarylogic_epi64(F, n12, n16, 0xd9);
vpternlogq zmm15, zmm3, zmmword ptr[r11], 0CBh
에 변수 F 덮어 쓰기되지 않도록에서 변수 순서를 변경할 수 있습니다. (그러나 이상하게도 메모리에서 3 번 가져온다 ...)
컴파일러가'_mm_xor' /'_mm_and'/등을'vpternlogd' 명령으로 최적화 할 지 확인 했습니까? –
@PeterCordes 인텔 컴파일러는 부울 논리를 ternlog에 병합합니다. 그러나 더 큰 시퀀스를 단순화하는 것이 얼마나 현명한지를 테스트 한 적이 없습니다. – Mysticial
@Mysticial :'((a^d) & (b^a)) & (c & (d^a)^f) & e |에 대해'vpternlogd'를 주로 사용합니다. f'가 아니라 IDK가 최적이라면 말이죠. 내 대답에서 Godbolt 링크를 업데이트했습니다. –