hdl-js
Version:
Hardware definition language (HDL) and Hardware simulator
143 lines (121 loc) • 3.19 kB
JavaScript
/**
* The MIT License (MIT)
* Copyright (c) 2017-present Dmitry Soshnikov <dmitry.soshnikov@gmail.com>
*/
;
/**
* Helper `gen` function calls node type handler.
*/
function gen(node) {
return node ? generator[node.type](node) : '';
}
/**
* Generates input pins.
*/
function genInputs(inputs) {
return 'IN ' + inputs.map(gen).join(', ') + ';';
}
/**
* Generates output pins.
*/
function genOutputs(outputs) {
return 'OUT ' + outputs.map(gen).join(', ') + ';';
}
/**
* Generates parts implementation.
*/
function genParts(parts) {
if (!parts || parts.length === 0) {
return '';
}
return '\n\n PARTS:\n\n ' + parts.map(gen).join(';\n') + ';';
}
/**
* Generates builtin chips list.
*/
function genBuiltins(builtins) {
if (!builtins || builtins.length === 0) {
return '';
}
return '\n\n BUILTIN ' + builtins.map(gen).join(', ') + ';';
}
/**
* Generates clocked pins.
*/
function genClocked(clocked) {
if (!clocked || clocked.length === 0) {
return '';
}
return '\n\n CLOCKED ' + clocked.map(gen).join(', ') + ';';
}
/**
* AST handler.
*/
var generator = {
Chip: function Chip(node) {
return '\n CHIP ' + node.name + ' {\n ' + genInputs(node.inputs) + '\n ' + genOutputs(node.outputs) +
// Optional parts:
genParts(node.parts) + genBuiltins(node.builtins) + genClocked(node.clocked) + '\n }\n ';
},
Name: function Name(node) {
var name = node.value;
// a[1]
if (node.hasOwnProperty('index')) {
return name + '[' + node.index + ']';
}
// a[1]
if (node.hasOwnProperty('size')) {
return name + '[' + node.size + ']';
}
// a[0..3]
if (node.hasOwnProperty('range')) {
return name + '[' + node.range.from + '..' + node.range.to + ']';
}
// a
return name;
},
ChipCall: function ChipCall(node) {
var args = node.arguments.map(gen).join(', ');
return node.name + '(' + args + ')';
},
Argument: function Argument(node) {
return gen(node.name) + '=' + gen(node.value);
},
Constant: function Constant(node) {
return node.raw;
}
};
/**
* Reformats the code according to options.
*/
function reformat(code) {
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
_ref$indent = _ref.indent,
indent = _ref$indent === undefined ? 2 : _ref$indent;
return code.trim().split('\n').map(function (line, index, arr) {
line = line.trim();
if (line && index > 0 && index < arr.length - 1) {
line = ' '.repeat(indent) + line;
}
return line;
}).join('\n');
}
module.exports = {
/**
* Generates an HDL code from AST.
*
* options: {indent = 2}
*/
fromAST: function fromAST(node, options) {
var hdl = reformat(gen(node), options);
return ['/**', ' * Automatically generated by hdl-js "' + node.name + '" gate.', ' */', hdl].join('\n');
},
/**
* Generates an HDL code from a CompositeGate instance.
*
* options: see `generateFromAST`.
*/
fromCompositeGate: function fromCompositeGate(compositeGate, options) {
return this.fromAST(compositeGate.toAST(), options);
}
};