# llot **Repository Path**: woodford/llot ## Basic Information - **Project Name**: llot - **Description**: low level operator transpiler - **Primary Language**: CoffeeScript - **License**: BSD-3-Clause - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-05-21 - **Last Updated**: 2023-05-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Low Level Operator Transpiler(llot) * 名称: 低层次算子转译器 基础代码来自于coffee-hdl项目,是一个带有代码生成能力的转译器框架. * 目标: 通过增加typescript词法, 以typescript作为宿主语法描述算法,生成混合向量运算,DSA运算的底层运算指令. * 假设: 系统带有一个完备的标量处理器(cpu), 挂载可编程的向量处理硬件引擎(vector)和更加高效的能完成特定计算的硬件模块(DSA) cpu可以通过寄存器或者共享内存和vector或者DSA交换数据 * 动机: 当一个AI算子需要vector和DSA配合cpu做异构计算一般有两种方案 * 一种是从下岛上,配置寄存器->启动->等待中断/查询,所需的存储器计算资源需要在运行时分配,这种方式表达能力差,差错成本高 * 一种是从上到下,事先定义好ir用来隔离算法和硬件,编译高级语言到ir,这种方法表达能力足够,这个方法往往采用很重的前段框架,ir一般颗粒度太细,直接映射DSA的计算功能需要比较大的工程量. llot的想法是通过一个框架直接定制描述语言,使得其颗粒度和硬件能一一对应,描述能力近似于高级语言,并可以发射到各种层次的描述形式. 执行流程: 源文件是通过定制typescript语法的的llot文件描述算子,用转译器转成标准typescript文件,配合llot运行时生成js文件,js文件包含变量生命周期管理和低层次算子,再执行js文件最终输出目标处理器代码.目标处理器代码根据不同的发射器可以是汇编,C,或者直接是二进制,也可以直接仿真. ## 设置和测试 ``` npm install source sourceme.sh cd test/basic llot.coffee softmax.llot ``` ## 输出结果说明 ```javascript 1 function *Softmax( 2 ) { 3 // variable __f32_1 symbol s1, 分配变量__f32_1到通用寄存器s1 4 asm.init_var(0x0,0); 5 // variable __f32_2 symbol s2, 分配变量__f32_2到通用寄存器s2 6 asm.init_var(0x1,0); 7 8 // var declare 9 // vector __vec_0 @256, 向量__vec_0内存地址256 10 // vector __vec_3 @656,向量__vec_3内存地址656 11 // vector __vec_4 @1056, 向量__vec_4内存地址1056 12 // v0 __vec_0 13 // s1 __f32_1 14 // s2 __f32_2 15 // v3 __vec_3 16 // v4 __vec_4 17 18 asm.sfu_exp(256,656,100,"f32"); 19 // sfu_exp(v0,v3) 通过指数运算加速器把__vec_0指向的100个fp32类型数据映射到__vec_3指向内存 20 asm.reduce_add(656,100,0,"f32"); 21 // reduce_add(v3,s1) 通过reduce运算加速器把__vec_3指向的100个fp32类型数据做加法,结果输出到__f32_1变量 22 asm.recip(0,1,"f32"); 23 // sfu_recip(s1,s2) 把__f32_1变量求倒数输出到__f32_2变量 24 asm.vec.begin(); 25 asm.vec.load(0,656/*__vec_3*/,100); //载入__vec_3向量 26 asm.vec.set_const_indirect(1,1,100); //载入__f32_2变量 27 asm.vec.fmultivc(1); //运算向量乘标量 28 asm.vec.store(1056/*__vec_4*/,100); //输出到__vec_4向量 29 asm.vec.end(); 30 // *__vec_4 = __vec_3*__f32_2 31 //release v0, 释放__vec_0指向的内存 32 //release s2, 释放__f32_2变量占用寄存器 33 //release v3, 释放__vec_3指向的内存 34 return [1056,0] //返回__vec_4向量和__vec_0变量 35 36 } ```