source: icGREP/icgrep-devel/icgrep/kernels/alignedprint.cpp @ 5326

Last change on this file since 5326 was 5326, checked in by cameron, 2 years ago

Changes from Adam

File size: 4.7 KB
Line 
1/*
2 *  Copyright (c) 2017 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5
6#include "alignedprint.h"
7#include <IR_Gen/idisa_builder.h>  // for IDISA_Builder
8
9using namespace llvm;
10
11namespace kernel {
12
13    void p2s_step(IDISA::IDISA_Builder * iBuilder, Value * p0, Value * p1, Value * hi_mask, unsigned shift, Value * &s1, Value * &s0) {
14    Value * t0 = iBuilder->simd_if(1, hi_mask, p0, iBuilder->simd_srli(16, p1, shift));
15    Value * t1 = iBuilder->simd_if(1, hi_mask, iBuilder->simd_slli(16, p0, shift), p1);
16    s1 = iBuilder->esimd_mergeh(8, t1, t0);
17    s0 = iBuilder->esimd_mergel(8, t1, t0);
18}
19
20inline void p2s(IDISA::IDISA_Builder * iBuilder, Value * p[], Value * s[]) {
21    Value * bit00004444[2];
22    Value * bit22226666[2];
23    Value * bit11115555[2];
24    Value * bit33337777[2];
25    p2s_step(iBuilder, p[0], p[4], iBuilder->simd_himask(8), 4, bit00004444[1], bit00004444[0]);
26    p2s_step(iBuilder, p[1], p[5], iBuilder->simd_himask(8), 4, bit11115555[1], bit11115555[0]);
27    p2s_step(iBuilder, p[2], p[6], iBuilder->simd_himask(8), 4, bit22226666[1], bit22226666[0]);
28    p2s_step(iBuilder, p[3], p[7], iBuilder->simd_himask(8), 4, bit33337777[1], bit33337777[0]);
29    Value * bit00224466[4];
30    Value * bit11335577[4];
31    for (unsigned j = 0; j<2; j++) {
32        p2s_step(iBuilder, bit00004444[j], bit22226666[j],iBuilder->simd_himask(4), 2, bit00224466[2*j+1], bit00224466[2*j]);
33        p2s_step(iBuilder, bit11115555[j], bit33337777[j],iBuilder->simd_himask(4), 2, bit11335577[2*j+1], bit11335577[2*j]);
34    }
35    for (unsigned j = 0; j<4; j++) {
36        p2s_step(iBuilder, bit00224466[j], bit11335577[j], iBuilder->simd_himask(2), 1, s[2*j+1], s[2*j]);
37    }
38}
39
40void PrintableBits::generateDoBlockMethod() {
41    // Load current block
42    Value * bitStrmVal = loadInputStreamBlock("bitStream", iBuilder->getInt32(0));
43
44    Value * bits[8];
45
46    /*
47    00110001 is the Unicode codepoint for '1' and 00101110 is the codepoint for '.'.
48    We want to output a byte stream that is aligned with the input bitstream such that it contains 00110001 in each 1 position and 00101110 in each 0 position.
49   
50    For example, consider input bitstream 101. Our desired output is:
51    00110001 00101110 00110001
52
53    We can do the bitstream to bytestream conversion in parallel by viewing the output stream in terms of parallel bit streams.
54
55    0   0   0 -> First bit position of every byte is all zeros
56    0   0   0 -> Same for second bit
57    1   1   1 -> Third bit is all ones
58    1   0   1 -> 4th bit is 1 for a '1' byte and '0' for a zero byte. Matches input bit stream
59    0   1   0 -> opposite
60    0   1   0 -> opposite
61    0   1   0 -> opposite
62    1   0   1 -> same as 4th bit position.
63   
64    Armed with the above we can do the bit->byte conversion all at once
65    rather than byte at a time! That's what we do below.
66    */
67
68    bits[0] = ConstantInt::getNullValue(iBuilder->getBitBlockType());
69    bits[1] = ConstantInt::getNullValue(iBuilder->getBitBlockType());
70    bits[2] = ConstantInt::getAllOnesValue(iBuilder->getBitBlockType());
71    bits[3] = bitStrmVal;
72    Value * negBitStrmVal = iBuilder->simd_not(bitStrmVal);
73    bits[4] = negBitStrmVal;
74    bits[5] = negBitStrmVal;
75    bits[6] = negBitStrmVal;
76    bits[7] = bitStrmVal;
77   
78    // Reassemble the paralell bit streams into a byte stream
79    Value * printableBytes[8];
80    p2s(iBuilder, bits, printableBytes);
81   
82    for (unsigned j = 0; j < 8; ++j) {
83        storeOutputStreamPack("byteStream", iBuilder->getInt32(0), iBuilder->getInt32(j), iBuilder->bitCast(printableBytes[j]));
84    }
85}
86
87PrintableBits::PrintableBits(IDISA::IDISA_Builder * builder)
88: BlockOrientedKernel(builder, "PrintableBits", {Binding{builder->getStreamSetTy(1, 1), "bitStream"}}, {Binding{builder->getStreamSetTy(1, 8), "byteStream"}}, {}, {}, {})
89{
90    setNoTerminateAttribute(true);
91    setDoBlockUpdatesProducedItemCountsAttribute(false);
92
93}
94
95SelectStream::SelectStream(IDISA::IDISA_Builder * builder, unsigned sizeInputStreamSet, unsigned streamIndex)
96: BlockOrientedKernel(builder, "SelectStream", {Binding{builder->getStreamSetTy(sizeInputStreamSet, 1), "bitStreams"}}, {Binding{builder->getStreamSetTy(1, 1), "bitStream"}}, {}, {}, {}), mSizeInputStreamSet(sizeInputStreamSet), mStreamIndex(streamIndex)
97{
98    setNoTerminateAttribute(true);
99    setDoBlockUpdatesProducedItemCountsAttribute(false);
100
101}
102
103void SelectStream::generateDoBlockMethod() {
104    if (mStreamIndex >= mSizeInputStreamSet)
105        llvm::report_fatal_error("Stream index out of bounds.\n");
106   
107    Value * bitStrmVal = loadInputStreamBlock("bitStreams", iBuilder->getInt32(mStreamIndex));
108
109    storeOutputStreamBlock("bitStream", iBuilder->getInt32(0), bitStrmVal);
110}
111}
Note: See TracBrowser for help on using the repository browser.