UNPKG

hdl-js

Version:

Hardware definition language (HDL) and Hardware simulator

338 lines (280 loc) 11 kB
/** * The MIT License (MIT) * Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com> */ 'use strict'; var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var Gate = require('./Gate'); /** * A gate consisting of several sub-parts implementation * (usually a user-defined gate). */ var CompositeGate = function (_Gate) { _inherits(CompositeGate, _Gate); /** * Creates a gate instance with the given name. */ function CompositeGate() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$name = _ref.name, name = _ref$name === undefined ? null : _ref$name, _ref$inputPins = _ref.inputPins, inputPins = _ref$inputPins === undefined ? [] : _ref$inputPins, _ref$outputPins = _ref.outputPins, outputPins = _ref$outputPins === undefined ? [] : _ref$outputPins, _ref$internalPins = _ref.internalPins, internalPins = _ref$internalPins === undefined ? [] : _ref$internalPins, _ref$parts = _ref.parts, parts = _ref$parts === undefined ? [] : _ref$parts, _ref$ast = _ref.ast, ast = _ref$ast === undefined ? null : _ref$ast, _ref$manualClock = _ref.manualClock, manualClock = _ref$manualClock === undefined ? false : _ref$manualClock; _classCallCheck(this, CompositeGate); var _this = _possibleConstructorReturn(this, (CompositeGate.__proto__ || Object.getPrototypeOf(CompositeGate)).call(this, { name: name, inputPins: inputPins, outputPins: outputPins, manualClock: manualClock })); _this._internalPins = internalPins; _this._parts = parts; // If a composite gate is created from AST, // it directly provides it: _this._ast = ast; // Rebuild map to consider internal pins. _this._buildNamesToPinsMap(); return _this; } /** * Returns internal pins of this gate. */ _createClass(CompositeGate, [{ key: 'getInternalPins', value: function getInternalPins() { return this._internalPins; } /** * Returns implementation parts (gates) of this gate.. */ }, { key: 'getParts', value: function getParts() { return this._parts; } /** * Evaluates this gate. */ }, { key: 'eval', value: function _eval() { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = this._parts[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var part = _step.value; part.eval(); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } /** * Whether this gate is clocked. */ }, { key: 'clockUp', /** * Handler for the rising edge of the clock: updates internal state, * outputs are not updated ("latched"). */ value: function clockUp() { if (!this.getClass().isClocked()) { throw new TypeError('Gate#clockUp: "' + this._name + '" is not clocked.'); } var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = this._parts[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var part = _step2.value; part.tick(); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } /** * Handler for the falling edge of the clock: commits the internal state, * values to the output. */ }, { key: 'clockDown', value: function clockDown() { if (!this.getClass().isClocked()) { throw new TypeError('Gate#clockDown: "' + this._name + '" is not clocked.'); } var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = this._parts[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var part = _step3.value; part.tock(); } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } } /** * Transforms this composite gate instance to the AST format. * The AST then can be fed to the code generator, and be * exported to an HDL file. */ }, { key: 'toAST', value: function toAST() { // If the composite gate instance is created from AST // it directly provides it. Or if we already calculated it, // directly return. if (this._ast) { return this._ast; } var pinToNode = function pinToNode(pin) { var nameNode = { type: 'Name', value: pin.getName() }; if (pin.getSize() !== 1) { nameNode.size = pin.getSize(); } return nameNode; }; var inputs = this.getInputPins().map(pinToNode); var outputs = this.getOutputPins().map(pinToNode); // E.g. And(a=a[0], b=b[0], out=out[0]); // The index/range is stored in the `connectInfo`: var parts = this.getParts().map(function (part) { var callArguments = []; // a, b: part.getInputPins().forEach(function (pin) { var connectInfo = pin.getSourcePin().getListeningPinsMap().get(pin); var name = Object.assign({ type: 'Name', value: pin.getName() }, connectInfo.destinationSpec); var value = Object.assign({ type: 'Name', value: pin.getSourcePin().getName() }, connectInfo.sourceSpec); callArguments.push({ type: 'Argument', name: name, value: value }); }); // Several pins can listen to the output pins: part.getOutputPins().forEach(function (pin) { var _iteratorNormalCompletion4 = true; var _didIteratorError4 = false; var _iteratorError4 = undefined; try { for (var _iterator4 = pin.getListeningPinsMap()[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { var _ref2 = _step4.value; var _ref3 = _slicedToArray(_ref2, 2); var destPin = _ref3[0]; var connectInfo = _ref3[1]; var name = Object.assign({ type: 'Name', value: pin.getName() }, connectInfo.sourceSpec); var value = Object.assign({ type: 'Name', value: destPin.getName() }, connectInfo.destinationSpec); callArguments.push({ type: 'Argument', name: name, value: value }); } } catch (err) { _didIteratorError4 = true; _iteratorError4 = err; } finally { try { if (!_iteratorNormalCompletion4 && _iterator4.return) { _iterator4.return(); } } finally { if (_didIteratorError4) { throw _iteratorError4; } } } }); return { type: 'ChipCall', name: part.getName(), arguments: callArguments }; }); return this._ast = { type: 'Chip', name: this.getName(), inputs: inputs, outputs: outputs, parts: parts, builtins: [], clocked: [] }; } }], [{ key: 'isClocked', value: function isClocked() { // This default value is overridden in the child classes // created from HDL files. return false; } }]); return CompositeGate; }(Gate); module.exports = CompositeGate;