Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tinyfpga support #193

Merged
merged 8 commits into from
Jan 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@
"icon": "resources/images/icestudio-logo.png"
},
"apio": {
"min": "0.3.0b3",
"min": "0.3.0b4",
"max": "0.4.0",
"extras": [
"tinyfpgab"
],
"external": ""
},
"collection": "0.3.0",
"engines": {
"node": ">= 0.10.0"
},
Expand Down
2 changes: 1 addition & 1 deletion app/resources/boards/TinyFPGA-B2/pinout.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"type": "inout", "name": "PIN_1_USB_DP", "value": "A3"}, {"type": "inout", "name": "PIN_2_USB_DN", "value": "A4"}, {"type": "input", "name": "CLK", "value": "B4"}, {"type": "inout", "name": "PIN_4", "value": "B2"}, {"type": "inout", "name": "PIN_5", "value": "A2"}, {"type": "inout", "name": "PIN_6", "value": "A1"}, {"type": "inout", "name": "PIN_7", "value": "B1"}, {"type": "inout", "name": "PIN_8", "value": "C1"}, {"type": "inout", "name": "PIN_9", "value": "D1"}, {"type": "inout", "name": "PIN_10", "value": "E1"}, {"type": "inout", "name": "PIN_11", "value": "G1"}, {"type": "inout", "name": "PIN_12", "value": "H1"}, {"type": "inout", "name": "PIN_13", "value": "J1"}, {"type": "inout", "name": "PIN_14_SDO", "value": "G6"}, {"type": "inout", "name": "PIN_15_SDI", "value": "H7"}, {"type": "inout", "name": "PIN_16_SCK", "value": "G7"}, {"type": "inout", "name": "PIN_17_SS", "value": "F7"}, {"type": "inout", "name": "PIN_18", "value": "D9"}, {"type": "inout", "name": "PIN_19", "value": "C9"}, {"type": "inout", "name": "PIN_20", "value": "E8"}, {"type": "inout", "name": "PIN_21", "value": "A9"}, {"type": "inout", "name": "PIN_22", "value": "A8"}, {"type": "inout", "name": "PIN_23", "value": "A7"}, {"type": "inout", "name": "PIN_24", "value": "A6"}]
[{"type": "inout", "name": "USB_DP", "value": "A3"}, {"type": "inout", "name": "USB_DM", "value": "A4"}, {"type": "input", "name": "CLK", "value": "B4"}, {"type": "inout", "name": "PIN_4", "value": "B2"}, {"type": "inout", "name": "PIN_5", "value": "A2"}, {"type": "inout", "name": "PIN_6", "value": "A1"}, {"type": "inout", "name": "PIN_7", "value": "B1"}, {"type": "inout", "name": "PIN_8", "value": "C1"}, {"type": "inout", "name": "PIN_9", "value": "D1"}, {"type": "inout", "name": "PIN_10", "value": "E1"}, {"type": "inout", "name": "PIN_11", "value": "G1"}, {"type": "inout", "name": "PIN_12", "value": "H1"}, {"type": "inout", "name": "PIN_13", "value": "J1"}, {"type": "inout", "name": "SDO", "value": "G6"}, {"type": "inout", "name": "SDI", "value": "H7"}, {"type": "inout", "name": "SCK", "value": "G7"}, {"type": "inout", "name": "SS", "value": "F7"}, {"type": "inout", "name": "PIN_18", "value": "D9"}, {"type": "inout", "name": "PIN_19", "value": "C9"}, {"type": "inout", "name": "PIN_20", "value": "E8"}, {"type": "inout", "name": "PIN_21", "value": "A9"}, {"type": "inout", "name": "PIN_22", "value": "A8"}, {"type": "inout", "name": "PIN_23", "value": "A7"}, {"type": "inout", "name": "PIN_24", "value": "A6"}]
32 changes: 16 additions & 16 deletions app/resources/boards/TinyFPGA-B2/pinout.pcf
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,27 @@
# -----------------------------------------------------------------------------
#
# TinyFPGA B-series information: https://github.com/tinyfpga/TinyFPGA-B-Series/
### left side of board
set_io --warn-no-port PIN_1_USB_DP A3
set_io --warn-no-port PIN_2_USB_DN A4
set_io --warn-no-port CLK B4 # input
set_io --warn-no-port PIN_4 B2
set_io --warn-no-port PIN_5 A2
set_io --warn-no-port PIN_6 A1
set_io --warn-no-port PIN_7 B1
set_io --warn-no-port PIN_8 C1
set_io --warn-no-port PIN_9 D1

# -- Left side of board
set_io --warn-no-port USB_DP A3
set_io --warn-no-port USB_DM A4
set_io --warn-no-port CLK B4 # input
set_io --warn-no-port PIN_4 B2
set_io --warn-no-port PIN_5 A2
set_io --warn-no-port PIN_6 A1
set_io --warn-no-port PIN_7 B1
set_io --warn-no-port PIN_8 C1
set_io --warn-no-port PIN_9 D1
set_io --warn-no-port PIN_10 E1
set_io --warn-no-port PIN_11 G1
set_io --warn-no-port PIN_12 H1
set_io --warn-no-port PIN_13 J1

### right side of board
set_io --warn-no-port PIN_14_SDO G6
set_io --warn-no-port PIN_15_SDI H7
set_io --warn-no-port PIN_16_SCK G7
set_io --warn-no-port PIN_17_SS F7
# -- Right side of board
set_io --warn-no-port SDO G6
set_io --warn-no-port SDI H7
set_io --warn-no-port SCK G7
set_io --warn-no-port SS F7
set_io --warn-no-port PIN_18 D9
set_io --warn-no-port PIN_19 C9
set_io --warn-no-port PIN_20 E8
Expand Down
4 changes: 2 additions & 2 deletions app/scripts/services/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,11 @@ angular.module('icestudio')
}

this.showToolchain = function () {
return this.selectedBoard.info.interface !== 'GPIO';
return (this.selectedBoard && this.selectedBoard.info.interface !== 'GPIO') || false;
};

this.showDrivers = function () {
return this.selectedBoard && (this.selectedBoard.info.interface === 'FTDI' || this.selectedBoard.info.interface === 'Serial');
return (this.selectedBoard && (this.selectedBoard.info.interface === 'FTDI' || this.selectedBoard.info.interface === 'Serial')) || false;
};

});
74 changes: 49 additions & 25 deletions app/scripts/services/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -325,13 +325,40 @@ angular.module('icestudio')

if (stdout) {
// - Apio errors
if (stdout.indexOf('[upload] Error') !== -1 ||
stdout.indexOf('Error: board not detected') !== -1) {
resultAlert = alertify.error(gettextCatalog.getString('Board {{name}} not detected', { name: utils.bold(common.selectedBoard.info.label) }), 30);
if (stdout.indexOf('Error: board not connected') !== -1) {
resultAlert = alertify.error(gettextCatalog.getString('Board {{name}} not connected', { name: utils.bold(common.selectedBoard.info.label) }), 30);
}
else if (stdout.indexOf('Error: unkown board') !== -1) {
else if (stdout.indexOf('Error: board not available') !== -1) {
resultAlert = alertify.error(gettextCatalog.getString('Board {{name}} not available', { name: utils.bold(common.selectedBoard.info.label) }), 30);
setupDriversAlert();
}
else if (stdout.indexOf('Error: unknown board') !== -1) {
resultAlert = alertify.error(gettextCatalog.getString('Unknown board'), 30);
}
else if (stdout.indexOf('[upload] Error') !== -1) {
switch (common.selectedBoard.name) {
// TinyFPGA-B2 programmer errors
case 'TinyFPGA-B2':
var match = stdout.match(/Bootloader\snot\sactive/g);
if (match && match.length === 3) {
resultAlert = alertify.error(gettextCatalog.getString('Bootloader not active'), 30);
}
else if (stdout.indexOf('Device or resource busy') !== -1) {
resultAlert = alertify.error(gettextCatalog.getString('Board {{name}} not available', { name: utils.bold(common.selectedBoard.info.label) }), 30);
setupDriversAlert();
}
else if (stdout.indexOf('device disconnected or multiple access on port') !== -1) {
resultAlert = alertify.error(gettextCatalog.getString('Board {{name}} disconnected', { name: utils.bold(common.selectedBoard.info.label) }), 30);
}
else {
resultAlert = alertify.error(gettextCatalog.getString(stdout), 30);
}
break;
default:
resultAlert = alertify.error(gettextCatalog.getString(stdout), 30);
}
console.warn(stdout);
}
// Yosys error (Mac OS)
else if (stdout.indexOf('Library not loaded:') !== -1 &&
stdout.indexOf('libffi') !== -1) {
Expand Down Expand Up @@ -724,7 +751,6 @@ angular.module('icestudio')
apioInstallIcestorm,
apioInstallIverilog,
apioInstallDrivers,
apioInstallScons,
installationCompleted
]);
}
Expand Down Expand Up @@ -782,7 +808,8 @@ angular.module('icestudio')
// Remote installation

function installOnlineApio(callback) {
updateProgress('pip install -U apio', 30);
var extraPackages = _package.apio.extras || [];
updateProgress('pip install -U apio[' + extraPackages.toString() + ']', 30);
utils.installOnlineApio(callback);
}

Expand All @@ -803,19 +830,14 @@ angular.module('icestudio')

function apioInstallDrivers(callback) {
if (common.WIN32) {
updateProgress('apio install drivers', 80);
updateProgress('apio install drivers', 90);
utils.apioInstall('drivers', callback);
}
else {
callback();
}
}

function apioInstallScons(callback) {
updateProgress('apio install scons', 90);
utils.apioInstall('scons', callback);
}

function installationCompleted(callback) {
checkToolchain(function() {
if (toolchain.installed) {
Expand All @@ -834,20 +856,22 @@ angular.module('icestudio')
}

function setupDriversAlert() {
var message = gettextCatalog.getString('Click here to <b>setup the drivers</b>');
if (!infoAlert) {
setTimeout(function() {
infoAlert = alertify.message(message, 30);
infoAlert.callback = function(isClicked) {
infoAlert = null;
if (isClicked) {
if (resultAlert) {
resultAlert.dismiss(false);
if (common.showDrivers()) {
var message = gettextCatalog.getString('Click here to <b>setup the drivers</b>');
if (!infoAlert) {
setTimeout(function() {
infoAlert = alertify.message(message, 30);
infoAlert.callback = function(isClicked) {
infoAlert = null;
if (isClicked) {
if (resultAlert) {
resultAlert.dismiss(false);
}
$rootScope.$broadcast('enableDrivers');
}
$rootScope.$broadcast('enableDrivers');
}
};
}, 1000);
};
}, 1000);
}
}
}

Expand Down
15 changes: 5 additions & 10 deletions app/scripts/services/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,20 +97,13 @@ angular.module('icestudio')

this.executeCommand = function(command, callback) {
nodeChildProcess.exec(command.join(' '),
function (error, stdout, stderr) {
function (error, stdout/*, stderr*/) {
// console.log(error, stdout, stderr);
if (error) {
this.enableKeyEvents();
this.enableClickEvents();
callback(true);
angular.element('#progress-message')
.text(stderr);
angular.element('#progress-bar')
.addClass('notransition progress-bar-danger')
.removeClass('progress-bar-info progress-bar-striped active')
.text('Error')
.attr('aria-valuenow', 100)
.css('width', '100%');
alertify.error(stdout, 30);
}
else {
callback();
Expand Down Expand Up @@ -178,7 +171,9 @@ angular.module('icestudio')
};

this.installOnlineApio = function(callback) {
this.executeCommand([coverPath(common.ENV_PIP), 'install', '-U', 'apio">=' + _package.apio.min + ',<' + _package.apio.max + '"'], callback);
var versionRange = '">=' + _package.apio.min + ',<' + _package.apio.max + '"';
var extraPackages = _package.apio.extras || [];
this.executeCommand([coverPath(common.ENV_PIP), 'install', '-U', 'apio[' + extraPackages.toString() + ']' + versionRange], callback);
};

this.apioInstall = function(_package, callback) {
Expand Down
3 changes: 2 additions & 1 deletion gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ module.exports = function(grunt) {
// Project configuration
grunt.initConfig({

pkg: grunt.file.readJSON('package.json'),
pkg: grunt.file.readJSON('app/package.json'),

// Automatically inject Bower components into the app
wiredep: {
Expand Down Expand Up @@ -139,6 +139,7 @@ module.exports = function(grunt) {
apioMin: '<%=pkg.apio.min%>',
apioMax: '<%=pkg.apio.max%>',
buildDir: 'dist/',
extraPackages: '<%=pkg.apio.extras%>',
platforms: platforms
}
},
Expand Down
5 changes: 0 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@
"gettext": "grunt gettext",
"postinstall": "npmpd && cd app && npm install && bower install && cd ../tasks && npm install && cd .. && grunt getcollection"
},
"apio": {
"min": "0.3.0b3",
"max": "0.4.0"
},
"collection": "0.3.0",
"devDependencies": {
"bower": "^1.8.0",
"grunt": "^1.0.1",
Expand Down
60 changes: 31 additions & 29 deletions tasks/toolchain_builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ inherits(ToolchainBuilder, EventEmitter);
module.exports = ToolchainBuilder;
function ToolchainBuilder(options) {
var defaults = {
apioMin: '0.1.9',
apioMax: '1.0.0',
apioMin: '',
apioMax: '',
buildDir: './build',
cacheDir: './cache',
extraPackages: [],
platforms: ['linux32', 'linux64', 'win32', 'win64', 'osx32', 'osx64'],
};

Expand Down Expand Up @@ -57,32 +58,32 @@ ToolchainBuilder.prototype.build = function (callback) {
this.emit('log', this.options.venvPip);
// Let's create the standalone toolchains
this.ensurePythonIsAvailable()
.then(this.extractVirtualenv.bind(this))
.then(this.createVirtualenv.bind(this))
.then(this.downloadApio.bind(this))
.then(this.installApio.bind(this))
.then(this.downloadApioPackages.bind(this))
.then(this.packageApio.bind(this))
.then(this.packageApioPackages.bind(this))
.then(this.createDefaultToolchains.bind(this))
.then(function(info) {
var result = info || this;

if(hasCallback) {
callback(false, result);
} else {
done.resolve(result);
}
})
.catch(function(error) {
if(hasCallback) {
callback(error);
} else {
done.reject(error);
}
});
.then(this.extractVirtualenv.bind(this))
.then(this.createVirtualenv.bind(this))
.then(this.downloadApio.bind(this))
.then(this.installApio.bind(this))
.then(this.downloadApioPackages.bind(this))
.then(this.packageApio.bind(this))
.then(this.packageApioPackages.bind(this))
.then(this.createDefaultToolchains.bind(this))
.then(function(info) {
var result = info || this;

if(hasCallback) {
callback(false, result);
} else {
done.resolve(result);
}
})
.catch(function(error) {
if(hasCallback) {
callback(error);
} else {
done.reject(error);
}
});

return hasCallback ? true : done.promise;
return hasCallback ? true : done.promise;
};

ToolchainBuilder.prototype.ensurePythonIsAvailable = function () {
Expand Down Expand Up @@ -132,9 +133,10 @@ ToolchainBuilder.prototype.downloadApio = function () {
var self = this;
self.emit('log', '> Download apio');
return new Promise(function(resolve, reject) {
var versionRange = '">=' + self.options.apioMin + ',<' + self.options.apioMax + '"';
var command = [
self.options.venvPip, 'download', '--dest', self.options.apioDir,
'apio">=' + self.options.apioMin + ',<' + self.options.apioMax + '"'
'apio[' + self.options.extraPackages.toString() + ']' + versionRange
];
childProcess.exec(command.join(' '),
function(error/*, stdout, stderr*/) {
Expand Down Expand Up @@ -171,7 +173,7 @@ ToolchainBuilder.prototype.downloadApioPackages = function () {
self.emit('log', '> Download apio packages');
return new Promise(function(resolve, reject) {
function command(dest, platform) {
var packages = ['system', 'icestorm', 'iverilog', 'scons', (platform.startsWith('windows') ? 'drivers' : '')];
var packages = ['system', 'icestorm', 'iverilog', (platform.startsWith('windows') ? 'drivers' : '')];
return [ (process.platform === 'win32' ? 'set' : 'export'),
'APIO_HOME_DIR=' + dest + (process.platform === 'win32' ? '&' : ';'),
self.options.venvApio, 'install', '--platform', platform ].concat(packages);
Expand Down