tengine.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  1. // Experimental
  2. var tengine = {};
  3. var base = require('./base');
  4. tengine.ModelFactory = class {
  5. match(context) {
  6. return tengine.Reader.open(context.stream);
  7. }
  8. open(context, match) {
  9. return tengine.Metadata.open(context).then((metadata) => {
  10. return new tengine.Model(metadata, match);
  11. });
  12. }
  13. };
  14. tengine.Model = class {
  15. constructor(metadata, reader) {
  16. this._version = reader.version;
  17. this._metadata = [
  18. { name: 'source', value: reader.source }
  19. ];
  20. this._graphs = reader.graphs.map((graph) => new tengine.Graph(metadata, graph));
  21. }
  22. get format() {
  23. return "Tengine v" + this._version;
  24. }
  25. get metadata() {
  26. return this._metadata;
  27. }
  28. get graphs() {
  29. return this._graphs;
  30. }
  31. };
  32. tengine.Graph = class {
  33. constructor(metadata, graph) {
  34. this._name = graph.id.toString();
  35. this._inputs = [];
  36. this._outputs = [];
  37. this._nodes = [];
  38. const tensors = graph.tensors.map((tensor) => new tengine.Argument(tensor));
  39. for (const input of graph.inputs) {
  40. const node = graph.nodes[input];
  41. this._inputs.push(new tengine.Parameter(node.name, true, node.outputs.map((output) => tensors[output])));
  42. }
  43. for (const output of graph.outputs) {
  44. const node = graph.nodes[output];
  45. this._outputs.push(new tengine.Parameter(node.name, true, node.outputs.map((output) => tensors[output])));
  46. }
  47. for (const node of graph.nodes) {
  48. switch (node.type) {
  49. case 'INPUT':
  50. case 'Const':
  51. break;
  52. default:
  53. this._nodes.push(new tengine.Node(metadata, node, tensors));
  54. break;
  55. }
  56. }
  57. }
  58. get name() {
  59. return this._name;
  60. }
  61. get inputs() {
  62. return this._inputs;
  63. }
  64. get outputs() {
  65. return this._outputs;
  66. }
  67. get nodes() {
  68. return this._nodes;
  69. }
  70. };
  71. tengine.Parameter = class {
  72. constructor(name, visible, args) {
  73. this._name = name;
  74. this._visible = visible;
  75. this._arguments = args;
  76. }
  77. get name() {
  78. return this._name;
  79. }
  80. get visible() {
  81. return this._visible;
  82. }
  83. get arguments() {
  84. return this._arguments;
  85. }
  86. };
  87. tengine.Argument = class {
  88. constructor(tensor) {
  89. this._name = tensor.name;
  90. this._type = new tengine.TensorType(tensor.dataType, new tengine.TensorShape(tensor.dims));
  91. this._initializer = (tensor.type === 2) ? new tengine.Tensor(this._type, tensor.buffer) : null;
  92. }
  93. get name() {
  94. return this._name;
  95. }
  96. get type() {
  97. if (this._initializer) {
  98. return this._initializer.type;
  99. }
  100. return this._type;
  101. }
  102. get quantization() {
  103. return null;
  104. }
  105. get initializer() {
  106. return this._initializer;
  107. }
  108. };
  109. tengine.Node = class {
  110. constructor(metadata, node, tensors) {
  111. this._name = node.name;
  112. const type = node.type;
  113. const version = node.version;
  114. this._inputs = [];
  115. this._outputs = [];
  116. this._attributes = [];
  117. this._type = metadata.type(type, version) || { name: type };
  118. for (let i = 0; i < node.params.length; i++) {
  119. const metadata = (this._type && this._type.attributes && i < this._type.attributes.length) ? this._type.attributes[i] : null;
  120. const name = metadata ? metadata.name : i.toString();
  121. this._attributes.push(new tengine.Attribute(metadata, name, node.params[i]));
  122. }
  123. const inputs = node.inputs;
  124. let inputIndex = 0;
  125. if (this._type && this._type.inputs) {
  126. for (const inputDef of this._type.inputs) {
  127. if (inputIndex < inputs.length || inputDef.option != 'optional') {
  128. const inputCount = (inputDef.option == 'variadic') ? (inputs.length - inputIndex) : 1;
  129. const inputArguments = inputs.slice(inputIndex, inputIndex + inputCount).filter((id) => id != '' || inputDef.option != 'optional').map((id) => tensors[id]);
  130. this._inputs.push(new tengine.Parameter(inputDef.name, true, inputArguments));
  131. inputIndex += inputCount;
  132. }
  133. }
  134. }
  135. else {
  136. this._inputs.push(...inputs.slice(inputIndex).map((id, index) => {
  137. const inputName = ((inputIndex + index) == 0) ? 'input' : (inputIndex + index).toString();
  138. return new tengine.Parameter(inputName, true, [ tensors[id] ]);
  139. }));
  140. }
  141. const outputs = node.outputs;
  142. let outputIndex = 0;
  143. if (this._type && this._type.outputs) {
  144. for (const outputDef of this._type.outputs) {
  145. if (outputIndex < outputs.length || outputDef.option != 'optional') {
  146. const outputCount = (outputDef.option == 'variadic') ? (outputs.length - outputIndex) : 1;
  147. const outputArguments = outputs.slice(outputIndex, outputIndex + outputCount).map((id) => tensors[id]);
  148. this._outputs.push(new tengine.Parameter(outputDef.name, true, outputArguments));
  149. outputIndex += outputCount;
  150. }
  151. }
  152. }
  153. else {
  154. this._outputs.push(...outputs.slice(outputIndex).map((id, index) => {
  155. const outputName = ((outputIndex + index) == 0) ? 'output' : (outputIndex + index).toString();
  156. return new tengine.Parameter(outputName, true, [ tensors[id] ]);
  157. }));
  158. }
  159. }
  160. get type() {
  161. return this._type;
  162. }
  163. get name() {
  164. return this._name;
  165. }
  166. get attributes() {
  167. return this._attributes;
  168. }
  169. get inputs() {
  170. return this._inputs;
  171. }
  172. get outputs() {
  173. return this._outputs;
  174. }
  175. };
  176. tengine.Attribute = class {
  177. constructor(schema, key, value) {
  178. this._type = '';
  179. this._name = key;
  180. this._value = value;
  181. if (schema) {
  182. this._name = schema.name;
  183. if (schema.type) {
  184. this._type = schema.type;
  185. }
  186. if (Object.prototype.hasOwnProperty.call(schema, 'visible') && !schema.visible) {
  187. this._visible = false;
  188. }
  189. else if (Object.prototype.hasOwnProperty.call(schema, 'default')) {
  190. if (this._value == schema.default || (this._value && this._value.toString() == schema.default.toString())) {
  191. this._visible = false;
  192. }
  193. }
  194. }
  195. }
  196. get type() {
  197. return this._type;
  198. }
  199. get name() {
  200. return this._name;
  201. }
  202. get value() {
  203. return this._value;
  204. }
  205. get visible() {
  206. return this._visible == false ? false : true;
  207. }
  208. };
  209. tengine.Tensor = class {
  210. constructor(type, data) {
  211. this._type = type;
  212. this._data = data;
  213. }
  214. get type() {
  215. return this._type;
  216. }
  217. get values() {
  218. return this._data;
  219. }
  220. };
  221. tengine.TensorType = class {
  222. constructor(dataType, shape) {
  223. switch (dataType) {
  224. case 0: this._dataType = 'float32'; break;
  225. case 1: this._dataType = 'float16'; break;
  226. case 2: this._dataType = 'int8'; break;
  227. case 3: this._dataType = 'uint8'; break;
  228. case 4: this._dataType = 'int32'; break;
  229. case 5: this._dataType = 'int16'; break;
  230. default: throw new tengine.Error("Unsupported data type'" + dataType + "'.");
  231. }
  232. this._shape = shape;
  233. }
  234. get dataType() {
  235. return this._dataType;
  236. }
  237. get shape() {
  238. return this._shape;
  239. }
  240. toString() {
  241. return this._dataType + this._shape.toString();
  242. }
  243. };
  244. tengine.TensorShape = class {
  245. constructor(dimensions) {
  246. this._dimensions = dimensions;
  247. }
  248. get dimensions() {
  249. return this._dimensions;
  250. }
  251. toString() {
  252. return this._dimensions ? ('[' + this._dimensions.map((dimension) => dimension ? dimension.toString() : '?').join(',') + ']') : '';
  253. }
  254. };
  255. tengine.Metadata = class {
  256. static open(context) {
  257. if (tengine.Metadata._metadata) {
  258. return Promise.resolve(tengine.Metadata._metadata);
  259. }
  260. return context.request('tengine-metadata.json', 'utf-8', null).then((data) => {
  261. tengine.Metadata._metadata = new tengine.Metadata(data);
  262. return tengine.Metadata._metadata;
  263. }).catch(() => {
  264. tengine.Metadata._metadata = new tengine.Metadata(null);
  265. return tengine.Metadata._metadata;
  266. });
  267. }
  268. constructor(data) {
  269. this._map = new Map();
  270. if (data) {
  271. const metadata = JSON.parse(data);
  272. for (const item of metadata) {
  273. if (item.name) {
  274. const version = item.version || 0;
  275. const name = item.name + ':' + version.toString();
  276. this._map.set(name, item);
  277. }
  278. }
  279. }
  280. }
  281. type(name, version) {
  282. let current = version;
  283. while (current > 0) {
  284. if (this._map.has(name + ':' + current.toString())) {
  285. break;
  286. }
  287. current--;
  288. }
  289. if (current >= 0) {
  290. const schema = this._map.get(name + ':' + current.toString());
  291. if (current !== version) {
  292. this._map.set(name + ':' + version.toString(), schema);
  293. }
  294. return schema;
  295. }
  296. return null;
  297. }
  298. };
  299. tengine.Reader = class {
  300. static open(stream) {
  301. if (stream && stream.length > 4) {
  302. const buffer = stream.peek(2);
  303. if (buffer[0] < 4 && buffer[1] === 0) {
  304. return new tengine.Reader(stream);
  305. }
  306. }
  307. return null;
  308. }
  309. constructor(stream) {
  310. this._stream = stream;
  311. // https://github.com/OAID/Tengine/wiki/The-format-of-tmfile
  312. // https://github.com/OAID/Tengine/blob/tengine-lite/source/serializer/tmfile/tm2_format.h
  313. }
  314. _read() {
  315. if (this._stream) {
  316. const types = new Map();
  317. const register = (index, version, name, params) => {
  318. types.set(index.toString() + ':' + version.toString(), { name: name, params: params });
  319. };
  320. const operator = (index, version) => {
  321. let current = version;
  322. while (current >= 0) {
  323. if (types.has(index.toString() + ':' + current.toString())) {
  324. break;
  325. }
  326. current--;
  327. }
  328. if (current >= 0) {
  329. const schema = types.get(index.toString() + ':' + current.toString());
  330. if (current !== version) {
  331. types.set(index.toString() + ':' + version.toString(), schema);
  332. }
  333. return schema;
  334. }
  335. return null;
  336. };
  337. /* eslint-disable space-in-parens */
  338. register( 0, 0, 'Accuracy', []);
  339. register( 1, 0, 'BatchNormalization', [ 'f', 'f', 'i' ]);
  340. register( 2, 0, 'BilinearResize', [ 'f', 'f', 'i' ]);
  341. register( 3, 0, 'Concat', [ 'i' ]);
  342. register( 4, 0, 'Const', []);
  343. register( 5, 0, 'Convolution', [ 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i' ]);
  344. register( 6, 0, 'Deconvolution', [ 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i' ]);
  345. register( 7, 0, 'DetectionOutput', [ 'i', 'i', 'i', 'f', 'f' ]);
  346. register( 8, 0, 'DropOut', []);
  347. register( 9, 0, 'Eltwise', [ 'i', 'i' ]);
  348. register(10, 0, 'Flatten', [ 'i' ]);
  349. register(11, 0, 'FullyConnected', [ 'i' ]);
  350. register(12, 0, 'INPUT', []);
  351. register(13, 0, 'LRN', [ 'i', 'f', 'f', 'i', 'f' ]);
  352. register(14, 0, 'Normalize', [ 'i', 'i' ]);
  353. register(15, 0, 'Permute', [ 'i', 'i', 'i', 'i', 'i' ]);
  354. register(16, 0, 'Pooling', [ 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i' ]);
  355. register(17, 0, 'Prelu', []);
  356. register(18, 0, 'PriorBox', [ 'f[]', 'f[]', 'f[]', 'f[]', 'i', 'i', 'i', 'i', 'i', 'f', 'f', 'f', 'i', 'i' ]);
  357. register(19, 0, 'Region', [ 'i', 'i', 'i', 'i', 'f', 'f', 'f[]' ]);
  358. register(20, 0, 'ReLU', [ 'f' ]);
  359. register(21, 0, 'ReLU6', []);
  360. register(22, 0, 'Reorg', [ 'i' ]);
  361. register(23, 0, 'Reshape', [ 'i', 'i', 'i', 'i', 'i', 'i' ]);
  362. // register(23, 0, 'Reshape', [ 'i', 'i', 'i[]' ]);
  363. register(24, 0, 'RoiPooling', [ 'i', 'i', 'f' ]);
  364. register(25, 0, 'RPN', [ 'f[]', 'f[]', 'i', 'i', 'i', 'i', 'i', 'f', 'anchors' ]);
  365. register(26, 0, 'Scale', [ 'i', 'i', 'i' ]);
  366. register(27, 0, 'Slice', [ 'i', 'i[]', 'i[]', 'i[]', 'i', 'i', 'i', 'i', 'i' ]);
  367. register(28, 0, 'SoftMax', [ 'i' ]);
  368. register(29, 0, 'Split', [ 'i', 'i', 'boolean', 'boolean', 'i[]' ]);
  369. register(30, 0, 'DetectionPostProcess', [ 'i', 'i', 'f', 'f', 'i', 'f[]' ]);
  370. register(31, 0, 'Gemm', [ 'f', 'f', 'i', 'i' ]);
  371. register(32, 0, 'Generic', [ 'i', 'i', 'string' ]);
  372. register(33, 0, 'Logistic', []);
  373. register(34, 0, 'LSTM', [ 'f', 'f', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i' ]);
  374. register(35, 0, 'RNN', [ 'f', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i' ]);
  375. register(36, 0, 'TanH', []);
  376. register(37, 0, 'Sigmoid', []);
  377. register(38, 0, 'Squeeze', [ 'i', 'i', 'i', 'i' ]);
  378. register(39, 0, 'FusedbnScaleRelu', []);
  379. register(40, 0, 'Pad', [ 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'f' ]);
  380. register(41, 0, 'StridedSlice', [ 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i' ]);
  381. register(42, 0, 'ArgMax', [ 'i' ]);
  382. register(43, 0, 'ArgMin', [ 'i' ]);
  383. register(44, 0, 'TopKV2', [ 'i', 'i' ]);
  384. register(45, 0, 'Reduction', [ 'i', 'i', 'i', 'i', 'i', 'i' ]);
  385. register(46, 0, 'Max', []);
  386. register(47, 0, 'Min', []);
  387. register(48, 0, 'GRU', [ 'f', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i', 'i' ]);
  388. register(49, 0, 'Addn', 'i');
  389. register(50, 0, 'SwapAxis', [ 'i', 'i' ]);
  390. register(51, 0, 'Upsample', [ 'f' ]);
  391. register(52, 0, 'SpaceToBatchND', [ 'i', 'i', 'i', 'i', 'i', 'i' ]);
  392. register(53, 0, 'BatchToSpaceND', [ 'i', 'i', 'i', 'i', 'i', 'i' ]);
  393. register(54, 0, 'Resize', [ 'f', 'f', 'i' ]);
  394. register(55, 0, 'ShuffleChannel', [ 'i' ]);
  395. register(56, 0, 'Crop', [ 'i', 'i', 'i', 'i', 'i', 'i', 'boolean', 'i', 'i' ]);
  396. register(57, 0, 'ROIAlign', [ 'i', 'i', 'f' ]);
  397. register(58, 0, 'Psroipooling', [ 'i', 'i', 'f', 'i' ]);
  398. register(59, 0, 'Unary', [ 'i' ]);
  399. register(60, 0, 'Expanddims', [ 'i' ]);
  400. register(61, 0, 'Bias', [ 'i' ]);
  401. register(62, 0, 'Noop', []);
  402. register(63, 0, 'Threshold', [ 'f' ]);
  403. register(64, 0, 'Hardsigmoid', [ 'f', 'f' ]);
  404. register(65, 0, 'Embed', [ 'f', 'f', 'f', 'f' ]);
  405. register(66, 0, 'InstanceNorm', [ 'f' ]);
  406. register(67, 0, 'MVN', [ 'i', 'i', 'f' ]);
  407. register(68, 0, 'Absval', []);
  408. register(69, 0, 'Cast', [ 'i', 'i' ]);
  409. register(70, 0, 'HardSwish', [ 'f', 'f' ]);
  410. register(71, 0, 'Interp', [ 'i', 'f', 'f', 'i', 'i' ]);
  411. register(72, 0, 'SELU', [ 'f', 'f' ]);
  412. register(73, 0, 'ELU', [ 'f' ]);
  413. register(74, 0, 'BroadMul', []);
  414. register(75, 0, 'Logical', [ 'i' ]);
  415. register(76, 0, 'Gather', [ 'i', 'i' ]);
  416. register(77, 0, 'Transpose', [ 'i[]' ]);
  417. register(78, 0, 'Comparison', [ 'i' ]);
  418. register(79, 0, 'SpaceToDepth', [ 'i' ]);
  419. register(80, 0, 'DepthToSpace', [ 'i' ]);
  420. register(81, 0, 'Reverse', []);
  421. register(82, 0, 'SparseToDense', [ 'i','i','i' ]);
  422. register(83, 0, 'Ceil', []);
  423. register(84, 0, 'SquaredDifference', []);
  424. register(85, 0, 'Round', []);
  425. register(86, 0, 'ZerosLike', []);
  426. register(87, 0, 'Clip', [ 'f','f' ]);
  427. register(88, 0, 'Unsqueeze', [ 'i[]' ]);
  428. register(89, 0, 'ReduceL2', [ 'i','i' ]);
  429. register(90, 0, 'Mean', []);
  430. register(91, 0, 'MatMul', []);
  431. register(92, 0, 'Expand', ['i[]']);
  432. register(93, 0, 'Scatter', ['i','boolean']);
  433. register(94, 0, 'Shape', []);
  434. register(95, 0, 'Where', []);
  435. register(96, 0, 'Tile', ['i','i']);
  436. register(97, 0, 'Mish', []);
  437. register(98, 0, 'L2Pool', []);
  438. register(99, 0, 'LogSoftmax', []);
  439. register(100, 0, 'ReLU1', []);
  440. register(101, 0, 'L2Normalization', []);
  441. register(102, 0, 'PackModel', ['i','i']);
  442. register(103, 0, 'Num', []);
  443. /* eslint-enable space-in-parens */
  444. const buffer = this._stream.peek();
  445. const reader = new tengine.BinaryReader(buffer);
  446. this._majorVersion = reader.uint16();
  447. this._minorVersion = reader.uint16();
  448. if (this._majorVersion !== 2) {
  449. throw new tengine.Error("Unsupported format version 'v" + this._majorVersion.toString() + "." + this._minorVersion.toString() + "'.");
  450. }
  451. this._compileVersion = reader.uint16();
  452. reader.skip(2); // struct align
  453. reader.seek(reader.uint32()); // root table
  454. this._originalFormat = reader.int32();
  455. this._subFormat = reader.int32();
  456. this._graphs = [];
  457. const subgraphOffsets = reader.uint32s();
  458. for (const subgraphOffset of subgraphOffsets) {
  459. reader.seek(subgraphOffset);
  460. const subgraph = {};
  461. subgraph.id = reader.int32();
  462. subgraph.graphLayout = reader.int32();
  463. /*
  464. if (graphLayout == 0) {
  465. return "NCHW";
  466. }
  467. if (graphLayout == 1) {
  468. return "NHWC";
  469. }
  470. */
  471. subgraph.originalLayout = reader.int32();
  472. subgraph.inputs = reader.uint32s();
  473. subgraph.outputs = reader.uint32s();
  474. const nodeOffsets = reader.uint32s();
  475. const tensorOffsets = reader.uint32s();
  476. const bufferOffsets = reader.uint32s();
  477. subgraph.name = reader.string();
  478. subgraph.nodes = [];
  479. subgraph.tensors = [];
  480. this._graphs.push(subgraph);
  481. // nodes
  482. for (const nodeOffset of nodeOffsets) {
  483. reader.seek(nodeOffset);
  484. const node = {};
  485. node.id = reader.int32();
  486. node.inputs = reader.uint32s();
  487. node.outputs = reader.uint32s();
  488. const typeOffset = reader.int32();
  489. node.name = reader.string();
  490. const attributeOffsets = reader.uint32s();
  491. node.dynamicShape = reader.boolean();
  492. reader.seek(typeOffset);
  493. node.version = reader.int32();
  494. const index = reader.int32();
  495. const paramsOffset = reader.uint32();
  496. const schema = operator(index, node.version);
  497. node.type = schema ? schema.name : index.toString();
  498. const paramTypes = schema ? schema.params : [];
  499. node.params = [];
  500. if (paramsOffset) {
  501. reader.seek(paramsOffset);
  502. for (const paramType of paramTypes) {
  503. if (paramType !== 'boolean') {
  504. reader.align(4);
  505. }
  506. switch (paramType) {
  507. case 'i':
  508. node.params.push(reader.int32());
  509. break;
  510. case 'f':
  511. node.params.push(reader.float32());
  512. break;
  513. case 'i[]':
  514. node.params.push(reader.int32s());
  515. break;
  516. case 'f[]':
  517. node.params.push(reader.float32s());
  518. break;
  519. case 'boolean':
  520. node.params.push(reader.boolean());
  521. break;
  522. case 'string':
  523. node.params.push(reader.string());
  524. break;
  525. case 'anchors':
  526. node.params.push(reader.anchors(4));
  527. break;
  528. default:
  529. throw new tengine.Error("Unsupported param type '" + paramType + "' in '" + node.type + "'.");
  530. }
  531. }
  532. }
  533. if (node.type === 'Slice') {
  534. node.params[6] = (this._originalFormat == 5) ? node.params[6] : 0;
  535. }
  536. node.attributes = attributeOffsets.map((attributeOffset) => {
  537. reader.seek(attributeOffset);
  538. const name = reader.string();
  539. const value = reader.string();
  540. const type = reader.int32();
  541. return { name: name, value: value, type: type };
  542. });
  543. subgraph.nodes.push(node);
  544. }
  545. // buffers
  546. const buffers = bufferOffsets.map((bufferOffset) => {
  547. reader.seek(bufferOffset);
  548. const size = reader.uint32();
  549. const offset = reader.int32();
  550. if (offset !== 0) {
  551. reader.seek(offset);
  552. return reader.read(size);
  553. }
  554. return null;
  555. });
  556. // tensors
  557. subgraph.tensors = tensorOffsets.map((tensorOffset) => {
  558. reader.seek(tensorOffset);
  559. const tensor = {};
  560. tensor.id = reader.int32();
  561. tensor.buffer = buffers[reader.int32()];
  562. tensor.dims = reader.int32s();
  563. tensor.name = reader.string();
  564. const quantparamsOffset = reader.int32();
  565. tensor.layout = reader.int32();
  566. tensor.type = reader.int32(); // ar = 1, const = 2, input = 3, vdep, unknown
  567. tensor.dataType = reader.int32();
  568. if (quantparamsOffset) {
  569. reader.seek(quantparamsOffset);
  570. tensor.quantparams = {
  571. zeroPoint: reader.int32(),
  572. scale: reader.float32(),
  573. width: reader.int32()
  574. };
  575. }
  576. return tensor;
  577. });
  578. for (const node of subgraph.nodes) {
  579. if (node.type === 'Convolution') {
  580. switch (subgraph.graphLayout) {
  581. case 0: // NCHW
  582. node.params[6] = subgraph.tensors[node.inputs[1]].dims[1];
  583. break;
  584. case 1: // NHWC
  585. node.params[6] = subgraph.tensors[node.inputs[1]].dims[3];
  586. break;
  587. default:
  588. throw new tengine.Error("Unsupported 'Convolution' layout '" + subgraph.graphLayout + "'.");
  589. }
  590. }
  591. }
  592. }
  593. delete this._stream;
  594. }
  595. }
  596. get version() {
  597. this._read();
  598. return this._majorVersion + '.' + this._minorVersion;
  599. }
  600. get source() {
  601. this._read();
  602. switch (this._originalFormat) {
  603. case 0: return '';
  604. case 1: return 'Tengine';
  605. case 2: return 'Caffe';
  606. case 3: return 'ONNX';
  607. case 4: return 'MXNet';
  608. case 5: return 'TensorFlow';
  609. case 6: return 'TensorFlow Lite';
  610. case 7: return 'Darknet';
  611. case 8: return 'DLA v' + this._subFormat;
  612. case 9: return 'ncnn';
  613. case 10: return 'MegEngine';
  614. case 11: return 'OneFlow';
  615. case 12: return 'Horizon';
  616. case 13: return 'Bitman';
  617. default: throw new tengine.Error("Unsupported source '" + this._originalFormat.toString() + "'.");
  618. }
  619. }
  620. get graphs() {
  621. this._read();
  622. return this._graphs;
  623. }
  624. };
  625. tengine.BinaryReader = class extends base.BinaryReader {
  626. string() {
  627. const position = this.uint32();
  628. let content = '';
  629. if (position) {
  630. const next = this._position;
  631. this.seek(position);
  632. const size = this.uint32();
  633. this.seek(this.uint32());
  634. for (let i = 0; i < size - 1; i++) {
  635. content += String.fromCharCode(this._buffer[this._position++]);
  636. }
  637. this.seek(next);
  638. }
  639. return content;
  640. }
  641. uint32s() {
  642. const values = [];
  643. const offset = this.uint32();
  644. if (offset) {
  645. const next = this.position;
  646. this.seek(offset);
  647. const count = this.uint32();
  648. for (let i = 0; i < count; i++) {
  649. values.push(this.uint32());
  650. }
  651. this.seek(next);
  652. }
  653. return values;
  654. }
  655. int32s() {
  656. const values = [];
  657. const offset = this.uint32();
  658. if (offset) {
  659. const next = this.position;
  660. this.seek(offset);
  661. const count = this.uint32();
  662. for (let i = 0; i < count; i++) {
  663. values.push(this.int32());
  664. }
  665. this.seek(next);
  666. }
  667. return values;
  668. }
  669. float32s() {
  670. const values = [];
  671. const offset = this.uint32();
  672. if (offset) {
  673. const next = this.position;
  674. this.seek(offset);
  675. const count = this.uint32();
  676. for (let i = 0; i < count; i++) {
  677. values.push(this.float32());
  678. }
  679. this.seek(next);
  680. }
  681. return values;
  682. }
  683. anchors(length) {
  684. const arrays = [];
  685. const offset = this.uint32();
  686. if (offset) {
  687. const next = this._position;
  688. this.seek(offset);
  689. const count = this.uint32();
  690. for (let i = 0; i < count; i++) {
  691. const array = [];
  692. for (let j = 0; j < length; j++) {
  693. array.push(this.float32());
  694. }
  695. arrays.push(array);
  696. }
  697. this.seek(next);
  698. }
  699. return arrays;
  700. }
  701. };
  702. tengine.Error = class extends Error {
  703. constructor(message) {
  704. super(message);
  705. this.name = 'Error loading Tengine model.';
  706. }
  707. };
  708. if (typeof module !== 'undefined' && typeof module.exports === 'object') {
  709. module.exports.ModelFactory = tengine.ModelFactory;
  710. }