| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249 |
- import * as base from './base.js';
- const kmodel = {};
- kmodel.ModelFactory = class {
- async match(context) {
- const reader = kmodel.Reader.open(context.stream);
- if (reader) {
- return context.set('kmodel', reader);
- }
- return null;
- }
- async open(context) {
- const target = context.value;
- target.read();
- return new kmodel.Model(target);
- }
- };
- kmodel.Model = class {
- constructor(model) {
- this.format = `kmodel v${model.version}`;
- this.modules = model.modules.map((module) => new kmodel.Graph(module));
- }
- };
- kmodel.Graph = class {
- constructor(module) {
- this.name = module.name || '';
- this.description = module.type || '';
- this.inputs = [];
- this.outputs = [];
- this.nodes = [];
- const scopes = new Map();
- let index = 0;
- const values = new Map();
- const value = (arg) => {
- const name = arg.name;
- const type = arg.shape ? new kmodel.TensorType(arg.datatype || '?', arg.shape) : null;
- if (arg.data) {
- const tensor = arg.data ? new kmodel.Tensor(type, arg.data) : null;
- return new kmodel.Value(name, type || null, tensor);
- }
- if (!values.has(name)) {
- values.set(name, new kmodel.Value(name, type || null, null));
- } if ((type && !type.equals(values.get(name).type))) {
- return new kmodel.Value(name, type);
- }
- return values.get(name);
- };
- for (const layer of module.layers) {
- for (const input of layer.inputs || []) {
- for (const arg of input.value) {
- arg.name = scopes.has(arg.name) ? scopes.get(arg.name) : arg.name;
- }
- }
- for (const output of layer.outputs || []) {
- for (const arg of output.value) {
- const name = scopes.has(arg.name) ? `${arg.name}#${index}` : arg.name;
- scopes.set(arg.name, name); // custom argument id
- arg.name = name;
- if (arg.name && arg.shape && !arg.data) {
- value(arg);
- }
- }
- }
- index++;
- }
- for (const layer of module.layers) {
- for (const output of layer.outputs || []) {
- for (const arg of output.value) {
- if (arg.name && arg.shape && !arg.data) {
- value(arg);
- }
- }
- }
- }
- for (const layer of module.layers) {
- for (const input of layer.inputs || []) {
- for (const arg of input.value) {
- if (arg.name && arg.shape && !arg.data) {
- value(arg);
- }
- }
- }
- }
- for (const layer of module.layers) {
- switch (layer.type.name) {
- case 'INPUT':
- case 'input': {
- for (const input of layer.outputs) {
- const values = input.value.map((arg) => value(arg));
- const argument = new kmodel.Argument('input', values);
- this.inputs.push(argument);
- }
- break;
- }
- case 'OUTPUT':
- case 'output': {
- for (const output of layer.inputs) {
- const values = output.value.map((arg) => value(arg));
- const argument = new kmodel.Argument(output.name, values);
- this.outputs.push(argument);
- }
- break;
- }
- default: {
- const node = new kmodel.Node(layer, value);
- this.nodes.push(node);
- break;
- }
- }
- }
- }
- };
- kmodel.Argument = class {
- constructor(name, value) {
- this.name = name;
- this.value = value;
- }
- };
- kmodel.Value = class {
- constructor(name, type, initializer) {
- if (typeof name !== 'string') {
- throw new kmodel.Error(`Invalid value identifier '${JSON.stringify(name)}'.`);
- }
- this.name = name;
- this.type = !type && initializer ? initializer.type : type;
- this.initializer = initializer;
- }
- };
- kmodel.TensorType = class {
- constructor(dataType, shape) {
- this.dataType = dataType;
- this.shape = new kmodel.TensorShape(shape);
- }
- equals(obj) {
- return obj && this.dataType === obj.dataType && this.shape && this.shape.equals(obj.shape);
- }
- toString() {
- return this.dataType + this.shape.toString();
- }
- };
- kmodel.TensorShape = class {
- constructor(dimensions) {
- this.dimensions = dimensions;
- }
- equals(obj) {
- if (obj && Array.isArray(obj.dimensions) && Array.isArray(this.dimensions)) {
- if (this.dimensions.length === obj.dimensions.length) {
- return obj.dimensions.every((value, index) => this.dimensions[index] === value);
- }
- if (obj.dimensions.every((dim) => Number.isInteger(dim)) && this.dimensions.every((dim) => Number.isInteger(dim))) {
- const a = obj.dimensions.reduce((a, b) => a * b, 1);
- const b = this.dimensions.reduce((a, b) => a * b, 1);
- return a === b;
- }
- }
- return false;
- }
- toString() {
- if (this.dimensions && Array.isArray(this.dimensions) && this.dimensions.length > 0) {
- return `[${this.dimensions.map((dim) => dim ? dim.toString() : '?').join(',')}]`;
- }
- return '';
- }
- };
- kmodel.Tensor = class {
- constructor(type, data) {
- this.type = type;
- this.values = data;
- }
- };
- kmodel.Node = class {
- constructor(layer, value) {
- this.identifier = layer.location === undefined ? layer.location : layer.location.toString();
- this.name = '';
- this.type = layer.type;
- this.inputs = [];
- this.outputs = [];
- this.chain = [];
- this.attributes = [];
- this.chain = [];
- for (const [name, value] of Object.entries(layer)) {
- if (name === 'type' || name === 'location' || name === 'inputs' || name === 'outputs' || name === 'chain') {
- continue;
- }
- const attribute = new kmodel.Argument(name, value);
- this.attributes.push(attribute);
- }
- for (const input of layer.inputs || []) {
- const values = input.value.map((arg) => value(arg));
- const argument = new kmodel.Argument(input.name, values);
- this.inputs.push(argument);
- }
- for (const output of layer.outputs || []) {
- const values = output.value.map((arg) => value(arg));
- const argument = new kmodel.Argument(output.name, values);
- this.outputs.push(argument);
- }
- for (const chain of layer.chain || []) {
- const node = new kmodel.Node(chain, value);
- this.chain.push(node);
- }
- }
- };
- kmodel.Reader = class {
- static open(stream) {
- if (stream && stream.length >= 4) {
- const length = Math.min(8, stream.length);
- const buffer = stream.peek(length);
- if ([0x03, 0x00, 0x00, 0x00].every((value, index) => value === buffer[index])) {
- return new kmodel.Reader(stream, 3);
- }
- if ([0x4C, 0x44, 0x4D, 0x4B].every((value, index) => value === buffer[index]) && buffer.length >= 8) {
- const reader = base.BinaryReader.open(buffer);
- reader.skip(4);
- const version = reader.uint32();
- return new kmodel.Reader(stream, version);
- }
- }
- return null;
- }
- constructor(stream, version) {
- this.stream = stream;
- this.version = version;
- this.modules = [];
- }
- read() {
- if (this.version < 3 || this.version > 7) {
- throw new kmodel.Error(`Unsupported model version '${this.version}'.`);
- }
- const types = new Map();
- const register = (type, name, category, callback) => {
- types.set(type, { type: { name, category: category || '' }, callback });
- };
- switch (this.version) {
- case 3: {
- const reader = new kmodel.BinaryReader.v3(this.stream);
- const model_header = reader.kpu_model_header_t();
- const layers = new Array(model_header.layers_length);
- const outputs = new Array(model_header.output_count);
- for (let i = 0; i < model_header.output_count; i++) {
- outputs[i] = reader.kpu_model_output_t(`output${i > 0 ? i.toString() : ''}`);
- }
- for (let i = 0; i < layers.length; i++) {
- layers[i] = reader.kpu_model_layer_header_t();
- layers[i].location = i;
- }
- let offset = reader.position;
- for (const layer of layers) {
- layer.offset = offset;
- offset += layer.body_size;
- }
- /* eslint-disable space-in-parens */
- register( -1, 'DUMMY');
- register( 0, 'INVALID');
- register( 1, 'ADD');
- register( 2, 'QUANTIZED_ADD');
- register( 3, 'GLOBAL_MAX_POOL2D', 'Pool');
- register( 4, 'QUANTIZED_GLOBAL_MAX_POOL2D', 'Pool');
- register( 5, 'GLOBAL_AVERAGE_POOL2D', 'Pool', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.kernel_size = reader.uint32();
- layer.channels = reader.uint32();
- });
- register( 6, 'QUANTIZED_GLOBAL_AVERAGE_POOL2D', 'Pool');
- register( 7, 'MAX_POOL2D', 'Pool');
- register( 8, 'QUANTIZED_MAX_POOL2D', 'Pool', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.inputs[0].value[0].shape = [reader.uint32(), reader.uint32(), reader.uint32()];
- layer.outputs[0].value[0].shape = [reader.uint32(), reader.uint32(), reader.uint32()];
- layer.kernel = [reader.uint32(), reader.uint32()];
- layer.stride = [reader.uint32(), reader.uint32()];
- layer.padding = [reader.uint32(), reader.uint32()];
- });
- register( 9, 'AVERAGE_POOL2D', 'Pool');
- register( 10, 'QUANTIZED_AVERAGE_POOL2D', 'Pool');
- register( 11, 'QUANTIZE', '', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.count = reader.uint32();
- layer.scale = reader.float32();
- layer.bias = reader.float32();
- });
- register( 12, 'DEQUANTIZE', '', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.count = reader.uint32();
- layer.scale = reader.float32();
- layer.bias = reader.float32();
- });
- register( 13, 'REQUANTIZE', '', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.count = reader.uint32();
- layer.table = reader.read(256);
- });
- register( 14, 'L2_NORMALIZATION', 'Normalization');
- register( 15, 'SOFTMAX', 'Activation', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.channels = reader.uint32();
- });
- register( 16, 'CONCAT', 'Tensor', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.outputs = [reader.parameter('output')];
- layer.inputs_mem = new Array(reader.uint32());
- for (let i = 0; i < layer.inputs_mem.length; i++) {
- layer.inputs_mem[i] = {
- start: reader.uint32(),
- end: reader.uint32()
- };
- }
- });
- register( 17, 'QUANTIZED_CONCAT', 'Tensor', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.outputs = [reader.parameter('output')];
- layer.inputs_mem = new Array(reader.uint32());
- for (let i = 0; i < layer.inputs_mem.length; i++) {
- layer.inputs_mem[i] = {
- start: reader.uint32(),
- end: reader.uint32()
- };
- }
- });
- register( 18, 'FULLY_CONNECTED', 'Layer', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.in_channels = reader.uint32();
- layer.out_channels = reader.uint32();
- const act = reader.uint32();
- const activations = [
- { name: 'LINEAR', category: 'Activation' },
- { name: 'RELU', category: 'Activation' },
- { name: 'RELU6', category: 'Activation' },
- ];
- if (act !== 0) {
- if (act > activations.length) {
- throw new kmodel.Error(`Unsupported FULLY_CONNECTED activation '${act}'.`);
- }
- layer.chain = [{ type: activations[act] }];
- }
- layer.inputs.push({ name: 'weights', value: [{ name: '', datatype: 'float32', shape: [layer.in_channels, layer.out_channels], data: reader.read(4 * layer.in_channels * layer.out_channels) }] });
- layer.inputs.push({ name: 'bias', value: [{ name: '', datatype: 'float32', shape: [layer.out_channels], data: reader.read(4 * layer.out_channels) }] });
- });
- register( 19, 'QUANTIZED_FULLY_CONNECTED', 'Layer');
- register( 20, 'TENSORFLOW_FLATTEN', 'Shape', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- const shape = [reader.uint32(), reader.uint32(), reader.uint32()];
- layer.inputs[0].value[0].shape = shape;
- layer.outputs[0].value[0].shape = shape;
- });
- register( 21, 'QUANTIZED_TENSORFLOW_FLATTEN', 'Shape', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- const shape = [reader.uint32(), reader.uint32(), reader.uint32()];
- layer.inputs[0].value[0].shape = shape;
- layer.outputs[0].value[0].shape = shape;
- });
- register( 22, 'RESIZE_NEAREST_NEIGHBOR', '', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.inputs[0].value[0].shape = [reader.uint32(), reader.uint32(), reader.uint32()];
- layer.out_width = reader.uint32();
- layer.out_height = reader.uint32();
- layer.align_corners = reader.uint32();
- });
- register( 23, 'QUANTIZED_RESIZE_NEAREST_NEIGHBOR', '', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.inputs[0].value[0].shape = [reader.uint32(), reader.uint32(), reader.uint32()];
- layer.out_width = reader.uint32();
- layer.out_height = reader.uint32();
- layer.align_corners = reader.uint32();
- });
- register( 1000, 'CONV', 'Layer');
- register( 1001, 'DWCONV', 'Layer');
- register( 1002, 'QUANTIZED_RESHAPE', 'Shape');
- register( 1003, 'RESHAPE', 'Shape');
- register(10240, 'K210_CONV', 'Layer', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.outputs = [reader.parameter('output')];
- const layer_offset = reader.uint32();
- const weights_offset = reader.uint32();
- const bn_offset = reader.uint32();
- const act_offset = reader.uint32();
- reader.seek(layer_offset);
- layer.interrupt_enabe = reader.uint64_bits({ int_en: 0, ram_flag: 1, full_add: 2, depth_wise_layer: 3 });
- layer.inputs = [reader.parameter('input', 'kpu')];
- const outputs = [reader.parameter('output', 'kpu')];
- layer.outputs[0].value.push(outputs[0].value[0]);
- // layer.outputs = layer.flags & 1 ? layer.outputs : outputs;
- layer.image_channel_num = reader.uint64_bits({ i_ch_num: 0, o_ch_num: 32, o_ch_num_coef: 48 });
- layer.image_size = reader.uint64_bits({ i_row_wid: 0, i_col_high: 10, o_row_wid: 32, o_col_high : 42 });
- layer.kernel_pool_type_cfg = reader.uint64_bits({ kernel_type: 0, pad_type: 3, pool_type: 4, first_stride: 8, bypass_conv: 9, load_para: 10, dma_burst_size: 16, pad_value: 24, bwsx_base_addr: 32 });
- layer.kernel_load_cfg = reader.uint64_bits({ load_coor: 0, load_time: 1, para_size: 15, para_start_addr: 32 });
- layer.kernel_offset = reader.uint64_bits({ coef_column_offset: 0, coef_row_offset: 4 });
- layer.kernel_calc_type_cfg = reader.uint64_bits({ channel_switch_addr: 0, row_switch_addr: 16, coef_size: 20, coef_group: 28, load_act: 31, active_addr: 32 });
- layer.write_back_cfg = reader.uint64_bits({ wb_channel_switch_addr: 0, wb_row_switch_addr: 16, wb_group: 20 });
- layer.conv_value = reader.uint64_bits({ shr_w: 0, shr_x: 4, arg_w: 8, arg_x: 32 });
- layer.conv_value2 = reader.uint64_bits({ arg_add: 0 });
- layer.dma_parameter = reader.uint64_bits({ send_data_out: 0, channel_byte_num: 16, dma_total_byte: 32 });
- layer.chain = [];
- const ic = layer.image_channel_num.i_ch_num + 1;
- const oc = layer.image_channel_num.o_ch_num + 1;
- layer.outputs[0].value[0].shape = [layer.image_size.o_row_wid + 1, layer.image_size.o_col_high + 1, oc];
- const filter = [1, 3][layer.kernel_pool_type_cfg.kernel_type];
- const weights_shape = layer.interrupt_enabe.depth_wise_layer ? [oc, filter, filter] : [ic, oc, filter, filter];
- const weights_size = weights_shape.reduce((a, b) => a * b);
- reader.seek(bn_offset);
- const batch_norm = {
- type: { name: 'BATCH_NORM', category: 'Normalization' },
- weights: []
- };
- batch_norm.weights = new Array(oc);
- for (let i = 0; i < oc; i++) {
- batch_norm.weights[i] = reader.uint64_bits({ norm_mul: 0, norm_add: 24, norm_shift: 56, reserved: 60 });
- delete batch_norm.weights[i].reserved;
- }
- layer.chain.push(batch_norm);
- reader.seek(act_offset);
- const activation = {};
- activation.type = { name: 'ACTIVATION', category: 'Activation' };
- activation.activate_para = new Array(16);
- for (let i = 0; i < 16; i++) {
- activation.activate_para[i] = reader.uint64_bits({ shift_number: 0, y_mul: 8, x_start: 24, reserved: 60 });
- delete activation.activate_para[i].reserved;
- }
- for (let i = 0; i < 16; i++) {
- activation.activate_para[i].bias = reader.int8();
- }
- layer.chain.push(activation);
- reader.seek(weights_offset);
- layer.inputs.push({
- name: 'weights',
- value: [{
- name: '',
- datatype: 'uint8',
- shape: weights_shape,
- data: reader.read(weights_size)
- }]
- });
- delete layer.kernel_pool_type_cfg.bwsx_base_addr;
- delete layer.kernel_calc_type_cfg.active_addr;
- delete layer.kernel_load_cfg.para_start_addr;
- });
- register(10241, 'K210_ADD_PADDING', '', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output', 'kpu')];
- layer.channels = reader.uint32();
- });
- register(10242, 'K210_REMOVE_PADDING', '', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.channels = reader.uint32();
- });
- register(10243, 'K210_UPLOAD', '', (layer, reader) => {
- layer.flags = reader.uint32();
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output', 'kpu')];
- const shape = [reader.uint32(), reader.uint32(), reader.uint32()];
- layer.inputs[0].value[0].shape = shape;
- layer.outputs[0].value[0].shape = shape;
- });
- /* eslint-enable space-in-parens */
- for (const layer of layers) {
- const type = types.get(layer.type);
- if (!type) {
- throw new kmodel.Error(`Unsupported version '${this.version}' layer type '${layer.type}'.`);
- }
- if (!type.callback) {
- throw new kmodel.Error(`Unsupported version '${this.version}' layer '${type.type.name}'.`);
- }
- layer.type = type.type;
- reader.seek(layer.offset);
- type.callback(layer, reader);
- delete layer.offset;
- delete layer.body_size;
- }
- if (layers.length > 0) {
- layers.unshift({
- type: { name: 'input' },
- outputs: [layers[0].inputs[0]]
- });
- }
- for (const output of outputs) {
- layers.push({
- type: { name: 'output' },
- inputs: output.address
- });
- }
- this.modules.push({
- name: '',
- layers
- });
- break;
- }
- case 4: {
- const reader = new kmodel.BinaryReader.v4(this.stream);
- const model_header = {
- flags: reader.uint32(),
- target: reader.uint32(), // 0=CPU, 1=K210
- constants: reader.uint32(),
- main_mem: reader.uint32(),
- nodes: reader.uint32(),
- inputs: reader.uint32(),
- outputs: reader.uint32(),
- reserved0: reader.uint32(),
- };
- const inputs = new Array(model_header.inputs);
- for (let i = 0; i < inputs.length; i++) {
- inputs[i] = reader.parameter(`input${i === 0 ? '' : (i + 1)}`);
- }
- for (let i = 0; i < inputs.length; i++) {
- inputs[i].value[0].shape = reader.runtime_shape_t();
- }
- const outputs = new Array(model_header.outputs);
- for (let i = 0; i < outputs.length; i++) {
- outputs[i] = reader.parameter(`output${i === 0 ? '' : (i + 1)}`);
- }
- reader.constants(model_header.constants);
- const layers = new Array(model_header.nodes);
- for (let i = 0; i < layers.length; i++) {
- layers[i] = {
- location: i,
- opcode: reader.uint32(),
- body_size: reader.uint32()
- };
- }
- let offset = reader.position;
- for (const layer of layers) {
- layer.offset = offset;
- offset += layer.body_size;
- }
- /* eslint-disable space-in-parens */
- register( 0x00, 'binary', '', (layer, reader) => {
- layer.inputs = [
- reader.parameter('a'),
- reader.parameter('b')
- ];
- layer.outputs = [reader.parameter('outputs')];
- layer.binary_op = reader.binary_op_t();
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.inputs[1].value[0].shape = reader.runtime_shape_t();
- layer.outputs[0].value[0].shape = reader.runtime_shape_t();
- layer.fused_activation = [reader.float32(), reader.float32()];
- });
- register( 0x01, 'concat', 'Tensor', (layer, reader) => {
- layer.outputs = [reader.parameter('output')];
- layer.inner_size = reader.uint32();
- layer.outer_size = reader.uint32();
- const inputs_count = reader.uint32();
- layer.inputs = [{ name: 'inputs', value: [] }];
- for (let i = 0; i < inputs_count; i++) {
- layer.inputs[0].value[i] = reader.argument();
- }
- layer.dims = new Array(inputs_count);
- for (let i = 0; i < inputs_count; i++) {
- layer.dims[i] = reader.int32();
- }
- });
- register( 0x02, 'conv2d', 'Layer', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.groups = reader.int32();
- layer.out_channels = reader.int32();
- layer.padding_h = reader.padding();
- layer.padding_w = reader.padding();
- layer.filter_h = reader.int32();
- layer.filter_w = reader.int32();
- layer.stride_h = reader.int32();
- layer.stride_w = reader.int32();
- layer.dilation_h = reader.int32();
- layer.dilation_w = reader.int32();
- layer.fused_activation = [reader.float32(), reader.float32()];
- const weights_shape = [layer.out_channels, layer.inputs[0].value[0].shape[1] / layer.groups, layer.filter_h, layer.filter_w];
- const weights_size = 4 * weights_shape.reduce((a, b) => a * b);
- layer.inputs.push({
- name: 'weights',
- value: [{
- name: '',
- datatype: 'float32',
- shape: weights_shape,
- data: reader.read(weights_size)
- }]
- });
- const bias_shape = [layer.out_channels];
- const bias_size = 4 * layer.out_channels;
- layer.inputs.push({
- name: 'bias',
- value: [{
- name: '',
- datatype: 'float32',
- shape: bias_shape,
- data: reader.read(bias_size)
- }]
- });
- });
- register( 0x03, 'dequantize', '', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.zero_point = reader.int32();
- layer.scale = reader.float32();
- });
- register( 0x04, 'matmul', '', (layer, reader) => {
- layer.inputs = [
- reader.parameter('a'),
- reader.parameter('b'),
- ];
- layer.outputs = [reader.parameter('output')];
- layer.a_rows = reader.int32();
- layer.a_cols = reader.int32();
- layer.b_cols = reader.int32();
- layer.inputs[1].value[0].shape = [layer.a_cols, layer.b_cols];
- layer.fused_activation = [reader.float32(), reader.float32()];
- const bias = reader.read(4 * layer.b_cols);
- if (!bias.every((value) => value === 0)) {
- layer.inputs.push({
- name: 'bias',
- value: [{ name: '', datatype: 'float32', shape: [layer.b_cols], data: bias }]
- });
- }
- });
- register( 0x05, 'pad', 'Shape', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.paddings = reader.runtime_paddings_t();
- layer.pad_value = reader.scalar();
- });
- register( 0x06, 'quantize', '', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.zero_point = reader.int32();
- layer.scale = reader.float32();
- });
- register( 0x07, 'reduce', '', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.reduce_op = reader.reduce_op_t();
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.outputs[0].value[0].shape = reader.runtime_shape_t();
- layer.init_value = reader.float32();
- });
- register( 0x08, 'reduce_window2d', '', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.reduce_op = reader.reduce_op_t();
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.padding_h = reader.padding();
- layer.padding_w = reader.padding();
- layer.filter_h = reader.int32();
- layer.filter_w = reader.int32();
- layer.stride_h = reader.int32();
- layer.stride_w = reader.int32();
- layer.dilation_h = reader.int32();
- layer.dilation_w = reader.int32();
- layer.init_value = reader.float32();
- layer.fused_activation = [reader.float32(), reader.float32()];
- });
- register( 0x09, 'memory_copy', '', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- });
- register( 0x0A, 'resize_image', '', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.reduce_op = reader.reduce_op_t();
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.out_h = reader.int32();
- layer.out_w = reader.int32();
- layer.mode = reader.image_resize_mode_t();
- layer.align_corners = reader.boolean();
- });
- register( 0x0B, 'softmax', 'Activation');
- register( 0x0C, 'transpose', 'Transform', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.perm = reader.runtime_shape_t();
- });
- register( 0x0D, 'strided_slice', 'Tensor', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.begin = reader.runtime_shape_t();
- layer.end = reader.runtime_shape_t();
- layer.strides = reader.runtime_shape_t();
- });
- register( 0x0E, 'unary', '', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.unary_op = reader.unary_op_t();
- });
- register( 0x0F, 'quantized_conv2d', 'Layer', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.groups = reader.int32();
- layer.out_channels = reader.int32();
- layer.padding_h = reader.padding();
- layer.padding_w = reader.padding();
- layer.filter_h = reader.int32();
- layer.filter_w = reader.int32();
- layer.stride_h = reader.int32();
- layer.stride_w = reader.int32();
- layer.dilation_h = reader.int32();
- layer.dilation_w = reader.int32();
- layer.input_offset = reader.int32();
- layer.filter_offset = reader.int32();
- layer.output_mul = reader.int32();
- layer.output_shift = reader.int32();
- layer.output_offset = reader.int32();
- const bias = reader.span('int32', [layer.out_channels]);
- if (bias) {
- layer.inputs.push({ name: 'bias', value: [bias] });
- }
- const weights = reader.span('uint8', [layer.out_channels, layer.inputs[0].value[0].shape[1] / layer.groups, layer.filter_h, layer.filter_w]);
- if (weights) {
- layer.inputs.push({ name: 'weights', value: [weights] });
- }
- });
- register( 0x10, 'quantized_matmul', '', (layer, reader) => {
- layer.inputs = [
- reader.parameter('a'),
- reader.parameter('b'),
- ];
- layer.outputs = [reader.parameter('output')];
- layer.a_rows = reader.int32();
- layer.a_cols = reader.int32();
- layer.b_cols = reader.int32();
- layer.inputs[1].value[0].shape = [layer.a_cols, layer.b_cols];
- layer.input_a_offset = reader.int32();
- layer.input_b_offset = reader.int32();
- layer.output_mul = reader.int32();
- layer.output_shift = reader.int32();
- layer.output_offset = reader.int32();
- const bias = reader.span('int32', [layer.b_cols]);
- if (bias) {
- layer.inputs.push({ name: 'bias', value: [bias] });
- }
- });
- register( 0x11, 'quantized_binary', '', (layer, reader) => {
- layer.inputs = [
- reader.parameter('a'),
- reader.parameter('b')
- ];
- layer.outputs = [reader.parameter('outputs')];
- layer.binary_op = reader.binary_op_t();
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.inputs[1].value[0].shape = reader.runtime_shape_t();
- layer.outputs[0].value[0].shape = reader.runtime_shape_t();
- layer.input_a_offset = reader.int32();
- layer.input_a_mul = reader.int32();
- layer.input_a_shift = reader.int32();
- layer.input_b_offset = reader.int32();
- layer.input_b_mul = reader.int32();
- layer.input_b_shift = reader.int32();
- layer.output_offset = reader.int32();
- layer.output_mul = reader.int32();
- layer.output_shift = reader.int32();
- });
- register( 0x12, 'table_lookup1d', '', (layer, reader) => {
- layer.inputs = [reader.parameter('input'), reader.parameter('table')];
- layer.outputs = [reader.parameter('output')];
- });
- register( 0x13, 'conv2d_transpose', 'Layer', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.groups = reader.int32();
- layer.out_channels = reader.int32();
- layer.padding_h = reader.padding();
- layer.padding_w = reader.padding();
- layer.filter_h = reader.int32();
- layer.filter_w = reader.int32();
- layer.stride_h = reader.int32();
- layer.stride_w = reader.int32();
- layer.dilation_h = reader.int32();
- layer.dilation_w = reader.int32();
- layer.fused_activation = [reader.float32(), reader.float32()];
- const weights_shape = [layer.out_channels, layer.inputs[0].value[0].shape[1] / layer.groups, layer.filter_h, layer.filter_w];
- const weights_size = 4 * weights_shape.reduce((a, b) => a * b);
- layer.inputs.push({
- name: 'weights',
- value: [{
- name: '',
- datatype: 'float32',
- shape: weights_shape,
- data: reader.read(weights_size)
- }]
- });
- const bias_shape = [layer.out_channels];
- const bias_size = 4 * layer.out_channels;
- layer.inputs.push({
- name: 'bias',
- value: [{
- name: '',
- datatype: 'float32',
- shape: bias_shape,
- data: reader.read(bias_size)
- }]
- });
- });
- register( 0x14, 'nnil_unary_method', '', (layer, reader, size) => {
- const position = reader.position;
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.body = reader.read(size - (reader.position - position));
- });
- register(0x1001, 'cpu_conv2d', 'Layer', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.groups = reader.int32();
- layer.out_channels = reader.int32();
- layer.padding_h = reader.padding();
- layer.padding_w = reader.padding();
- layer.filter_h = reader.int32();
- layer.filter_w = reader.int32();
- layer.stride_h = reader.int32();
- layer.stride_w = reader.int32();
- layer.dilation_h = reader.int32();
- layer.dilation_w = reader.int32();
- layer.fused_activation = [reader.float32(), reader.float32()];
- });
- register(0x1002, 'cpu_depthwise_conv2d', 'Layer', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.out_channels = reader.int32();
- layer.padding_h = reader.padding();
- layer.padding_w = reader.padding();
- layer.filter_h = reader.int32();
- layer.filter_w = reader.int32();
- layer.stride_h = reader.int32();
- layer.stride_w = reader.int32();
- layer.dilation_h = reader.int32();
- layer.dilation_w = reader.int32();
- layer.fused_activation = [reader.float32(), reader.float32()];
- });
- register(0x1003, 'cpu_reduce_window2d', 'Pool', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.reduce_op = reader.reduce_op_t();
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.padding_h = reader.padding();
- layer.padding_w = reader.padding();
- layer.filter_h = reader.int32();
- layer.filter_w = reader.int32();
- layer.stride_h = reader.int32();
- layer.stride_w = reader.int32();
- layer.dilation_h = reader.int32();
- layer.dilation_w = reader.int32();
- layer.fused_activation = [reader.float32(), reader.float32()];
- });
- register(0x1004, 'cpu_quantized_conv2d', 'Layer', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.groups = reader.int32();
- layer.out_channels = reader.int32();
- layer.padding_h = reader.padding();
- layer.padding_w = reader.padding();
- layer.filter_h = reader.int32();
- layer.filter_w = reader.int32();
- layer.stride_h = reader.int32();
- layer.stride_w = reader.int32();
- layer.dilation_h = reader.int32();
- layer.dilation_w = reader.int32();
- layer.input_offset = reader.int32();
- layer.filter_offset = reader.int32();
- layer.output_mul = reader.int32();
- layer.output_shift = reader.int32();
- layer.output_offset = reader.int32();
- });
- register(0x1005, 'cpu_quantized_depthwise_conv2d', 'Layer', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- layer.out_channels = reader.int32();
- layer.padding_h = reader.padding();
- layer.padding_w = reader.padding();
- layer.filter_h = reader.int32();
- layer.filter_w = reader.int32();
- layer.stride_h = reader.int32();
- layer.stride_w = reader.int32();
- layer.dilation_h = reader.int32();
- layer.dilation_w = reader.int32();
- layer.input_offset = reader.int32();
- layer.filter_offset = reader.int32();
- layer.output_mul = reader.int32();
- layer.output_shift = reader.int32();
- layer.output_offset = reader.int32();
- });
- register(0x2001, 'kpu_upload', '', (layer, reader) => {
- layer.inputs = [reader.parameter('input')];
- layer.outputs = [reader.parameter('output')];
- layer.inputs[0].value[0].shape = reader.runtime_shape_t();
- });
- register(0x2002, 'kpu_conv2d', 'Layer', (layer, reader) => {
- layer.outputs = [reader.parameter('output')];
- layer.batches = reader.int32();
- layer.reserved0 = reader.int32();
- layer.interrupt_enabe = reader.uint64_bits({ int_en: 0, ram_flag: 1, full_add: 2, depth_wise_layer: 3 });
- const image_src_addr = reader.uint32();
- const image_dst_addr = reader.uint32();
- layer.inputs = [{ name: 'input', value: [{ name: `kpu:${image_src_addr}` }] }];
- const outputs = [{ name: 'output', value: [{ name: `kpu:${image_dst_addr}` }] }];
- layer.outputs[0].value.push(outputs[0].value[0]);
- // layer.outputs = layer.flags & 1 ? layer.outputs : outputs;
- layer.image_channel_num = reader.uint64_bits({ i_ch_num: 0, o_ch_num: 32, o_ch_num_coef: 48 });
- layer.image_size = reader.uint64_bits({ i_row_wid: 0, i_col_high: 10, o_row_wid: 32, o_col_high : 42 });
- layer.kernel_pool_type_cfg = reader.uint64_bits({ kernel_type: 0, pad_type: 3, pool_type: 4, first_stride: 8, bypass_conv: 9, load_para: 10, dma_burst_size: 16, pad_value: 24, bwsx_base_addr: 32 });
- layer.kernel_load_cfg = reader.uint64_bits({ load_coor: 0, load_time: 1, para_size: 15, para_start_addr: 32 });
- layer.kernel_offset = reader.uint64_bits({ coef_column_offset: 0, coef_row_offset: 4 });
- layer.kernel_calc_type_cfg = reader.uint64_bits({ channel_switch_addr: 0, row_switch_addr: 16, coef_size: 20, coef_group: 28, load_act: 31, active_addr: 32 });
- layer.write_back_cfg = reader.uint64_bits({ wb_channel_switch_addr: 0, wb_row_switch_addr: 16, wb_group: 20 });
- layer.conv_value = reader.uint64_bits({ shr_w: 0, shr_x: 4, arg_w: 8, arg_x: 32 });
- layer.conv_value2 = reader.uint64_bits({ arg_add: 0 });
- layer.dma_parameter = reader.uint64_bits({ send_data_out: 0, reserved: 1, channel_byte_num: 16, dma_total_byte: 32 });
- layer.chain = [];
- const ic = layer.image_channel_num.i_ch_num + 1;
- const oc = layer.image_channel_num.o_ch_num + 1;
- layer.outputs[0].value[0].shape = [layer.image_size.o_row_wid + 1, layer.image_size.o_col_high + 1, oc];
- const filter = [1, 3][layer.kernel_pool_type_cfg.kernel_type];
- const weights_shape = layer.interrupt_enabe.depth_wise_layer ? [oc, filter, filter] : [ic, oc, filter, filter];
- reader.skip(layer.kernel_pool_type_cfg.bwsx_base_addr);
- delete layer.kernel_pool_type_cfg.bwsx_base_addr;
- const batch_norm = {
- type: { name: 'batch_norm', category: 'Normalization' },
- weights: []
- };
- batch_norm.weights = new Array(oc);
- for (let i = 0; i < oc; i++) {
- batch_norm.weights[i] = reader.uint64_bits({ norm_mul: 0, norm_add: 24, norm_shift: 56, reserved: 60 });
- delete batch_norm.weights[i].reserved;
- }
- layer.chain.push(batch_norm);
- reader.skip(layer.kernel_calc_type_cfg.active_addr);
- delete layer.kernel_calc_type_cfg.active_addr;
- const activation = reader.kpu_activate_table_t();
- activation.type = { name: 'activation', category: 'Activation' };
- layer.chain.push(activation);
- reader.skip(layer.kernel_load_cfg.para_start_addr);
- delete layer.kernel_load_cfg.para_start_addr;
- const weights = reader.span('uint8', weights_shape);
- if (weights) {
- layer.inputs.push({ name: 'weights', value: [weights] });
- }
- });
- /* eslint-enable space-in-parens */
- for (const layer of layers) {
- const type = types.get(layer.opcode);
- if (!type) {
- throw new kmodel.Error(`Unsupported version '${this.version}' layer type '${layer.type}'.`);
- }
- if (!type.callback) {
- throw new kmodel.Error(`Unsupported version '${this.version}' layer '${type.type.name}'.`);
- }
- layer.type = type.type;
- reader.seek(layer.offset);
- if (type.callback) {
- type.callback(layer, reader, layer.body_size);
- }
- delete layer.offset;
- delete layer.body_size;
- delete layer.opcode;
- }
- for (const input of inputs) {
- layers.unshift({
- type: { name: 'INPUT' },
- outputs: [input]
- });
- }
- for (const output of outputs) {
- layers.push({
- type: { name: 'OUTPUT' },
- inputs: [output]
- });
- }
- this.modules.push({
- name: '',
- layers
- });
- break;
- }
- case 5:
- case 6:
- case 7: {
- let reader = null;
- switch (this.version) {
- case 5: reader = new kmodel.BinaryReader.v5(this.stream); break;
- case 6: reader = new kmodel.BinaryReader.v6(this.stream); break;
- case 7: reader = new kmodel.BinaryReader.v7(this.stream); break;
- default: throw new kmodel.Error(`Unsupported model version '${this.version}'.`);
- }
- const model_header = reader.model_header();
- this.modules = new Array(model_header.modules);
- for (let i = 0; i < this.modules.length; i++) {
- const module_header = reader.module_header();
- const mempools = new Array(module_header.mempools || 0);
- for (let j = 0; j < mempools.length; j++) {
- mempools[j] = reader.mempool_desc();
- }
- const shared_mempools = new Array(module_header.shared_mempools || 0);
- for (let j = 0; j < shared_mempools.length; j++) {
- shared_mempools[i] = reader.mempool_desc();
- }
- const function_headers = new Array(module_header.functions);
- const functions = new Array(module_header.functions);
- for (let j = 0; j < functions.length; j++) {
- const position = reader.position;
- let inputs = [];
- let outputs = [];
- if (this.version === 5) {
- const function_header = reader.function_header();
- inputs = new Array(function_header.inputs || 0);
- for (let k = 0; k < inputs.length; k++) {
- inputs[k] = reader.parameter(`input${k === 0 ? '' : (k + 1)}`);
- }
- for (let k = 0; k < inputs.length; k++ || 0) {
- inputs[k].value[0].shape = reader.shape();
- }
- outputs = new Array(function_header.outputs || 0);
- for (let k = 0; k < outputs.length; k++) {
- outputs[k] = reader.parameter(`output${k === 0 ? '' : (k + 1)}`);
- }
- for (let k = 0; k < outputs.length; k++) {
- outputs[k].value[0].shape = reader.shape();
- }
- reader.align(8);
- const size = reader.position - position;
- if (function_header.size > size) {
- reader.skip(function_header.size - size);
- }
- function_headers[j] = function_header;
- } else {
- const func_start = reader.position;
- const function_header = reader.function_header();
- const header_size = reader.position - func_start;
- const remaining_size = function_header.size - header_size;
- if (remaining_size > 0) {
- reader.skip(remaining_size);
- }
- function_headers[j] = function_header;
- }
- functions[j] = {
- type: { name: 'Unknown' },
- inputs,
- outputs
- };
- }
- const sections = new Map();
- for (let j = 0; j < module_header.sections; j++) {
- const section_header = reader.section_header();
- reader.skip(section_header.body_start);
- const body = reader.read(section_header.body_size);
- const section = {
- reader: base.BinaryReader.open(body),
- flags: section_header.flags
- };
- reader.align(8);
- sections.set(section_header.name, section);
- }
- for (let j = 0; j < function_headers.length; j++) {
- const function_header = function_headers[j];
- const reader = sections.get('.text').reader;
- reader.seek(function_header.entrypoint);
- const size = function_header.text_size;
- function_header.text = reader.read(size);
- const layer = functions[i];
- switch (module_header.type) {
- case 'stackvm': {
- layer.type = { name: 'stackvm' };
- let reader = null;
- const buffer = function_header.text;
- switch (this.version) {
- case 5: reader = new kmodel.BytecodeReader.v5(buffer); break;
- case 6: reader = new kmodel.BytecodeReader.v6(buffer); break;
- case 7: reader = new kmodel.BytecodeReader.v6(buffer); break;
- default: throw new kmodel.Error(`Unsupported model version '${this.version}'.`);
- }
- reader = null;
- if (reader) {
- layer.operations = reader.read();
- layer.tensor_operations = layer.operations.filter((op) => op.name === 'tensor');
- }
- break;
- }
- case 'k210':
- case 'k230':
- case 'k510':
- break;
- default:
- throw new kmodel.Error(`Unsupported module type '${module_header.type}'.`);
- }
- }
- this.modules[i] = {
- type: module_header.type,
- name: this.modules.length > 1 ? i.toString() : '',
- layers: functions
- };
- }
- break;
- }
- default: {
- throw new kmodel.Error(`Unsupported model version '${this.version}'.`);
- }
- }
- delete this.stream;
- }
- };
- kmodel.BinaryReader = class {
- constructor(data) {
- this._reader = base.BinaryReader.open(data);
- }
- get position() {
- return this._reader.position;
- }
- seek(position) {
- this._reader.seek(position);
- }
- skip(offset) {
- this._reader.skip(offset);
- }
- align(size) {
- this._reader.align(size);
- }
- read(length) {
- return this._reader.read(length);
- }
- boolean() {
- return this._reader.boolean();
- }
- byte() {
- return this._reader.byte();
- }
- int8() {
- return this._reader.int8();
- }
- int16() {
- return this._reader.int16();
- }
- int32() {
- return this._reader.int32();
- }
- uint16() {
- return this._reader.uint16();
- }
- uint32() {
- return this._reader.uint32();
- }
- uint64() {
- return this._reader.uint64().toNumber();
- }
- float32() {
- return this._reader.float32();
- }
- uint64_bits(fields) {
- const buffer = this.read(8);
- fields = Object.entries(fields);
- fields.push([null, Math.min(64, fields[fields.length - 1][1] + 56)]);
- const obj = {};
- for (let i = 0; i < fields.length - 1; i++) {
- const current = fields[i];
- const next = fields[i + 1];
- const [key, start] = current;
- const [, end] = next;
- let value = 0;
- let position = start;
- while (position < end) {
- const offset = (position / 8) >> 0;
- const start = (position & 7);
- const count = Math.min((offset + 1) * 8, end) - position;
- value |= ((buffer[offset] >>> start) & ((1 << count) - 1)) << (position - fields[i][1]);
- position += count;
- }
- obj[key] = value;
- }
- return obj;
- }
- };
- kmodel.BinaryReader.v3 = class extends kmodel.BinaryReader {
- constructor(buffer) {
- super(buffer);
- this.skip(4);
- }
- kpu_model_header_t() {
- return {
- flags: this.uint32(),
- arch: this.uint32(),
- layers_length: this.uint32(),
- max_start_address: this.uint32(),
- main_mem_usage: this.uint32(),
- output_count: this.uint32()
- };
- }
- kpu_model_output_t(name) {
- return {
- address: [this.parameter(name)],
- size: this.uint32()
- };
- }
- kpu_model_layer_header_t() {
- return {
- type: this.uint32(),
- body_size: this.uint32()
- };
- }
- argument(memory_type) {
- memory_type = memory_type || 'main';
- const address = this.uint32();
- return { name: `${memory_type}:${address}` };
- }
- parameter(name, memory_type) {
- return { name, value: [this.argument(memory_type)] };
- }
- };
- kmodel.BinaryReader.v4 = class extends kmodel.BinaryReader {
- constructor(buffer) {
- super(buffer);
- this.skip(8);
- this._memory_types = ['const', 'main', 'kpu'];
- this._datatypes = ['float32', 'uint8'];
- }
- memory_type_t() {
- const value = this.uint32();
- return this._memory_types[value];
- }
- datatype_t() {
- const value = this.uint32();
- return this._datatypes[value];
- }
- memory_range() {
- return {
- memory_type: this.memory_type_t(),
- datatype: this.datatype_t(),
- start: this.uint32(),
- size: this.uint32()
- };
- }
- argument() {
- const memory = this.memory_range();
- const value = {
- name: `${memory.memory_type}:${memory.start}`,
- datatype: memory.datatype
- };
- if (memory.memory_type === 'const') {
- value.data = this._constants.slice(memory.start, memory.start + memory.size);
- switch (value.datatype) {
- case 'uint8': value.shape = [value.data.length]; break;
- case 'float32': value.shape = [value.data.length >> 2]; break;
- default: break;
- }
- }
- return value;
- }
- parameter(name) {
- return { name, value: [this.argument()] };
- }
- runtime_shape_t() {
- return [this.uint32(), this.uint32(), this.uint32(), this.uint32()];
- }
- padding() {
- return { before: this.int32(), after: this.int32() };
- }
- runtime_paddings_t() {
- return [this.padding(), this.padding(), this.padding(), this.padding()];
- }
- scalar() {
- return {
- datatype_t: this.uint32(),
- storage: this.read(4)
- };
- }
- kpu_activate_table_t() {
- const value = {};
- value.activate_para = new Array(16);
- for (let i = 0; i < 16; i++) {
- value.activate_para[i] = this.uint64_bits({ shift_number: 0, y_mul: 8, x_start: 24, reserved: 60 });
- delete value.activate_para[i].reserved;
- }
- for (let i = 0; i < 16; i++) {
- value.activate_para[i].bias = this.int8();
- }
- return value;
- }
- unary_op_t() {
- const value = this.uint32();
- return ['abs', 'ceil', 'cos', 'exp', 'floor', 'log', 'neg', 'rsqrt', 'sin', 'square'][value];
- }
- binary_op_t() {
- const value = this.uint32();
- return ['add', 'sub', 'mul', 'div', 'min', 'max'][value];
- }
- reduce_op_t() {
- const value = this.uint32();
- return ['mean', 'min', 'max', 'sum'][value];
- }
- image_resize_mode_t() {
- const value = this.uint32();
- return ['bilinear', 'nearest_neighbor'][value];
- }
- constants(size) {
- this._constants = this.read(size);
- }
- span(datatype, shape) {
- const size = shape.reduce((a, b) => a * b, 1);
- const itemsize = { 'int32': 4, 'uint8': 1 };
- const buffer = this.read(itemsize[datatype] * size);
- if (!buffer.every((value) => value === 0)) {
- const array = {};
- array.name = '';
- array.datatype = datatype;
- array.shape = shape;
- array.data = buffer;
- return array;
- }
- return null;
- }
- };
- kmodel.BinaryReader.v5 = class extends kmodel.BinaryReader {
- constructor(buffer) {
- super(buffer);
- this.skip(8);
- this._datatypes = ['int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64', 'float16', 'float32', 'float64', 'bfloat16'];
- this._memory_locations = new Map([[0, 'input'], [1, 'output'], [2, 'rdata'], [3, 'data'], [4, 'shared_data'], [64, 'kpu']]);
- }
- model_header() {
- const model_header = {
- header_size: this.uint32(),
- flags: this.uint32(),
- alignment: this.uint32(),
- modules: this.uint32(),
- entry_module: this.uint32(),
- entry_function: this.uint32()
- };
- if (model_header.header_size < 32) {
- throw new kmodel.Error(`Invalid header size '${model_header.header_size}'.`);
- }
- if (model_header.header_size > this.position) {
- this.skip(model_header.header_size - this.position);
- }
- delete model_header.header_size;
- return model_header;
- }
- module_type_t() {
- const buffer = this.read(16);
- const decoder = new TextDecoder('ascii');
- const text = decoder.decode(buffer);
- return text.replace(/\0.*$/, '');
- }
- module_header() {
- const start = this.position;
- const module_header = {
- type: this.module_type_t(),
- version: this.uint32(),
- header_size: this.uint32(),
- size: this.uint32(),
- mempools: this.uint32(),
- shared_mempools: this.uint32(),
- sections: this.uint32(),
- functions: this.uint32(),
- reserved0: this.uint32()
- };
- if (module_header.header_size > (this.position - start)) {
- this.skip(module_header.header_size - (this.position - start));
- }
- return module_header;
- }
- mempool_desc() {
- return {
- location: this.byte(),
- reserved0: this.read(3),
- size: this.uint32()
- };
- }
- section_header() {
- const buffer = this.read(16);
- const decoder = new TextDecoder('ascii');
- const name = decoder.decode(buffer);
- return {
- name: name.replace(/\0.*$/, ''),
- flags: this.uint32(),
- body_start: this.uint32(),
- body_size: this.uint32(),
- reserved0: this.uint32()
- };
- }
- function_header() {
- const position = this.position;
- const function_header = {
- header_size: this.uint32(),
- size: this.uint32(),
- input_pool_size: this.uint32(),
- output_pool_size: this.uint32(),
- inputs: this.uint32(),
- outputs: this.uint32(),
- entrypoint: this.uint32(),
- text_size: this.uint32()
- };
- const header_size = this.position - position;
- if (function_header.header_size > header_size) {
- this.skip(function_header.header_size - header_size);
- }
- return function_header;
- }
- memory_location_t() {
- const value = this.byte();
- if (!this._memory_locations.has(value)) {
- throw new kmodel.Error(`Unsupported memory location '${value}'.`);
- }
- return this._memory_locations.get(value);
- }
- datatype_t() {
- const value = this.byte();
- return this._datatypes[value];
- }
- memory_range() {
- return {
- memory_location: this.memory_location_t(),
- datatype: this.datatype_t(),
- shared_module: this.uint16(),
- start: this.uint32(),
- size: this.uint32()
- };
- }
- argument() {
- const memory = this.memory_range();
- const value = {
- name: `${memory.memory_location}:${memory.start}`,
- datatype: memory.datatype
- };
- /*
- if (memory.memory_type === 'const') {
- value.data = constants.slice(memory.start, memory.start + memory.size);
- switch (value.datatype) {
- case 'uint8': value.shape = [ value.data.length ]; break;
- case 'float32': value.shape = [ value.data.length >> 2 ]; break;
- default: break;
- }
- }
- */
- return value;
- }
- parameter(name) {
- return { name, value: [this.argument()] };
- }
- shape() {
- const array = new Array(this.uint32());
- for (let i = 0; i < array.length; i++) {
- array[i] = this.uint32();
- }
- return array;
- }
- };
- kmodel.BinaryReader.v6 = class extends kmodel.BinaryReader.v5 {
- model_header() {
- return {
- flags: this.uint32(),
- alignment: this.uint32(),
- modules: this.uint32(),
- entry_module: this.uint32(),
- entry_function: this.uint32(),
- reserved0: this.uint32()
- };
- }
- module_header() {
- return {
- type: this.module_type_t(),
- version: this.uint32(),
- size: this.uint32(),
- sections: this.uint32(),
- functions: this.uint32()
- };
- }
- function_header() {
- return {
- parameters: this.uint32(),
- entrypoint: this.uint32(),
- text_size: this.uint32(),
- size: this.uint32(),
- sections: this.uint32(),
- reserved0: this.uint32(),
- };
- }
- section_header() {
- const buffer = this.read(16);
- const decoder = new TextDecoder('ascii');
- const name = decoder.decode(buffer);
- return {
- name: name.replace(/\0.*$/, ''),
- size: this.uint32(),
- flags: this.uint32(),
- body_start: this.uint32(),
- body_size: this.uint32(),
- memory_size: this.uint32(),
- reserved0: this.uint32()
- };
- }
- deserialize_datatype() {
- const typecode = this.byte();
- if (typecode === 100) { // dt_pointer
- const elem_type = this.deserialize_datatype();
- return { type: 'pointer', elem_type };
- } else if (typecode === 101) { // dt_valuetype
- const uuid = this.read(16);
- const size_bytes = this.uint32();
- return { type: 'valuetype', uuid, size_bytes };
- } else if (typecode >= 0 && typecode <= 12) {
- const types = ['bool', 'int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64', 'float16', 'float32', 'float64', 'bfloat16'];
- return { type: 'prim', name: types[typecode] || `unknown_${typecode}` };
- }
- throw new kmodel.Error(`Unknown datatype typecode: ${typecode}`);
- }
- deserialize_type() {
- const token = this.byte();
- switch (token) {
- case 0: // type_sig_invalid
- return { type: 'invalid' };
- case 1: // type_sig_any
- return { type: 'any' };
- case 2: { // type_sig_tensor
- const elem_type = this.deserialize_datatype();
- const is_scalar = this.byte() === 0;
- const shape = [];
- if (!is_scalar) {
- let dim_token = 0;
- while ((dim_token = this.byte()) !== 255) { // type_sig_end
- if (dim_token === 1) { // dim_fixed
- shape.push(this.uint32());
- } else if (dim_token === 2) { // dim_unknown
- shape.push(-1);
- } else {
- throw new kmodel.Error(`Invalid dim token: ${dim_token}`);
- }
- }
- }
- return { type: 'tensor', elem_type, shape, is_scalar };
- }
- case 3: { // type_sig_tuple
- const fields = [];
- while (this.peek() !== 255) { // type_sig_end
- fields.push(this.deserialize_type());
- }
- this.skip(1); // skip end token
- return { type: 'tuple', fields };
- }
- case 4: // type_sig_callable
- throw new kmodel.Error('Callable types not supported');
- default:
- throw new kmodel.Error(`Unknown type signature token: ${token}`);
- }
- }
- peek() {
- const value = this.byte();
- this.seek(this.position - 1);
- return value;
- }
- };
- kmodel.BinaryReader.v7 = class extends kmodel.BinaryReader.v6 {
- module_header() {
- return {
- type: this.module_type_t(),
- version: this.uint32(),
- sections: this.uint32(),
- functions: this.uint32(),
- reserved0: this.uint32(),
- size: this.uint64(),
- };
- }
- function_header() {
- return {
- parameters: this.uint32(),
- sections: this.uint32(),
- entrypoint: this.uint64(),
- text_size: this.uint64(),
- size: this.uint64(),
- };
- }
- section_header() {
- const buffer = this.read(16);
- const decoder = new TextDecoder('ascii');
- const name = decoder.decode(buffer);
- return {
- name: name.replace(/\0.*$/, ''),
- flags: this.uint32(),
- reserved0: this.uint32(),
- size: this.uint64(),
- body_start: this.uint64(),
- body_size: this.uint64(),
- memory_size: this.uint64(),
- };
- }
- };
- kmodel.BytecodeReader = class {
- constructor(buffer) {
- this._reader = base.BinaryReader.open(buffer);
- }
- read() {
- const operations = [];
- while (this._reader.position < this._reader.length) {
- const position = this._reader.position;
- const opcode = this._reader.byte();
- if (!this._opcodes.has(opcode)) {
- throw new kmodel.Error(`Unknown opcode '${opcode}'.`);
- }
- const name = this._opcodes.get(opcode);
- const operation = { name, position };
- this.operation(operation);
- // console.log(JSON.stringify(operation));
- operations.push(operation);
- if (name === 'ret') {
- break;
- }
- }
- return operations;
- }
- strings() {
- // Read strings until we encounter a null byte as the first character
- const array = [];
- while (this._reader.position < this._reader.length) {
- // Peek at next byte
- const byte = this._reader.byte();
- if (byte === 0) {
- break; // End of array
- }
- // Put the byte back by moving position back
- this._reader.seek(this._reader.position - 1);
- array.push(this.string());
- }
- return array;
- }
- };
- kmodel.BytecodeReader.v5 = class extends kmodel.BytecodeReader {
- constructor(buffer) {
- super(buffer);
- this._opcodes = new Map([
- [0, 'nop'], [1, 'ldnull'], [2, 'ldc_i4'], [3, 'ldc_i4_0'], [4, 'ldc_i4_1'],
- [5, 'ldc_r4'], [6, 'ldind_i1'], [7, 'ldind_i2'], [8, 'ldind_i4'], [9, 'ldind_i'],
- [10, 'ldind_u1'], [11, 'ldind_u2'], [12, 'ldind_u4'], [13, 'ldind_u'],
- [14, 'ldind_br2'], [15, 'ldind_r4'], [16, 'stind_i1'], [17, 'stind_i2'],
- [18, 'stind_i4'], [19, 'stind_i'], [20, 'stind_br2'], [21, 'stind_r4'],
- [22, 'lea_gp'], [23, 'lea_buffer'], [24, 'ldelem_i1'], [25, 'ldelem_i2'],
- [26, 'ldelem_i4'], [27, 'ldelem_i'], [28, 'ldelem_u1'], [29, 'ldelem_u2'],
- [30, 'ldelem_u4'], [0x1F, 'ldelem_u'], [0x20, 'ldelem_br2'], [33, 'ldelem_r4'],
- [34, 'stelem_i1'], [35, 'stelem_i2'], [36, 'stelem_i4'], [37, 'stelem_i'],
- [38, 'stelem_br2'], [39, 'stelem_r4'], [40, 'ldarg'], [41, 'ldarg_0'],
- [42, 'ldarg_1'], [43, 'ldarg_2'], [44, 'ldarg_3'], [45, 'ldarg_4'],
- [46, 'ldarg_5'], [47, 'dup'], [48, 'pop'], [0x31, 'stshape'], [50, 'stpaddings'],
- [51, 'neg'], [52, 'add'], [53, 'sub'], [54, 'mul'], [55, 'div'], [56, 'div_u'],
- [57, 'rem'], [58, 'rem_u'], [59, 'and'], [60, 'or'], [61, 'xor'], [62, 'not'],
- [63, 'shl'], [64, 'shr'], [65, 'shr_u'], [66, 'clt'], [67, 'clt_u'],
- [68, 'cle'], [69, 'cle_u'], [70, 'ceq'], [71, 'cge'], [72, 'cge_u'],
- [73, 'cgt'], [74, 'cgt_u'], [75, 'cne'], [76, 'conv_i1'], [77, 'conv_i2'],
- [78, 'conv_i4'], [79, 'conv_i'], [80, 'conv_u1'], [81, 'conv_u2'],
- [82, 'conv_u4'], [83, 'conv_u'], [84, 'conv_br2'], [85, 'conv_r4'],
- [86, 'br'], [87, 'br_true'], [88, 'br_false'], [89, 'ret'], [90, 'call'],
- [91, 'ecall'], [0x5C, 'throw'], [0x5D, 'break'], [0x5E, 'tensor']
- ]);
- this._tensorFunctions = new Map([
- [0x0000, { name: 'batch_to_space', category: 'Transform' }],
- [0x0001, { name: 'binary', category: '' }],
- [0x0002, { name: 'broadcast', category: '' }],
- [0x0003, { name: 'call', category: '' }],
- [0x0004, { name: 'clamp', category: 'Activation' }],
- [0x0005, { name: 'conv2d', category: 'Layer' }],
- [0x0006, { name: 'conv2d_transpose', category: 'Layer' }],
- [0x0007, { name: 'convert', category: '' }],
- [0x0008, { name: 'copy', category: '' }],
- [0x0009, { name: 'cumsum', category: '' }],
- [0x000A, { name: 'dequantize', category: 'Quantization' }],
- [0x000B, { name: 'equal', category: '' }],
- [0x000C, { name: 'gather', category: 'Transform' }],
- [0x000D, { name: 'gather_nd', category: 'Transform' }],
- [0x000E, { name: 'hardmax', category: 'Activation' }],
- [0x000F, { name: 'logistic', category: 'Activation' }],
- [0x0010, { name: 'lut1d', category: '' }],
- [0x0011, { name: 'matmul', category: 'Layer' }],
- [0x0012, { name: 'onehot', category: '' }],
- [0x0013, { name: 'pad', category: '' }],
- [0x0014, { name: 'quantize', category: 'Quantization' }],
- [0x0015, { name: 'random_normal', category: '' }],
- [0x0016, { name: 'random_uniform', category: '' }],
- [0x0017, { name: 'reduce', category: 'Reduce' }],
- [0x0018, { name: 'reduce_arg', category: 'Reduce' }],
- [0x0019, { name: 'reduce_prod', category: 'Reduce' }],
- [0x001A, { name: 'reduce_window2d', category: 'Pool' }],
- [0x001B, { name: 'resize_image', category: 'Transform' }],
- [0x001C, { name: 'roi_align', category: '' }],
- [0x001D, { name: 'sigmoid', category: 'Activation' }],
- [0x001E, { name: 'slice', category: 'Tensor' }],
- [0x001F, { name: 'softmax', category: 'Activation' }],
- [0x0020, { name: 'space_to_batch', category: 'Transform' }],
- [0x0021, { name: 'take', category: '' }],
- [0x0022, { name: 'ternary', category: '' }],
- [0x0023, { name: 'topk', category: '' }],
- [0x0024, { name: 'transpose', category: 'Transform' }],
- [0x0025, { name: 'trilu', category: '' }],
- [0x0026, { name: 'unary', category: '' }]
- ]);
- }
- operation(operation) {
- switch (operation.name) {
- case 'ldc_i4':
- operation.value = this._reader.int32();
- break;
- case 'ldc_r4':
- operation.imm = this._reader.float32();
- break;
- case 'lea_gp':
- operation.gpid = this._reader.byte();
- operation.offset = this._reader.int32();
- break;
- case 'lea_buffer':
- operation.location = this._reader.byte();
- operation.subres_id = this._reader.byte();
- operation.offset = this._reader.int32();
- break;
- case 'ldarg':
- operation.index = this._reader.uint32();
- break;
- case 'stpaddings':
- operation.rpaddings = this._reader.byte();
- operation.rank = this._reader.byte();
- break;
- case 'stshape':
- operation.rshape = this._reader.byte();
- operation.rank = this._reader.byte();
- break;
- case 'br':
- case 'br_true':
- case 'br_false':
- operation.target = this._reader.int32();
- break;
- case 'call':
- operation.args = this._reader.byte();
- operation.target = this._reader.int32();
- break;
- case 'ecall':
- operation.args = this._reader.byte();
- break;
- case 'extcall':
- operation.args = this._reader.uint16();
- operation.is_prim_func = this._reader.byte() !== 0;
- break;
- case 'cuscall':
- operation.registered_name = this.string();
- operation.fields_size = this._reader.uint32();
- this._reader.skip(operation.fields_size);
- operation.args = this._reader.uint16();
- break;
- case 'tensor': {
- operation.tensor_function = this._reader.uint16();
- const func = this._tensorFunctions.get(operation.tensor_function);
- if (func) {
- operation.tensor_name = func.name;
- operation.tensor_category = func.category;
- }
- this.tensor(operation);
- break;
- }
- default:
- break;
- }
- }
- string() {
- // Read null-terminated string
- const bytes = [];
- let byte = this._reader.byte();
- while (byte !== 0) {
- bytes.push(byte);
- byte = this._reader.byte();
- }
- return new TextDecoder('utf-8').decode(new Uint8Array(bytes));
- }
- tensor(operation) {
- switch (operation.tensor_name) {
- case 'binary':
- operation.datatype = this._reader.byte();
- operation.rshape_src1 = this._reader.byte();
- operation.rstride_src1 = this._reader.byte();
- operation.rshape_src2 = this._reader.byte();
- operation.rstride_src2 = this._reader.byte();
- operation.rstride_dest = this._reader.byte();
- operation.binary_op = this._reader.byte();
- operation.fused_clamp_low = this._reader.float32();
- operation.fused_clamp_high = this._reader.float32();
- break;
- case 'bitcast':
- operation.type = this._reader.byte();
- operation.new_type = this._reader.byte();
- break;
- case 'call':
- operation.function_id = this._reader.uint32();
- operation.module_id = this._reader.uint16();
- operation.num_src = this._reader.byte();
- operation.num_dst = this._reader.byte();
- break;
- case 'cast':
- operation.new_type = this._reader.byte();
- operation.cast_mode = this._reader.uint32();
- break;
- case 'compare':
- operation.compare_op = this._reader.byte();
- break;
- case 'concat':
- operation.axis = this._reader.int32();
- break;
- case 'cumsum':
- operation.datatype = this._reader.byte();
- operation.rshape_src = this._reader.byte();
- operation.axis = this._reader.int32();
- operation.exclusive = this._reader.byte() !== 0;
- operation.reverse = this._reader.byte() !== 0;
- break;
- case 'condition':
- operation.can_fold_const_call = this._reader.byte() !== 0;
- break;
- case 'conv2d':
- operation.datatype = this._reader.byte();
- operation.rshape_src = this._reader.byte();
- operation.rstride_src = this._reader.byte();
- operation.rshape_kernel = this._reader.byte();
- operation.rstride_kernel = this._reader.byte();
- operation.rstride_bias = this._reader.byte();
- operation.rstride_dest = this._reader.byte();
- operation.groups = this._reader.uint16();
- operation.stride_h = this._reader.uint16();
- operation.stride_w = this._reader.uint16();
- operation.dilation_h = this._reader.uint16();
- operation.dilation_w = this._reader.uint16();
- operation.fused_clamp_low = this._reader.float32();
- operation.fused_clamp_high = this._reader.float32();
- break;
- case 'conv2d_transpose':
- operation.pad_mode = this._reader.byte();
- break;
- case 'dequantize':
- operation.target_type = this._reader.byte();
- break;
- case 'fake_dequantize':
- operation.target_type = this._reader.byte();
- break;
- case 'fake_quantize':
- operation.target_type = this._reader.byte();
- break;
- case 'gather':
- operation.axis = this._reader.int32();
- break;
- case 'layer_norm':
- operation.axis = this._reader.int32();
- operation.epsilon = this._reader.float32();
- operation.use_mean = this._reader.byte() !== 0;
- break;
- case 'lstm':
- operation.direction = this._reader.uint32();
- operation.layout = this._reader.uint32();
- operation.activations = this.strings();
- break;
- case 'matmul':
- operation.rshape_src1 = this._reader.byte();
- operation.rshape_src2 = this._reader.byte();
- operation.fused_clamp_low = this._reader.float32();
- operation.fused_clamp_high = this._reader.float32();
- break;
- case 'normal':
- operation.type = this._reader.byte();
- break;
- case 'random_normal':
- operation.datatype_dest = this._reader.byte();
- operation.rshape_dest = this._reader.byte();
- operation.mean = this._reader.float32();
- operation.std = this._reader.float32();
- operation.seed = this._reader.float32();
- break;
- case 'normal_like':
- operation.type = this._reader.byte();
- break;
- case 'one_hot':
- operation.one_hot_mode = this._reader.byte();
- break;
- case 'pad':
- operation.datatype = this._reader.byte();
- operation.rshape_src = this._reader.byte();
- operation.rstride_src = this._reader.byte();
- operation.rstride_dest = this._reader.byte();
- operation.rpaddings = this._reader.byte();
- operation.pad_mode = this._reader.byte();
- break;
- case 'quantize':
- operation.target_type = this._reader.byte();
- break;
- case 'quant_param_of':
- operation.quant_mode = this._reader.uint32();
- break;
- case 'range_of':
- operation.is_range_of_weight = this._reader.byte() !== 0;
- break;
- case 'reduce':
- operation.reduce_op = this._reader.byte();
- break;
- case 'reduce_arg':
- operation.reduce_arg_op = this._reader.byte();
- operation.dest_type = this._reader.byte();
- break;
- case 'reduce_window2d':
- operation.reduce_op = this._reader.byte();
- break;
- case 'require':
- operation.message = this.string();
- operation.can_fold_const_call = this._reader.byte() !== 0;
- break;
- case 'resize_image':
- operation.resize_mode = this._reader.byte();
- operation.transformation_mode = this._reader.uint32();
- operation.nearest_mode = this._reader.uint32();
- operation.is_tfresize = this._reader.byte() !== 0;
- break;
- case 'unary':
- operation.unary_op = this._reader.byte();
- break;
- case 'uniform':
- operation.type = this._reader.byte();
- break;
- case 'uniform_like':
- operation.type = this._reader.byte();
- break;
- case 'where':
- operation.is_tf_where = this._reader.byte() !== 0;
- break;
- default:
- break;
- }
- }
- };
- kmodel.BytecodeReader.v6 = class extends kmodel.BytecodeReader.v5 {
- constructor(reader) {
- super(reader);
- this._opcodes = new Map([
- [0, 'nop'], [1, 'ldnull'], [2, 'ldc_i4'], [3, 'ldc_i4_0'], [4, 'ldc_i4_1'],
- [5, 'ldc_r4'], [6, 'ldind_i1'], [7, 'ldind_i2'], [8, 'ldind_i4'], [9, 'ldind_i'],
- [10, 'ldind_u1'], [11, 'ldind_u2'], [12, 'ldind_u4'], [13, 'ldind_u'],
- [14, 'ldind_br2'], [15, 'ldind_r4'], [16, 'stind_i1'], [17, 'stind_i2'],
- [18, 'stind_i4'], [19, 'stind_i'], [20, 'stind_br2'], [21, 'stind_r4'],
- [22, 'lea_gp'], [23, 'ldelem_i1'], [24, 'ldelem_i2'], [25, 'ldelem_i4'],
- [26, 'ldelem_i'], [27, 'ldelem_u1'], [28, 'ldelem_u2'], [29, 'ldelem_u4'],
- [30, 'ldelem_u'], [31, 'ldelem_br2'], [32, 'ldelem_r4'], [33, 'stelem_i1'],
- [34, 'stelem_i2'], [35, 'stelem_i4'], [36, 'stelem_i'], [37, 'stelem_br2'],
- [38, 'stelem_r4'], [39, 'ldarg'], [40, 'ldarg_0'], [41, 'ldarg_1'],
- [42, 'ldarg_2'], [43, 'ldarg_3'], [44, 'ldarg_4'], [45, 'ldarg_5'],
- [46, 'dup'], [47, 'pop'], [48, 'ldlocal'], [49, 'stlocal'], [50, 'ldtuple_elem'],
- [51, 'ldtuple'], [52, 'lddatatype'], [53, 'ldtensor'], [54, 'ldscalar'],
- [55, 'neg'], [56, 'add'], [57, 'sub'], [58, 'mul'], [59, 'div'], [60, 'div_u'],
- [61, 'rem'], [62, 'rem_u'], [63, 'and'], [64, 'or'], [65, 'xor'], [66, 'not'],
- [67, 'shl'], [68, 'shr'], [69, 'shr_u'], [70, 'clt'], [71, 'clt_u'],
- [72, 'cle'], [73, 'cle_u'], [74, 'ceq'], [75, 'cge'], [76, 'cge_u'],
- [77, 'cgt'], [78, 'cgt_u'], [79, 'cne'], [80, 'conv_i1'], [81, 'conv_i2'],
- [82, 'conv_i4'], [83, 'conv_i'], [84, 'conv_u1'], [85, 'conv_u2'],
- [86, 'conv_u4'], [87, 'conv_u'], [88, 'conv_br2'], [89, 'conv_r4'],
- [90, 'br'], [91, 'br_true'], [92, 'br_false'], [93, 'ret'], [94, 'call'],
- [95, 'ecall'], [96, 'extcall'], [97, 'cuscall'], [98, 'throw'], [99, 'break'],
- [100, 'tensor']
- ]);
- this._tensorFunctions = new Map([
- [0, { name: 'batch_normalization', category: 'Normalization' }],
- [1, { name: 'batch_to_space', category: 'Transform' }],
- [2, { name: 'binary', category: '' }],
- [3, { name: 'bitcast', category: '' }],
- [4, { name: 'broadcast', category: '' }],
- [5, { name: 'broadcast_shape', category: 'Shape' }],
- [6, { name: 'bucket_pad', category: '' }],
- [7, { name: 'cast', category: '' }],
- [8, { name: 'celu', category: 'Activation' }],
- [9, { name: 'clamp', category: 'Activation' }],
- [10, { name: 'compare', category: '' }],
- [11, { name: 'concat', category: 'Tensor' }],
- [12, { name: 'condition', category: '' }],
- [13, { name: 'constant_of_shape', category: '' }],
- [14, { name: 'conv2d', category: 'Layer' }],
- [15, { name: 'conv2d_shape', category: 'Shape' }],
- [16, { name: 'conv2d_transpose', category: 'Layer' }],
- [17, { name: 'conv2d_transpose_shape', category: 'Shape' }],
- [18, { name: 'cum_sum', category: '' }],
- [19, { name: 'dequantize', category: 'Quantization' }],
- [20, { name: 'elu', category: 'Activation' }],
- [21, { name: 'erf', category: 'Activation' }],
- [22, { name: 'expand', category: '' }],
- [23, { name: 'fake_dequantize', category: 'Quantization' }],
- [24, { name: 'fake_quantize', category: 'Quantization' }],
- [25, { name: 'fix_shape', category: 'Shape' }],
- [26, { name: 'flatten', category: 'Shape' }],
- [27, { name: 'gather', category: 'Transform' }],
- [28, { name: 'gather_elements', category: 'Transform' }],
- [29, { name: 'gather_nd', category: 'Transform' }],
- [30, { name: 'gelu', category: 'Activation' }],
- [31, { name: 'get_item', category: '' }],
- [32, { name: 'get_paddings', category: '' }],
- [33, { name: 'hardmax', category: 'Activation' }],
- [34, { name: 'hard_sigmoid', category: 'Activation' }],
- [35, { name: 'hard_swish', category: 'Activation' }],
- [36, { name: 'index_of', category: '' }],
- [37, { name: 'instance_normalization', category: 'Normalization' }],
- [38, { name: 'l2_normalization', category: 'Normalization' }],
- [39, { name: 'layer_norm', category: 'Normalization' }],
- [40, { name: 'leaky_relu', category: 'Activation' }],
- [41, { name: 'log_softmax', category: 'Activation' }],
- [42, { name: 'lp_normalization', category: 'Normalization' }],
- [43, { name: 'lrn', category: 'Normalization' }],
- [44, { name: 'lstm', category: 'Layer' }],
- [45, { name: 'mat_mul', category: 'Layer' }],
- [46, { name: 'mat_mul_shape', category: 'Shape' }],
- [47, { name: 'normal' }],
- [48, { name: 'normal_like' }],
- [49, { name: 'one_hot', category: '' }],
- [50, { name: 'pad', category: '' }],
- [51, { name: 'prelu', category: 'Activation' }],
- [52, { name: 'prod', category: '' }],
- [53, { name: 'quantize', category: 'Quantization' }],
- [54, { name: 'quant_param_of', category: 'Quantization' }],
- [55, { name: 'range', category: '' }],
- [56, { name: 'range_of', category: '' }],
- [57, { name: 'rank', category: 'Shape' }],
- [58, { name: 'reduce', category: 'Reduce' }],
- [59, { name: 'reduce_arg', category: 'Reduce' }],
- [60, { name: 'reduce_window2d', category: 'Pool' }],
- [61, { name: 'relu', category: 'Activation' }],
- [62, { name: 'relu6', category: 'Activation' }],
- [63, { name: 'require', category: '' }],
- [64, { name: 'reshape', category: 'Shape' }],
- [65, { name: 'reshape_shape', category: 'Shape' }],
- [66, { name: 'resize_image', category: 'Transform' }],
- [67, { name: 'reverse_sequence', category: '' }],
- [68, { name: 'scatter_nd', category: 'Transform' }],
- [69, { name: 'select', category: '' }],
- [70, { name: 'selu', category: 'Activation' }],
- [71, { name: 'shape_of', category: 'Shape' }],
- [72, { name: 'sigmoid', category: 'Activation' }],
- [73, { name: 'size_of', category: 'Shape' }],
- [74, { name: 'slice', category: 'Tensor' }],
- [75, { name: 'softmax', category: 'Activation' }],
- [76, { name: 'softplus', category: 'Activation' }],
- [77, { name: 'softsign', category: 'Activation' }],
- [78, { name: 'space_to_batch', category: 'Transform' }],
- [79, { name: 'split', category: 'Tensor' }],
- [80, { name: 'squeeze', category: 'Shape' }],
- [81, { name: 'squeeze_shape', category: 'Shape' }],
- [82, { name: 'stack', category: 'Tensor' }],
- [83, { name: 'swish', category: 'Activation' }],
- [84, { name: 'tile', category: '' }],
- [85, { name: 'top_k', category: '' }],
- [86, { name: 'transpose', category: 'Transform' }],
- [87, { name: 'transpose_shape', category: 'Shape' }],
- [88, { name: 'trilu', category: '' }],
- [89, { name: 'unary', category: '' }],
- [90, { name: 'uniform' }],
- [91, { name: 'uniform_like' }],
- [92, { name: 'unsqueeze', category: 'Shape' }],
- [93, { name: 'unsqueeze_shape', category: 'Shape' }],
- [94, { name: 'where', category: '' }]
- ]);
- }
- operation(operation) {
- switch (operation.opcode) {
- case 'ldarg':
- operation.index = this._reader.uint16();
- break;
- case 'call':
- operation.args = this._reader.uint16();
- operation.target = this._reader.int32();
- break;
- case 'ecall':
- operation.args = this._reader.uint16();
- break;
- case 'ldlocal':
- case 'stlocal':
- operation.index = this._reader.uint16();
- break;
- default:
- super.operation(operation);
- }
- }
- tensor(operation) {
- switch (operation.tensor_name) {
- case 'binary':
- operation.binary_op = this._reader.byte();
- break;
- case 'matmul':
- break;
- case 'normal':
- operation.type = this._reader.byte();
- break;
- case 'random_normal':
- operation.type = this._reader.byte();
- break;
- case 'normal_like':
- operation.type = this._reader.byte();
- break;
- case 'one_hot':
- operation.one_hot_mode = this._reader.byte();
- break;
- case 'pad':
- operation.pad_mode = this._reader.byte();
- break;
- case 'cumsum':
- break;
- case 'conv2d':
- operation.pad_mode = this._reader.byte();
- break;
- default:
- super.tensor(operation);
- }
- }
- };
- kmodel.Error = class extends Error {
- constructor(message) {
- super(message);
- this.name = 'Error loading kmodel.';
- }
- };
- export const ModelFactory = kmodel.ModelFactory;
|