[
  {
    "path": ".gitignore",
    "content": "node_modules\n"
  },
  {
    "path": "Combinational/arithmetics.js",
    "content": "const { AndGate, XorGate, OrGate } = require('./gates')\nconst { wires } = require('../Connectors/transport')\nconst { Hardware } = require('../Utility/new')\n\nclass HalfAdder extends Hardware {\n\n  constructor(x, s) {\n    if (x.length != 2 || s.length != 2) throw new Error('Invalid Connection/s')\n    super([x, s])\n    this.components.push(new XorGate([x[0]], [x[1]], [s[1]]))\n    this.components.push(new AndGate([x[0]], [x[1]], [s[0]]))\n  }\n\n}\n\nclass FullAdder extends Hardware {\n\n  constructor(x, s) {\n    if (x.length != 3 || s.length != 2) throw new Error('Invalid Connection/s')\n    super([x, s])\n    this.internalWiring = wires(3)\n    this.components.push(new HalfAdder([x[0], x[1]], [this.internalWiring[0], this.internalWiring[1]]))\n    this.components.push(new HalfAdder([this.internalWiring[1], x[2]], [this.internalWiring[2], s[1]]))\n    this.components.push(new OrGate([this.internalWiring[0]], [this.internalWiring[2]], [s[0]]))\n  }\n\n}\n\nclass PipoAdder extends Hardware {\n\n  constructor(a, b, s) {\n    if (a.length != b.length || s.length != a.length + 1) throw new Error('Invalid Connection/s')\n    super([a, b, s])\n    let size = a.length\n    this.internalWiring = wires(size)\n    if (size > 1) {\n      this.components.push(new FullAdder([a[0], b[0], this.internalWiring[0]], [this.internalWiring[1], s[size]]))\n      for(let i = 1; i < size - 1; i++) {\n        this.components.push(new FullAdder([a[i], b[i], this.internalWiring[i]], [this.internalWiring[i+1], s[size-i]]))\n      }\n      this.components.push(new FullAdder([a[size-1], b[size-1], this.internalWiring[size-1]], [s[0], s[1]]))\n    } else {\n      this.components.push(new FullAdder([a[0], b[0], this.internalWiring[0]], [s[0], s[1]]))\n    }\n    this.internalWiring[0].propagateSignal(0)\n  }\n\n}\n\nmodule.exports = { HalfAdder, FullAdder, PipoAdder }\n"
  },
  {
    "path": "Combinational/decoders.js",
    "content": "const { Hardware } = require('../Utility/new')\nconst { wires } = require('../Connectors/transport')\nconst { NotGate, AndGate } = require('./gates')\n\nclass Decoder1x2 extends Hardware {\n\n  constructor(x, o) {\n    if (x.length != 1 || o.length != 1) throw new Error('Invalid Connection/s')\n    super([x, [o[0], x[0]]])\n    this.components.push(new NotGate(x, o))\n  }\n\n}\n\nclass Decoder2x4 extends Hardware {\n\n  constructor(x0, x1, o) {\n    if(x0.length != 1 || x1.length != 1 || o.length != 4) throw new Error('Invalid Connection/s')\n    super([x0, x1, o])\n    this.internalWiring = wires(2)\n    this.components.push(new Decoder1x2(x0, [this.internalWiring[0]]))\n    this.components.push(new Decoder1x2(x1, [this.internalWiring[1]]))\n    this.components.push(new AndGate([this.internalWiring[0]], [this.internalWiring[1]], [o[0]]))\n    this.components.push(new AndGate([this.internalWiring[0]], x1, [o[1]]))\n    this.components.push(new AndGate(x0, [this.internalWiring[1]], [o[2]]))\n    this.components.push(new AndGate(x0, x1, [o[3]]))\n  }\n\n}\n\nmodule.exports = { Decoder1x2, Decoder2x4 }\n"
  },
  {
    "path": "Combinational/gates.js",
    "content": "const { Hardware } = require('../Utility/new')\n\nclass AndGate extends Hardware {\n\n  constructor(x, y, o) {\n    if (x.length != 1 || y.length != 1 || o.length != 1) throw new Error('Invalid Connection/s')\n    super([x, y, o])\n    this.x = x\n    this.y = y\n    this.o = o\n    this.hardware = this.hardware.bind(this)\n    x[0].on('signal', this.hardware)\n    y[0].on('signal', this.hardware)\n  }\n\n  hardware() {\n    let xSig = this.x[0].getSignal()\n    let ySig = this.y[0].getSignal()\n    if (xSig === 0 || ySig === 0) {\n      this.o[0].propagateSignal(0)\n    } else if (xSig === undefined || ySig === undefined) {\n      this.o[0].propagateSignal(undefined)\n    } else this.o[0].propagateSignal(xSig && ySig)\n  }\n\n}\n\nclass TriInpAndGate extends Hardware {\n\n  constructor(x, y, z, o) {\n    if (x.length != 1 || y.length != 1 || z.length != 1 || o.length != 1) throw new Error('Invalid Connection/s')\n    super([x, y, z, o])\n    this.x = x\n    this.y = y\n    this.z = z\n    this.o = o\n    this.hardware = this.hardware.bind(this)\n    x[0].on('signal', this.hardware)\n    y[0].on('signal', this.hardware)\n    z[0].on('signal', this.hardware)\n  }\n\n  hardware() {\n    let xSig = this.x[0].getSignal()\n    let ySig = this.y[0].getSignal()\n    let zSig = this.z[0].getSignal()\n    if (xSig === 0 || ySig === 0 || zSig === 0) {\n      this.o[0].propagateSignal(0)\n    } else if (xSig === undefined || ySig === undefined || zSig === undefined) {\n      this.o[0].propagateSignal(undefined)\n    } else this.o[0].propagateSignal(xSig && ySig && zSig)\n  }\n\n}\n\nclass OrGate extends Hardware {\n\n  constructor(x, y, o) {\n    if (x.length != 1 || y.length != 1 || o.length != 1) throw new Error('Invalid Connection/s')\n    super([x, y, o])\n    this.x = x\n    this.y = y\n    this.o  = o\n    this.hardware = this.hardware.bind(this)\n    x[0].on('signal', this.hardware)\n    y[0].on('signal', this.hardware)\n  }\n\n  hardware() {\n    let xSig = this.x[0].getSignal()\n    let ySig = this.y[0].getSignal()\n    if (xSig === 1 || ySig === 1) {\n      this.o[0].propagateSignal(1)\n    } else if (xSig === undefined || ySig === undefined) {\n      this.o[0].propagateSignal(undefined)\n    } else this.o[0].propagateSignal(xSig || ySig)\n  }\n\n}\n\nclass XorGate extends Hardware {\n\n  constructor(x, y, o) {\n    if (x.length != 1 || y.length != 1 || o.length != 1) throw new Error('Invalid Connection/s')\n    super([x, y, o])\n    this.x = x\n    this.y = y\n    this.o  = o\n    this.hardware = this.hardware.bind(this)\n    x[0].on('signal', this.hardware)\n    y[0].on('signal', this.hardware)\n  }\n\n  hardware() {\n    let xSig = this.x[0].getSignal()\n    let ySig = this.y[0].getSignal()\n    if (xSig === undefined || ySig === undefined) {\n      this.o[0].propagateSignal(undefined)\n    } else this.o[0].propagateSignal(Number(xSig != ySig))\n  }\n\n}\n\nclass NotGate extends Hardware {\n\n  constructor(x, o) {\n    if (x.length != 1 || o.length != 1) throw new Error('Invalid Connection/s')\n    super([x, o])\n    this.x = x\n    this.o = o\n    this.hardware = this.hardware.bind(this)\n    x[0].on('signal', this.hardware)\n  }\n\n  hardware() {\n    let xSig = this.x[0].getSignal()\n    if (xSig === undefined) {\n      this.o[0].propagateSignal(undefined)\n    } else this.o[0].propagateSignal(Number(!xSig))\n  }\n\n}\n\nclass NandGate extends Hardware {\n\n  constructor(x, y, o) {\n    if (x.length != 1 || y.length != 1 || o.length != 1) throw new Error('Invalid Connection/s')\n    super([x, y, o])\n    this.x = x\n    this.y = y\n    this.o  = o\n    this.hardware = this.hardware.bind(this)\n    x[0].on('signal', this.hardware)\n    y[0].on('signal', this.hardware)\n  }\n\n  hardware() {\n    let xSig = this.x[0].getSignal()\n    let ySig = this.y[0].getSignal()\n    if (xSig === 0 || ySig === 0) {\n      this.o[0].propagateSignal(1)\n    } else if (xSig === undefined || ySig === undefined) {\n      this.o[0].propagateSignal(undefined)\n    } else this.o[0].propagateSignal(Number(!(xSig && ySig)))\n  }\n\n}\n\nclass NorGate extends Hardware {\n\n  constructor(x, y, o) {\n    if (x.length != 1 || y.length != 1 || o.length != 1) throw new Error('Invalid Connection/s')\n    super([x, y, o])\n    this.x = x\n    this.y = y\n    this.o  = o\n    this.hardware = this.hardware.bind(this)\n    x[0].on('signal', this.hardware)\n    y[0].on('signal', this.hardware)\n  }\n\n  hardware() {\n    let xSig = this.x[0].getSignal()\n    let ySig = this.y[0].getSignal()\n    if (xSig === 1 || ySig === 1) {\n      this.o[0].propagateSignal(0)\n    } else if (xSig === undefined || ySig === undefined) {\n      this.o[0].propagateSignal(undefined)\n    } else this.o[0].propagateSignal(Number(!(xSig || ySig)))\n  }\n\n}\n\nclass XnorGate extends Hardware {\n\n  constructor(x, y, o) {\n    if (x.length != 1 || y.length != 1 || o.length != 1) throw new Error('Invalid Connection/s')\n    super([x, y, o])\n    this.x = x\n    this.y = y\n    this.o  = o\n    this.hardware = this.hardware.bind(this)\n    x[0].on('signal', this.hardware)\n    y[0].on('signal', this.hardware)\n  }\n\n  hardware() {\n    let xSig = this.x[0].getSignal()\n    let ySig = this.y[0].getSignal()\n    if (xSig === undefined || ySig === undefined) {\n      this.o[0].propagateSignal(undefined)\n    } else this.o[0].propagateSignal(Number(xSig == ySig))\n  }\n\n}\n\nmodule.exports = { AndGate, TriInpAndGate, OrGate, XorGate, NotGate, NandGate, NorGate, XnorGate }\n"
  },
  {
    "path": "Connectors/transport.js",
    "content": "const EventEmitter = require('events')\n\nclass Wire extends EventEmitter {\n\n  constructor(sig) {\n    super()\n\n    this.signal = sig\n    this.propagateSignal = this.propagateSignal.bind(this)\n    this.getSignal = this.getSignal.bind(this)\n  }\n\n  propagateSignal(newSignal) {\n    let oldSignal = this.signal\n\n    this.signal = newSignal\n\n    if (oldSignal != this.signal) this.emit('signal')\n  }\n\n  getSignal() {\n    return this.signal\n  }\n\n}\n\nclass Pulse extends Wire {\n\n  constructor(t, i) {\n    super()\n\n    this.i = i\n    this.timePeriod = t\n    this.alter = this.alter.bind(this)\n    this.switchOn = this.switchOn.bind(this)\n    this.switchOff = this.switchOff.bind(this)\n    this.interval = undefined\n  }\n\n  alter() {\n    this.propagateSignal(Number(!this.signal))\n  }\n\n  switchOn() {\n    if (!this.interval) {\n      this.signal = this.i\n      this.interval = setInterval(this.alter, this.timePeriod)\n    }\n  }\n\n  switchOff() {\n    if (this.interval) {\n      clearInterval(this.interval)\n      this.signal = undefined\n      this.interval = undefined\n    }\n  }\n\n}\n\nfunction wires(n) {\n  let wireSet = []\n  for(let i = 0; i < n ; i++) {\n    wireSet.push(new Wire())\n  }\n  return wireSet\n}\n\nmodule.exports = { Pulse, wires }\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017 Mayank Badola\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "![Architect](media/banner.png)\n\n> Highly Extensible Hardware Description Library for JavaScript Developers\n\nHardware is event-driven. And it is functional in nature, having abstractions on abstractions.\n\nMakes sense to have JavaScript emulate it doesn't it?\n\n### Motivation\n\nHardware Description can be fun and very educational, but I had to learn [VHDL](https://en.wikipedia.org/wiki/VHDL) to be able to do so.\n\nHence, being a JavaScript Enthusiast, I decided to write this library down for JavaScript Developers who wanted to get into Hardware Description but were reluctant to learn a new language for it.\n\nFor people not acquainted with both VHDL and JS, I'm pretty sure the learning curve would be lesser for this library. Although I cannot state that my library is better as it is not easy to compete with a language intended for hardware description, nevertheless, I will keep on hacking this library to see how this experiment goes.\n\nLet's get to business!\n\n### Installation\n\n`npm install architectjs`\n\n### Existing Hardware Abstractions\n\n* Gates\n  * AndGate\n  * TriInpAndGate\n  * OrGate\n  * XorGate\n  * NotGate\n  * NandGate\n  * NorGate\n  * XnorGate\n* Decoders\n  * Decoder1x2\n  * Decoder2x4\n* Arithmetics\n  * HalfAdder\n  * FullAdder\n  * PipoAdder\n* Flip-Flops\n  * SRFlipFlop\n  * DFlipFlop\n\n### :electric_plug: Plug-n-Play\n\nUse existing abstractions seemlessly.\n\nLet's plug in an AND-Gate\n\n```js\nconst { wires } = require('architectjs')('Connectors')\nconst { AndGate } = require('architectjs')('Gates')\nconst { StringIO } = require('architectjs')('IO')\n\n// provision wires to connect to your hardware\nconst inputA = wires(1)\nconst inputB = wires(1)\nconst output = wires(1)\n// initialise the hardware\nconst hWare = new AndGate(inputA, inputB, output)\n// wrap hardware in a I/O BlackBox\n// this is compulsory, to be able to do I/O using strings\nconst ioHandler = new StringIO(hWare)\n\nconsole.log(ioHandler.input('1', '1')) // prints 1\n\nconsole.log(ioHandler.input('0', '0')) // prints 0\n```\n\nSay what? `AND` is way too easy to be called an abstraction?\n\nNo worries, let's plug in this generalised Parallel-in-Parallel-out Adder!\n\n```js\nconst { wires } = require('architectjs')('Connectors')\nconst { PipoAdder } = require('architectjs')('Arithmetics')\nconst { StringIO } = require('architectjs')('IO')\n\n// code for 4-bit adder\nconst inputA = wires(4)\nconst inputB = wires(4)\nconst sum = wires(5)\nconst hWare = new PipoAdder(inputA, inputB, sum)\nconst ioHandler = new StringIO(hWare)\nconsole.log(ioHandler.input('1111', '1111')) // prints 11110\n```\n\nOr maybe we want to build something from existing abstractions?\n\n#### Abstraction Rules and Specs\n\n* Every Class/hardware extends on `Hardware`.\n* Every initialisation argument to the class instance has to be an array of `Wire` instances (obtained from the `wires` method).\n* An array consisting of I/O `wires` is passed onto the parent class `Hardware`, with only the last element being the output parameter. It is necessary to provide every input parameter and the output parameter to be able to wrap this in a `StringIO` instance to do I/O operations with `string` arguments.\n* Every class instance has two instance variables available from the parent `Hardware` instance :\n  * internalWiring - Array of `Wire` instances (initially empty).\n  * components - Array of abstractions used to build your hardware (initially empty).\n* Your entire logic goes into your Class' constructor.\n* `internalWiring` variable is used to initialise `Wire` instances that are not a part of the I/O for the hardware but are required to inter-connect the sub-components in your abstraction.\n* `components` variable is used to store instances of subcomponents used in your hardware. This helps a designer to quickly refer to all the build blocks that went into making a particular piece of hardware.\n\n\nLet's build a 4-input AND Gate using the above rules and specifications.\n\n```js\nconst { wires } = require('architectjs')('Connectors')\nconst { AndGate } = require('architectjs')('Gates')\nconst { StringIO } = require('architectjs')('IO')\nconst { Hardware } = require('architectjs')('Base')\n\nclass FourInpAndGate extends Hardware {\n\n  constructor(a, b, c, d, o) {\n    super([a, b, c, d, o])\n    this.internalWiring = wires(2) // declare wires to be used internally\n    this.components.push(new AndGate(a, b, this.internalWiring[0]))\n    this.components.push(new AndGate(c, d, this.internalWiring[1]))\n    this.components.push(new AndGate(this.internalWiring[0], this.internalWiring[1], o))\n  }\n\n}\n\nconst a = wires(1)\nconst b = wires(1)\nconst c = wires(1)\nconst d = wires(1)\nconst o = wires(1)\n\nconst fourInpAnd = new FourInpAndGate(a, b, c, d, o)\nconst ioHandler = new StringIO(fourInpAnd)\n\nconsole.log(ioHandler('0', '1', '1', '1')) // prints 0\n\nconsole.log(ioHandler('1', '1', '1', '1')) // prints 1\n```\n\n### Creating a Declarative Hardware Component\n\n#### Some Basic Rules\n\n* Every Class/hardware extends on `Hardware`.\n* All the logic goes inside the `hardware` method of your component's Class.\n* Event to be listened for must be `signal`.\n\n#### Let's get started\n\nEvery `Wire` instance extends on `EventEmitter`, thus this library essentially works by registering listeners in a Class instance and binding them to the `hardware` method of the Class.\n\nWith the help of `getSignal` and `propagateSignal` methods of `Wire`, read changes from input `Wire` instances, use your logic on them, and emit result through the output `Wire` instance.\n\nLet's set this up with an example taken from this library\n\n```js\nconst { Hardware } = require('architectjs')('Base')\n\nclass AndGate extends Hardware {\n\n  constructor(x, y, o) {\n    if (x.length != 1 || y.length != 1 || o.length != 1) throw new Error('Invalid Connection/s')\n    super([x, y, o])\n    this.x = x\n    this.y = y\n    this.o = o\n    this.hardware = this.hardware.bind(this)\n    x[0].on('signal', this.hardware)\n    y[0].on('signal', this.hardware)\n  }\n\n  hardware() {\n    let xSig = this.x[0].getSignal()\n    let ySig = this.y[0].getSignal()\n    if (xSig === 0 || ySig === 0) {\n      this.o[0].propagateSignal(0)\n    } else if (xSig === undefined || ySig === undefined) {\n      this.o[0].propagateSignal(undefined)\n    } else this.o[0].propagateSignal(xSig && ySig)\n  }\n\n}\n```\n### Development\n\nNew Hardware Component Proposals should be put up as an issue to discuss it's vialibility and modelling. I won't be considering anything else other than component proposals at the moment.\n\nI am also facing some problems in figuring out how to implement clock-edge driven circuits and circuits that have a feedback to them. Most of time, infinte events are triggered due to the feedbacking in the circuits.\n\nThere are just so many possibilities to do here! Would love to get contributions from the community :smile:\n"
  },
  {
    "path": "Sequential/ff.js",
    "content": "const { AndGate, NorGate, NandGate, NotGate } = require('../Combinational/gates')\nconst { wires } = require('../Connectors/transport')\nconst { Hardware } = require('../Utility/new')\n\nclass SRFlipFlop extends Hardware {\n\n  constructor(s, r, qqbar, c) {\n    if (s.length != 1 || r.length != 1 || qqbar.length != 2) throw new Error('Invalid Connection/s')\n    super([s, r, [qqbar[0]]])\n    this.internalWiring = wires(2)\n    this.components.push(new AndGate([c], s, [this.internalWiring[0]]))\n    this.components.push(new AndGate([c], r, [this.internalWiring[1]]))\n    this.components.push(new NorGate([this.internalWiring[0]], [qqbar[0]], [qqbar[1]]))\n    this.components.push(new NorGate([this.internalWiring[1]], [qqbar[1]], [qqbar[0]]))\n  }\n\n}\n\nclass DFlipFlop extends Hardware {\n\n  constructor(d, qqbar, c) {\n    if (d.length != 1 || qqbar.length != 2) throw new Error('Invalid Connection/s')\n    super([d, [qqbar[0]]])\n    this.internalWiring = wires(3)\n    this.components.push(new NotGate(d, [this.internalWiring[0]]))\n    this.components.push(new NandGate([c], d, [this.internalWiring[1]]))\n    this.components.push(new NandGate([c], [this.internalWiring[0]], [this.internalWiring[2]]))\n    this.components.push(new NandGate([this.internalWiring[1]], [qqbar[1]], [qqbar[0]]))\n    this.components.push(new NandGate([this.internalWiring[2]], [qqbar[0]], [qqbar[1]]))\n  }\n\n}\n\nmodule.exports = { SRFlipFlop, DFlipFlop }\n"
  },
  {
    "path": "Utility/ioManager.js",
    "content": "class StringIO {\n\n  constructor({ioMapping}) {\n    let inputGroup = ioMapping.length - 1\n    this.i = ioMapping.slice(0, inputGroup)\n    this.o = ioMapping[inputGroup]\n  }\n\n  input(...inputSeqs) {\n    let inpIndex = inputSeqs[0].length - 1\n    let totalInps = this.i.length\n    let pos = 0\n    while (inpIndex >= 0) {\n      for (let inpNum = 0; inpNum < totalInps; ++inpNum) {\n        this.i[inpNum][pos].propagateSignal(Number(inputSeqs[inpNum][inpIndex]))\n      }\n      ++pos\n      --inpIndex\n    }\n\n    let outBuff = this.o.map((wire) => {\n      return wire.getSignal()\n    })\n\n    outBuff = outBuff.join('')\n\n    return outBuff\n  }\n\n}\n\nmodule.exports = { StringIO }\n"
  },
  {
    "path": "Utility/new.js",
    "content": "class Hardware {\n\n  constructor(io) {\n    this.ioMapping = io\n    this.internalWiring = []\n    this.components = []\n  }\n\n}\n\nmodule.exports = { Hardware }\n"
  },
  {
    "path": "index.js",
    "content": "module.exports = function(path) {\n  return {\n    'Gates': require('./Combinational/gates'),\n    'Arithmetics': require('./Combinational/arithmetics'),\n    'Connectors': require('./Connectors/transport'),\n    'Sequential': require('./Sequential/ff'),\n    'IO': require('./Utility/ioManager'),\n    'Base': require('./Utility/new')\n  } [ path ]\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"architectjs\",\n  \"version\": \"0.1.2\",\n  \"description\": \"Hardware Description and Emulation Library\",\n  \"keywords\": [\n    \"hardware\",\n    \"design\",\n    \"emulation\",\n    \"hardware emulation\",\n    \"vhdl\",\n    \"architect\",\n    \"architectjs\",\n    \"library\"\n  ],\n  \"scripts\": {\n    \"test\": \"ava\"\n  },\n  \"repository\": \"mbad0la/Architect\",\n  \"author\": {\n    \"name\": \"Mayank Badola\",\n    \"email\": \"badola21295@gmail.com\",\n    \"url\": \"https://mayankbadola.me\"\n  },\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"ava\": \"^0.25.0\"\n  }\n}\n"
  },
  {
    "path": "test.js",
    "content": "import test from 'ava'\nimport { wires, Pulse } from './Connectors/transport'\nimport { NotGate, AndGate, TriInpAndGate, XorGate } from './Combinational/gates'\nimport { PipoAdder, HalfAdder, FullAdder } from './Combinational/arithmetics'\nimport { SRFlipFlop } from './Sequential/ff'\nimport { StringIO } from './Utility/ioManager'\nimport { Decoder1x2, Decoder2x4 } from './Combinational/decoders'\n\n\ntest('Not-Gate : 1', t => {\n  const inputA = wires(1)\n  const output = wires(1)\n  const hWare = new NotGate(inputA, output)\n  const ioHandler = new StringIO(hWare)\n  t.is(ioHandler.input('1'), '0')\n})\n\ntest('Not-Gate : 2', t => {\n  const inputA = wires(1)\n  const output = wires(1)\n  const hWare = new NotGate(inputA, output)\n  const ioHandler = new StringIO(hWare)\n  t.is(ioHandler.input('0'), '1')\n})\n\ntest('And-Gate : 1', t => {\n  const inputA = wires(1)\n  const inputB = wires(1)\n  const output = wires(1)\n  const hWare = new AndGate(inputA, inputB, output)\n  const ioHandler = new StringIO(hWare)\n  t.is(ioHandler.input('0', '0'), '0')\n})\n\ntest('And-Gate : 2', t => {\n  const inputA = wires(1)\n  const inputB = wires(1)\n  const output = wires(1)\n  const hWare = new AndGate(inputA, inputB, output)\n  const ioHandler = new StringIO(hWare)\n  t.is(ioHandler.input('0', '1'), '0')\n})\n\ntest('And-Gate : 3', t => {\n  const inputA = wires(1)\n  const inputB = wires(1)\n  const output = wires(1)\n  const hWare = new AndGate(inputA, inputB, output)\n  const ioHandler = new StringIO(hWare)\n  t.is(ioHandler.input('1', '1'), '1')\n})\n\ntest('Tri-Input And-Gate', t => {\n  const inputX = wires(1)\n  const inputY = wires(1)\n  const inputZ = wires(1)\n  const output = wires(1)\n  const hWare = new TriInpAndGate(inputX, inputY, inputZ, output)\n  const ioHandler = new StringIO(hWare)\n  t.is(ioHandler.input('1', '1', '1'), '1')\n})\n\ntest('Xor-Gate : 1', t => {\n  const inputA = wires(1)\n  const inputB = wires(1)\n  const output = wires(1)\n  const hWare = new XorGate(inputA, inputB, output)\n  const ioHandler = new StringIO(hWare)\n  t.is(ioHandler.input('1', '1'), '0')\n})\n\ntest('Xor-Gate : 2', t => {\n  const inputA = wires(1)\n  const inputB = wires(1)\n  const output = wires(1)\n  const hWare = new XorGate(inputA, inputB, output)\n  const ioHandler = new StringIO(hWare)\n  t.is(ioHandler.input('0', '1'), '1')\n})\n\ntest('Overflow for HalfAdder', t => {\n  const inputA = wires(2)\n  const sum = wires(2)\n  const hWare = new HalfAdder(inputA, sum)\n  const ioHandler = new StringIO(hWare)\n  t.is(ioHandler.input('11'), '10')\n})\n\ntest('Overflow for FullAdder', t => {\n  const inputA = wires(3)\n  const sum = wires(2)\n  const hWare = new FullAdder(inputA, sum)\n  const ioHandler = new StringIO(hWare)\n  t.is(ioHandler.input('111'), '11')\n})\n\ntest('Overflow for Parallel Adder (1 bit)', t => {\n  const inputA = wires(1)\n  const inputB = wires(1)\n  const sum = wires(2)\n  const hWare = new PipoAdder(inputA, inputB, sum)\n  const ioHandler = new StringIO(hWare)\n  t.is(ioHandler.input('1', '1'), '10')\n})\n\ntest('Overflow for Parallel Adder (2 bit)', t => {\n  const inputA = wires(2)\n  const inputB = wires(2)\n  const sum = wires(3)\n  const hWare = new PipoAdder(inputA, inputB, sum)\n  const ioHandler = new StringIO(hWare)\n  t.is(ioHandler.input('11', '11'), '110')\n})\n\ntest('Overflow for Parallel Adder (4 bit)', t => {\n  const inputA = wires(4)\n  const inputB = wires(4)\n  const sum = wires(5)\n  const hWare = new PipoAdder(inputA, inputB, sum)\n  const ioHandler = new StringIO(hWare)\n  t.is(ioHandler.input('1111', '1111'), '11110')\n})\n\ntest('HalfAdder - 1 bit PIPO Equivalence : 1', t => {\n  const inputA = wires(1)\n  const inputB = wires(1)\n  const sum1 = wires(2)\n  const halfAdderInput = wires(2)\n  const sum2 = wires(2)\n  const hWare1 = new PipoAdder(inputA, inputB, sum1)\n  const hWare2 = new HalfAdder(halfAdderInput, sum2)\n  const ioHandler1 = new StringIO(hWare1)\n  const ioHandler2 = new StringIO(hWare2)\n  t.is(ioHandler1.input('1', '1'), ioHandler2.input('11'))\n})\n\ntest('HalfAdder - 1 bit PIPO Equivalence : 2', t => {\n  const inputA = wires(1)\n  const inputB = wires(1)\n  const sum1 = wires(2)\n  const halfAdderInput = wires(2)\n  const sum2 = wires(2)\n  const hWare1 = new PipoAdder(inputA, inputB, sum1)\n  const hWare2 = new HalfAdder(halfAdderInput, sum2)\n  const ioHandler1 = new StringIO(hWare1)\n  const ioHandler2 = new StringIO(hWare2)\n  t.is(ioHandler1.input('1', '0'), ioHandler2.input('10'))\n})\n\ntest('HalfAdder - 1 bit PIPO Equivalence : 3', t => {\n  const inputA = wires(1)\n  const inputB = wires(1)\n  const sum1 = wires(2)\n  const halfAdderInput = wires(2)\n  const sum2 = wires(2)\n  const hWare1 = new PipoAdder(inputA, inputB, sum1)\n  const hWare2 = new HalfAdder(halfAdderInput, sum2)\n  const ioHandler1 = new StringIO(hWare1)\n  const ioHandler2 = new StringIO(hWare2)\n  t.is(ioHandler1.input('0', '0'), ioHandler2.input('00'))\n})\n\ntest('SR-Flip-Flop : Set', t => {\n  const s = wires(1)\n  const r = wires(1)\n  const qqbar = wires(2)\n  const clock = new Pulse(500, 1)\n  clock.switchOn()\n  const ff = new SRFlipFlop(s, r, qqbar, clock)\n  const ioHandler = new StringIO(ff)\n  t.is(ioHandler.input('1', '0'), '1')\n  clock.switchOff()\n})\n\ntest('SR-Flip-Flop : Reset', t => {\n  const s = wires(1)\n  const r = wires(1)\n  const qqbar = wires(2)\n  const clock = new Pulse(500, 1)\n  clock.switchOn()\n  const ff = new SRFlipFlop(s, r, qqbar, clock)\n  const ioHandler = new StringIO(ff)\n  t.is(ioHandler.input('0', '1'), '0')\n  clock.switchOff()\n})\n\ntest('SR-Flip-Flop : No Change', t => {\n  const s = wires(1)\n  const r = wires(1)\n  const qqbar = wires(2)\n  const clock = new Pulse(500, 1)\n  clock.switchOn()\n  const ff = new SRFlipFlop(s, r, qqbar, clock)\n  const ioHandler = new StringIO(ff)\n  const prevQ = ioHandler.input('0', '1')\n  t.is(ioHandler.input('0', '0'), prevQ)\n  clock.switchOff()\n})\n\ntest('1x2 Decoder : 1', t => {\n  const inputA = wires(1)\n  const outputA = wires(1)\n  const linerDecoder = new Decoder1x2(inputA, outputA)\n  const ioHandler = new StringIO(linerDecoder)\n  t.is(ioHandler.input('0'), '10')\n})\n\ntest('1x2 Decoder : 2', t => {\n  const inputA = wires(1)\n  const outputA = wires(1)\n  const linerDecoder = new Decoder1x2(inputA, outputA)\n  const ioHandler = new StringIO(linerDecoder)\n  t.is(ioHandler.input('1'), '01')\n})\n\ntest('2x4 Decoder : 1', t => {\n  const inputX = wires(1)\n  const inputY = wires(1)\n  const output = wires(4)\n  const d2x4 = new Decoder2x4(inputX, inputY, output)\n  const ioHandler = new StringIO(d2x4)\n  t.is(ioHandler.input('0', '0'), '1000')\n})\n\ntest('2x4 Decoder : 2', t => {\n  const inputX = wires(1)\n  const inputY = wires(1)\n  const output = wires(4)\n  const d2x4 = new Decoder2x4(inputX, inputY, output)\n  const ioHandler = new StringIO(d2x4)\n  t.is(ioHandler.input('1' ,'0'), '0010')\n})\n\ntest('2x4 Decoder : 3', t => {\n  const inputX = wires(1)\n  const inputY = wires(1)\n  const output = wires(4)\n  const d2x4 = new Decoder2x4(inputX, inputY, output)\n  const ioHandler = new StringIO(d2x4)\n  t.is(ioHandler.input('1', '1'), '0001')\n})\n"
  }
]