om.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. // Experimental
  2. var om = {};
  3. var protobuf = require('./protobuf');
  4. var base = require('./base');
  5. om.ModelFactory = class {
  6. match(context) {
  7. return om.Container.open(context);
  8. }
  9. open(context, match) {
  10. const container = match;
  11. return container.open().then(() => {
  12. return context.metadata('om-metadata.json').then((metadata) => {
  13. return new om.Model(metadata, container);
  14. });
  15. });
  16. }
  17. };
  18. om.Model = class {
  19. constructor(metadata, container) {
  20. this._graphs = [];
  21. this._format = container.format;
  22. const context = { metadata: metadata, weights: container.weights };
  23. for (const graph of container.model.graph) {
  24. this._graphs.push(new om.Graph(context, graph));
  25. }
  26. }
  27. get format() {
  28. return this._format;
  29. }
  30. get graphs() {
  31. return this._graphs;
  32. }
  33. };
  34. om.Graph = class {
  35. constructor(context, graph) {
  36. this._name = graph.name;
  37. this._nodes = [];
  38. this._inputs = [];
  39. this._outputs = [];
  40. for (const op of graph.op) {
  41. if (op.type === 'Const') {
  42. continue;
  43. }
  44. const node = new om.Node(context, op, graph);
  45. this._nodes.push(node);
  46. }
  47. }
  48. get name() {
  49. return this._name;
  50. }
  51. get nodes() {
  52. return this._nodes;
  53. }
  54. get inputs() {
  55. return this._inputs;
  56. }
  57. get outputs() {
  58. return this._outputs;
  59. }
  60. };
  61. om.Node = class {
  62. constructor(context, op, graph) {
  63. this._name = op.name;
  64. this._type = context.metadata.type(op.type) || { name: op.type };
  65. this._inputs = [];
  66. this._outputs = [];
  67. this._attributes = [];
  68. this._chain = [];
  69. this._controlDependencies = [];
  70. this._device = null;
  71. if (op.input) {
  72. for (let i = 0; i < op.input.length; i++) {
  73. if (op.input[i] === '') {
  74. continue;
  75. }
  76. const pos = op.input[i].lastIndexOf(':');
  77. const name = pos === 0 ? 'internal_unnamed' : op.input[i].slice(0, pos);
  78. const src_index = op.input[i].slice(pos + 1);
  79. if (src_index === '-1') {
  80. this._controlDependencies.push(new om.Argument(name));
  81. continue;
  82. }
  83. const parameterName = this._type.inputs && i < this._type.inputs.length ? this._type.inputs[i].name : 'input' + (i === 0 ? '' : i.toString());
  84. const inputNode = graph.op.find(node => node.name === name);
  85. const desc = op.input_desc[i];
  86. const layout = desc.layout;
  87. if (inputNode && inputNode.type === 'Const' && inputNode.attr && inputNode.attr.value && inputNode.attr) {
  88. let shape = null;
  89. const value = inputNode.attr.value.t;
  90. if (value.desc.shape != null) {
  91. shape = value.desc.shape.dim;
  92. }
  93. else if (value.desc.attr.origin_shape) {
  94. shape = value.desc.attr.origin_shape.list.i;
  95. }
  96. let data = null;
  97. if (value.data.length === 0) {
  98. if (context.weights == null) {
  99. data = null;
  100. }
  101. else if (value.desc.attr.merged_offset) {
  102. const offset = value.desc.attr.merged_offset.i;
  103. data = context.weights.slice(offset, offset + value.desc.weight_size);
  104. }
  105. else {
  106. const offset = value.desc.data_offset;
  107. data = context.weights.slice(offset, offset + value.desc.weight_size);
  108. }
  109. }
  110. else {
  111. data = value.data;
  112. }
  113. const dataType = desc && desc.dtype ? om.Utility.dtype(value.desc.dtype) : '?';
  114. const tensorType = new om.TensorType(dataType, shape, layout, value.desc.layout);
  115. const tensor = new om.Tensor('Constant', tensorType, data);
  116. const argument = new om.Argument(name, null, tensor);
  117. this._inputs.push(new om.Parameter(parameterName, true, [ argument ]));
  118. }
  119. else {
  120. const dataType = desc && desc.dtype ? om.Utility.dtype(desc.dtype) : '?';
  121. const shape = desc.shape ? desc.shape.dim : undefined;
  122. const tensorType = new om.TensorType(dataType, shape, layout, null);
  123. const identifier = src_index === '0' ? name : name + ':' + src_index;
  124. const argument = new om.Argument(identifier, tensorType, null);
  125. this._inputs.push(new om.Parameter(parameterName, true, [ argument ]));
  126. }
  127. }
  128. }
  129. if (op.output_desc) {
  130. for (let i = 0; i < op.output_desc.length; i++) {
  131. const desc = op.output_desc[i];
  132. let shape = desc.shape ? desc.shape.dim : undefined;
  133. if (op.type === 'Data' || op.type === 'ImageData' || op.type === 'DynamicImageData') {
  134. shape = desc.shape ? desc.shape.dim : op.input_desc[0].shape.dim;
  135. }
  136. const dataType = desc && desc.dtype ? om.Utility.dtype(desc.dtype) : '?';
  137. const format = desc.layout;
  138. const tensorType = new om.TensorType(dataType, shape, format);
  139. const identifier = i === 0 ? this._name : this._name + ':' + i;
  140. const argument = new om.Argument(identifier, tensorType, null);
  141. const outputName = this._type.outputs && i < this._type.outputs.length ? this._type.outputs[i].name : 'output' + (i === 0 ? '' : i.toString());
  142. this._outputs.push(new om.Parameter(outputName, true, [ argument ]));
  143. }
  144. }
  145. if (op.attr) {
  146. for (const attr of Object.entries(op.attr)) {
  147. const name = attr[0];
  148. const value = attr[1];
  149. if (name === 'device') {
  150. this._device = value;
  151. continue;
  152. }
  153. if (name === 'original_op_names') {
  154. continue;
  155. }
  156. if (name === 'relu_flag' && value.b) {
  157. this._chain.push(new om.Node(context, { type: 'ReLU' }, graph));
  158. continue;
  159. }
  160. const attribute = new om.Attribute(context, name, value);
  161. this._attributes.push(attribute);
  162. }
  163. }
  164. }
  165. get device() {
  166. return this._device;
  167. }
  168. get name() {
  169. return this._name || '';
  170. }
  171. get type() {
  172. return this._type;
  173. }
  174. get inputs() {
  175. return this._inputs;
  176. }
  177. get outputs() {
  178. return this._outputs;
  179. }
  180. get attributes() {
  181. return this._attributes;
  182. }
  183. get chain() {
  184. return this._chain;
  185. }
  186. get controlDependencies() {
  187. return this._controlDependencies;
  188. }
  189. };
  190. om.Attribute = class {
  191. constructor(context, name, value) {
  192. this._name = name;
  193. this._value = value;
  194. switch (value.value) {
  195. case 'i': {
  196. this._value = value.i;
  197. this._type = 'int64';
  198. break;
  199. }
  200. case 'f': {
  201. this._value = value.f;
  202. this._type = 'float32';
  203. break;
  204. }
  205. case 'b': {
  206. this._value = value.b;
  207. this._type = 'boolean';
  208. break;
  209. }
  210. case 'bt': {
  211. this._value = null;
  212. if (value.bt.length !== 0) {
  213. this._type = 'tensor';
  214. this._value = new om.Tensor('Constant', new om.TensorType('float32', [ value.bt.length / 4 ], null), value.bt);
  215. }
  216. break;
  217. }
  218. case 'dt': {
  219. this._type = 'DataType';
  220. this._value = om.Utility.dtype(value.dt.toNumber());
  221. break;
  222. }
  223. case 's': {
  224. if (typeof value.s === 'string') {
  225. this._value = value.s;
  226. }
  227. else if (value.s.filter(c => c <= 32 && c >= 128).length === 0) {
  228. this._value = om.Utility.decodeText(value.s);
  229. }
  230. else {
  231. this._value = value.s;
  232. }
  233. this._type = 'string';
  234. break;
  235. }
  236. case 'g': {
  237. this._type = 'graph';
  238. this._value = new om.Graph(context, value.g);
  239. break;
  240. }
  241. case 'func': {
  242. break;
  243. }
  244. case 'list': {
  245. const list = value.list;
  246. this._value = [];
  247. if (list.s && list.s.length > 0) {
  248. this._value = list.s.map(v => String.fromCharCode.apply(null, new Uint16Array(v))).join(', ');
  249. this._type = 'string[]';
  250. }
  251. else if (list.b && list.b.length > 0) {
  252. this._value = list.b;
  253. this._type = 'boolean[]';
  254. }
  255. else if (list.i && list.i.length > 0) {
  256. this._value = list.i;
  257. this._type = 'int64[]';
  258. }
  259. else if (list.f && list.f.length > 0) {
  260. this._value = list.f;
  261. this._type = 'float32[]';
  262. }
  263. else if (list.type && list.type.length > 0) {
  264. this._type = 'type[]';
  265. this._value = list.type.map((type) => om.Node.enum2Dtype(type) || '?');
  266. }
  267. else if (list.shape && list.shape.length > 0) {
  268. this._type = 'shape[]';
  269. this._value = list.shape.map((shape) => new om.TensorShape(shape));
  270. }
  271. break;
  272. }
  273. case 'list_list_int': {
  274. this._value = value.list_list_int.list_list_i.map((list) => list.list_i);
  275. break;
  276. }
  277. case 't': {
  278. const desc = value.t.desc;
  279. const dataType = desc && desc.dtype ? om.Utility.dtype(desc.dtype) : '?';
  280. const shape = desc.shape ? desc.shape.dim : undefined;
  281. const layout = desc.layout;
  282. const type = new om.TensorType(dataType, shape, layout, null);
  283. this._value = new om.Tensor('Constant', type, value.t.bytes);
  284. this._type = 'tensor';
  285. break;
  286. }
  287. case undefined: {
  288. this._value = null;
  289. break;
  290. }
  291. default: {
  292. throw new om.Error("Unsupported attribute type '" + JSON.stringify(value).substring(0, 32) + "'.");
  293. }
  294. }
  295. }
  296. get name() {
  297. return this._name;
  298. }
  299. get type() {
  300. return this._type;
  301. }
  302. get value() {
  303. return this._value;
  304. }
  305. get visible() {
  306. return true;
  307. }
  308. };
  309. om.Parameter = class {
  310. constructor(name, visible, args) {
  311. this._name = name;
  312. this._visible = visible;
  313. this._arguments = args;
  314. }
  315. get name() {
  316. return this._name;
  317. }
  318. get visible() {
  319. return this._visible;
  320. }
  321. get arguments() {
  322. return this._arguments;
  323. }
  324. };
  325. om.Argument = class {
  326. constructor(name, type, initializer) {
  327. if (typeof name !== 'string') {
  328. throw new om.Error("Invalid argument identifier '" + JSON.stringify(name) + "'.");
  329. }
  330. this._name = name;
  331. this._type = type || null;
  332. this._initializer = initializer || null;
  333. }
  334. get name() {
  335. return this._name;
  336. }
  337. get type() {
  338. if (this._initializer) {
  339. return this._initializer.type;
  340. }
  341. return this._type;
  342. }
  343. get initializer() {
  344. return this._initializer;
  345. }
  346. };
  347. om.Tensor = class {
  348. constructor(category, type, value) {
  349. this._category = category;
  350. this._type = type;
  351. this._data = value;
  352. }
  353. get category() {
  354. return this._category;
  355. }
  356. get type() {
  357. return this._type;
  358. }
  359. };
  360. om.TensorType = class {
  361. constructor(dataType, shape, format, denotation) {
  362. this._dataType = dataType;
  363. this._shape = new om.TensorShape(shape);
  364. const list = [];
  365. if (format) {
  366. list.push(format);
  367. }
  368. if (denotation && denotation !== format) {
  369. list.push(denotation);
  370. }
  371. this._denotation = list.join(' ');
  372. }
  373. get dataType() {
  374. return this._dataType;
  375. }
  376. set shape(dims) {
  377. this._shape = dims;
  378. }
  379. get shape() {
  380. return this._shape;
  381. }
  382. get denotation() {
  383. return this._denotation;
  384. }
  385. toString() {
  386. return this._dataType + this._shape.toString();
  387. }
  388. };
  389. om.TensorShape = class {
  390. constructor(shape) {
  391. this._shape = shape;
  392. }
  393. get dimensions() {
  394. return this._shape;
  395. }
  396. toString() {
  397. if (this._shape && Array.isArray(this._shape) && this._shape.length > 0) {
  398. return '[' + this._shape.map((dim) => dim ? dim.toString() : '?').join(',') + ']';
  399. }
  400. return '';
  401. }
  402. };
  403. om.Container = class {
  404. static open(context) {
  405. const stream = context.stream;
  406. if (stream && stream.length >= 256) {
  407. const buffer = stream.peek(4);
  408. const signature = Array.from(buffer).map((c) => String.fromCharCode(c)).join('');
  409. if (signature === 'IMOD' || signature === 'PICO') {
  410. return new om.Container(context, signature);
  411. }
  412. }
  413. return null;
  414. }
  415. constructor(context, signature) {
  416. this._context = context;
  417. this._signature = signature;
  418. }
  419. open() {
  420. const stream = this._context.stream;
  421. const reader = new base.BinaryReader(stream);
  422. const buffer = reader.read(4);
  423. this.signature = Array.from(buffer).map((c) => String.fromCharCode(c)).join('');
  424. switch (this.signature) {
  425. case 'IMOD': {
  426. this.format = 'DaVinci OM';
  427. const decoder = new TextDecoder('utf-8');
  428. const size = reader.uint32();
  429. this.version = reader.uint32();
  430. this.checksum = reader.read(64);
  431. reader.skip(4);
  432. this.is_encrypt = reader.byte();
  433. this.is_checksum = reader.byte();
  434. this.type = reader.byte(); // 0=IR model, 1=standard model, 2=OM Tiny model
  435. this.mode = reader.byte(); // 0=offline, 1=online
  436. this.name = decoder.decode(reader.read(32));
  437. this.ops = reader.uint32();
  438. this.userdefineinfo = reader.read(32);
  439. this.ir_version = reader.uint32();
  440. this.model_num = reader.uint32();
  441. this.platform_version = reader.read(20);
  442. this.platform_type = reader.byte();
  443. reader.seek(0);
  444. reader.skip(size);
  445. const partitions = new Array(reader.uint32());
  446. for (let i = 0; i < partitions.length; i++) {
  447. partitions[i] = {
  448. type: reader.uint32(),
  449. offset: reader.uint32(),
  450. size: reader.uint32()
  451. };
  452. }
  453. const offset = 256 + 4 + 12 * partitions.length;
  454. for (const partition of partitions) {
  455. reader.seek(offset + partition.offset);
  456. const buffer = reader.read(partition.size);
  457. switch (partition.type) {
  458. case 0: { // MODEL_DEF
  459. this.model = buffer;
  460. break;
  461. }
  462. case 1: { // WEIGHTS_DATA
  463. this.weights = buffer;
  464. break;
  465. }
  466. case 2: // TASK_INFO
  467. case 3: // TBE_KERNELS
  468. case 4: { // CUST_AICPU_KERNELS
  469. break;
  470. }
  471. case 5: { // DEVICE_CONFIG
  472. this.devices = new Map();
  473. const decoder = new TextDecoder('ascii');
  474. const reader = new base.BinaryReader(buffer);
  475. reader.uint32();
  476. for (let position = 4; position < partition.size;) {
  477. const length = reader.uint32();
  478. const buffer = reader.read(length);
  479. const name = decoder.decode(buffer);
  480. const device = reader.uint32();
  481. this.devices.set(name, device);
  482. position += 4 + length + 4;
  483. }
  484. break;
  485. }
  486. default: {
  487. throw new om.Error("Unsupported partition type '" + partition.type + "'.");
  488. }
  489. }
  490. }
  491. if (!this.model) {
  492. throw new om.Error('File does not contain a model definition.');
  493. }
  494. return this._context.require('./om-proto').then(() => {
  495. try {
  496. om.proto = protobuf.get('om').ge.proto;
  497. const reader = protobuf.BinaryReader.open(this.model);
  498. this.model = om.proto.ModelDef.decode(reader);
  499. }
  500. catch (error) {
  501. const message = error && error.message ? error.message : error.toString();
  502. throw new om.Error('File format is not ge.proto.ModelDef (' + message.replace(/\.$/, '') + ').');
  503. }
  504. });
  505. }
  506. case 'PICO': {
  507. this.format = 'DaVinci OM SVP'; // SVP = Smart Vision PICO
  508. reader.uint32(); // reserved
  509. this.size = reader.uint32();
  510. const param_size = reader.uint32();
  511. const param_offset = reader.uint32();
  512. reader.uint32(); // tmp_bufsize
  513. const tfm_offset = reader.uint32();
  514. reader.uint32(); // tfm_size
  515. this.type = 2;
  516. reader.seek(param_offset);
  517. this.param = reader.read(param_size);
  518. const buffer = reader.read(tfm_offset - reader.position);
  519. this.model = new svp.ModelDef(buffer);
  520. return Promise.resolve();
  521. }
  522. default: {
  523. return Promise.reject(new om.Error('Unsupported DaVinci OM ' + this.signature + ' signature.'));
  524. }
  525. }
  526. }
  527. };
  528. om.Utility = class {
  529. static dtype(value) {
  530. om.Utility._types = om.Utility._types || [
  531. 'undefined', 'float32', 'float16', 'int8', 'uint8', 'int16', 'uint16', 'int32',
  532. 'int64', 'uint32', 'uint64', 'boolean', 'float64', 'string', 'dual_sub_int8', 'dual_sub_uint8',
  533. 'complex64', 'complex128', 'qint8', 'qint16', 'qint32', 'quint8', 'quint16', 'resource',
  534. 'stringref', 'dual', 'variant', 'bfloat16', 'int4', 'uint1', 'int2', 'uint2'
  535. ];
  536. if (value >= om.Utility._types.length) {
  537. throw new om.Error("Unsupported dtype '" + value + "'.");
  538. }
  539. return om.Utility._types[value];
  540. }
  541. static decodeText(value) {
  542. om.Utility._textDecoder = om.Utility._textDecoder || new TextDecoder('utf-8');
  543. return om.Utility._textDecoder.decode(value);
  544. }
  545. };
  546. om.Error = class extends Error {
  547. constructor(message) {
  548. super(message);
  549. this.name = 'Error loading DaVinci model.';
  550. }
  551. };
  552. var svp = svp || {};
  553. svp.ModelDef = class ModelDef {
  554. constructor(buffer) {
  555. const reader = new svp.BinaryReader(buffer);
  556. this.attr = {};
  557. this.graph = [];
  558. this.name = reader.find(0x800D, 'string');
  559. this.batch_num = reader.find(0x600A);
  560. while (reader.position < reader.length) {
  561. const tag = reader.uint16();
  562. const value = reader.value(tag);
  563. switch (tag & 0x1fff) {
  564. case 0x0040: {
  565. this.graph.push(new svp.GraphDef(value));
  566. break;
  567. }
  568. case 0x0111: {
  569. const op = new svp.OpDef(value);
  570. for (const item of this.graph) {
  571. if (op.attr && op.attr.seg_id && op.attr.seg_id.i === item.id) {
  572. let out_num;
  573. if (typeof op.output_index == 'number') {
  574. out_num = op.output_index + 1;
  575. }
  576. else {
  577. const input_num = op.input.map((element) => element.split(":")[1]);
  578. out_num = input_num.length > 0 ? Math.max(...input_num) + 1 : 1;
  579. }
  580. const out_types = [];
  581. if (op.data_flow && op.data_flow !== '') {
  582. const data = op.data_flow;
  583. if (data.indexOf('o[{t') !== -1) {
  584. const outs = data.substring(data.indexOf('o[{t')).split(',');
  585. for (const out of outs) {
  586. const startIndex = out.indexOf("\"");
  587. const endIndex = out.indexOf("\"", startIndex + 1);
  588. out_types.push(out.substring(startIndex + 1, endIndex));
  589. }
  590. }
  591. }
  592. const out_list = [];
  593. while (out_num > 0) {
  594. const output_desc = {};
  595. output_desc.shape = { dim: op.output_shape_vector };
  596. output_desc.layout = 'NCHW';
  597. if (op.data_flow && out_types.length >= out_num) {
  598. output_desc.dtype = out_types[op.output_index + 1 - out_num];
  599. }
  600. out_list.push(output_desc);
  601. out_num--;
  602. }
  603. let curr_op = null;
  604. for (const op_item of item.op) {
  605. if (op_item.id === op.id) {
  606. curr_op = op_item;
  607. break;
  608. }
  609. }
  610. if (curr_op != null) {
  611. curr_op.output_desc = curr_op.output_desc.concat(out_list);
  612. }
  613. else {
  614. op.output_desc = op.output_desc.concat(out_list);
  615. item.op.push(op);
  616. }
  617. break;
  618. }
  619. }
  620. break;
  621. }
  622. default: {
  623. break;
  624. }
  625. }
  626. }
  627. if (this.graph.length > 1) {
  628. for (let i = 1; i < this.graph.length; i++) {
  629. this.graph[0].op = this.graph[0].op.concat(this.graph[i].op);
  630. }
  631. }
  632. }
  633. };
  634. svp.GraphDef = class {
  635. constructor(buffer) {
  636. this.input = [];
  637. this.output = [];
  638. this.op = [];
  639. this.attr = {};
  640. const reader = new svp.BinaryReader(buffer);
  641. const input = (buffer) => {
  642. const input = {};
  643. const reader = new svp.BinaryReader(buffer);
  644. while (reader.position < reader.length) {
  645. const tag = reader.uint16();
  646. switch (tag & 0x1fff) {
  647. case 0x0051: input.id = reader.value(tag); break;
  648. case 0x0058: input.name = reader.value(tag, 'string').trim(); break;
  649. case 0x005a: input.shape_vector = reader.value(tag, 'uint32[]'); break;
  650. default: reader.value(tag); break;
  651. }
  652. }
  653. return input;
  654. };
  655. const output = (buffer) => {
  656. const output = {};
  657. const reader = new svp.BinaryReader(buffer);
  658. while (reader.position < reader.length) {
  659. const tag = reader.uint16();
  660. switch (tag & 0x1fff) {
  661. case 0x0061: output.id = reader.value(tag); break;
  662. case 0x0066: output.name = reader.value(tag, 'string').trim(); break;
  663. case 0x0069: output.shape_vector = reader.value(tag, 'uint32[]'); break;
  664. case 0x0110: output.layer_num = reader.value(tag); break;
  665. default: reader.value(tag); break;
  666. }
  667. }
  668. return output;
  669. };
  670. while (reader.position < reader.length) {
  671. const tag = reader.uint16();
  672. const value = reader.value(tag);
  673. switch (tag & 0x1fff) {
  674. case 0x0041: this.id = value; break;
  675. case 0x0050: this.input.push(input(value)); break;
  676. case 0x0060: this.output.push(output(value)); break;
  677. default: break;
  678. }
  679. }
  680. }
  681. };
  682. svp.OpDef = class {
  683. constructor(buffer) {
  684. this.input = [];
  685. this.attr = {};
  686. this.input_i = [];
  687. this.output_i = [];
  688. this.input_desc = [];
  689. this.output_desc = [];
  690. const reader = new svp.BinaryReader(buffer);
  691. while (reader.position < reader.length) {
  692. const tag = reader.uint16();
  693. switch (tag & 0x1fff) {
  694. case 0x0114: this.name = reader.value(tag, 'string').trim(); break;
  695. case 0x0112: this.id = reader.value(tag); break;
  696. case 0x0119: this.attr.output_m2m_flag = reader.attribute(tag, 'i'); break;
  697. case 0x0121: this.attr.batch_flag = reader.attribute(tag, 'i'); break;
  698. case 0x0124: this.attr.dequant_scale = reader.attribute(tag, 'i'); break;
  699. case 0x0126: this.attr.output_address = reader.attribute(tag, 'i'); break;
  700. case 0x0125: this.attr.dequant_offset = reader.attribute(tag, 'i'); break;
  701. case 0x0127: this.attr.first_inst_addr = reader.attribute(tag, 'i'); break;
  702. case 0x0128: this.attr.last_inst_addr = reader.attribute(tag, 'i'); break;
  703. case 0x013B: this.attr.is_fusion_layer = reader.attribute(tag, 'i'); break;
  704. case 0x013C: this.input = reader.value(tag, 'string').split(','); break;
  705. case 0x014B: this.attr.seg_id = reader.attribute(tag, 'i'); break;
  706. case 0x0150: this.attr.is_not_last_merge_layer = reader.attribute(tag, 'i'); break;
  707. case 0x0151: this.attr.is_dump_avavilable = reader.attribute(tag, 'i'); break;
  708. case 0x0153: this.attr.debug_dump_offset = reader.attribute(tag, 'i'); break;
  709. case 0x0152: this.type = reader.value(tag, 'string'); break;
  710. case 0x0154: this.output_shape_vector = reader.value(tag, 'uint32[]'); break;
  711. case 0x0155: this.input_index = reader.value(tag); break;
  712. case 0x015B: this.output_index = reader.value(tag); break;
  713. case 0x0156: this.attr.trap_inst_pc = reader.attribute(tag, 'i'); break;
  714. case 0x0157: this.attr.profile_layer_id = reader.attribute(tag, 'i'); break;
  715. case 0xA15A:
  716. this.data_flow = reader.value(tag, 'string');
  717. this.attr.data_flow = new svp.AttrDef(this.data_flow.replace('i[{t', 'input[{type').replace(',f[{t', '\tforward[{type').replace(',o[{t', '\toutput[{type').replace(',{[t', ',{type'), 's');
  718. break;
  719. default: reader.value(tag); break;
  720. }
  721. }
  722. for (let i = 0; i < this.input.length; i++) {
  723. this.input_desc.push({ layout: 'NCHW', shape: {} });
  724. }
  725. }
  726. };
  727. svp.AttrDef = class {
  728. constructor(item, type) {
  729. switch (type) {
  730. case 's': this.s = item; break;
  731. case 'i': this.i = item; break;
  732. default: throw new svp.Error("Unsupported attribute type '" + type + "'.");
  733. }
  734. }
  735. get value() {
  736. if (this.s !== undefined) {
  737. return 's';
  738. }
  739. if (this.i !== undefined) {
  740. return 'i';
  741. }
  742. return undefined;
  743. }
  744. };
  745. svp.BinaryReader = class extends base.BinaryReader {
  746. value(tag, type) {
  747. let value;
  748. switch (tag >> 13) {
  749. case 1: value = this.int8(); break;
  750. case 2: value = this.uint16(); break;
  751. case 3: value = this.uint32(); break;
  752. case 4: value = this.read(this.int8()); break;
  753. case 5: value = this.read(this.uint16()); break;
  754. case 6: value = this.read(this.uint32()); break;
  755. default: throw new svp.Error("Unsupported value identifier '" + tag + "'.");
  756. }
  757. return type ? this._cast(value, type, tag) : value;
  758. }
  759. find(tag, type) {
  760. let value = null;
  761. let match = false;
  762. while (!match && this.position < this.length) {
  763. const current = this.uint16();
  764. value = this.value(current);
  765. match = current === tag;
  766. }
  767. this.seek(0);
  768. return match && type ? this._cast(value, type, tag) : value;
  769. }
  770. attribute(tag, type) {
  771. const value = this.value(tag);
  772. return new svp.AttrDef(value, type);
  773. }
  774. _cast(value, type, tag) {
  775. switch (type) {
  776. case 'string': {
  777. if (value instanceof Uint8Array) {
  778. svp.BinaryReader._decoder = svp.BinaryReader._decoder || new TextDecoder('utf-8');
  779. return svp.BinaryReader._decoder.decode(value).replace(/\0.*$/g, '');
  780. }
  781. throw new om.Error("Invalid 'string' tag '" + tag.toString(16) + "'.");
  782. }
  783. case 'uint32[]': {
  784. const reader = new base.BinaryReader(value);
  785. value = [];
  786. while (reader.position < reader.length) {
  787. value.push(reader.uint32());
  788. }
  789. return value;
  790. }
  791. default: {
  792. return value;
  793. }
  794. }
  795. }
  796. };
  797. svp.Error = class extends Error {
  798. constructor(message) {
  799. super(message);
  800. this.name = 'Error loading DaVinci SVP model.';
  801. }
  802. };
  803. if (typeof module !== 'undefined' && typeof module.exports === 'object') {
  804. module.exports.ModelFactory = om.ModelFactory;
  805. }