yosys
yosys copied to clipboard
Please add examples on how to use this module yowasp openfpgaloader
An example of how to use this would be great! Thanks!
I tried this code:
async function loadModule() {
try {
// Dynamically import the module
const module = await import('https://cdn.jsdelivr.net/npm/@yowasp/yosys/gen/bundle.js');
// Once the module is imported, you can use its exports
module.runYosys(["--version"]);
} catch (error) {
console.error('Error loading module:', error);
}
}
// Call the function to load the module
loadModule();
but i get this error from the browser:
Uncaught (in promise) RangeError: WebAssembly.Instance is disallowed on the main thread, if the buffer size is larger than 8MB. Use WebAssembly.instantiate, or use the flag `--enable-features=WebAssemblyUnlimitedSyncCompilation`.
at bundle.js:508:28
at Application.instantiate (bundle.js:4460:28)
at Application.execute (bundle.js:504:30)
at Application.run (bundle.js:534:17)
at bundle.js:531:46
For the time being (until https://github.com/bytecodealliance/jco/issues/375 is fixed) you must use a Web Worker to use @yowasp/yosys.
I've been working on integrating the jco updates but it's been a bit complex to test.
Here's what i did to make it run:
Create index.html:
<!-- Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
These are new security requirements for using SharedArrayBuffer.
You can check in code if cross origin isolation is enabled:
if (crossOriginIsolated) {
// SharedArrayBuffer is available
} -->
<script type="module" src="main.js"></script>
<script type="text/javascript">
</script>
Create main.js:
// Create a new worker from a JavaScript file
const worker = new Worker('worker.js');
// Handle messages sent from the worker
worker.onmessage = function(event) {
console.log('Message from worker:', event.data);
};
// Send a message to the worker
worker.postMessage('Hello from the main thread!');
Create worker.js:
async function loadModule() {
try {
// Dynamically import the module
// const module = await import('https://cdn.jsdelivr.net/npm/@yowasp/yosys/gen/bundle.js');
const module = await import('https://cdn.jsdelivr.net/npm/@yowasp/[email protected]/gen/bundle.js');
// Once the module is imported, you can use its exports
module.runOpenFPGALoader(["--help"]);
// module.runYosys(["--version"]);
// module.runYosys(["-m openFPGALoader"]);
} catch (error) {
console.error('Error loading module:', error);
}
}
// Call the function to load the module
loadModule();
Then serve these files on a webserver: python3 -m http.server
In chrome, install extension CORS Unblock, open a new tab, and enable CORS Unblock option: "Extra Options" -> "Append Headers to Allow Shared Array Buffer"
Access http://localhost:8000
You can see the output in the JS console.
Not sure how i can now use WebUSB and specify the device to OpenFPGALoader.
Hope this helps
OK, i figured it out. Just ignore the bad coding :) The file to be flashed is passed as an argument in filesIn (filename and data) to the module function, and the filename is passed as a normal argument in args.
main.js:
var selectDevice = document.createElement("selectDevice");
// Step 2 (Optional): Set attributes
selectDevice.textContent = "selectDevice"; // Set button text
selectDevice.setAttribute("id", "selectDevice"); // Set button ID
// Step 3: Append the button to an existing DOM element
document.body.appendChild(selectDevice);
// let filters = [];
// filters.push({ 'vendorId': 0x0403 });
// filters.push({ 'serialNumber': serial });
// navigator.usb.requestDevice({ 'filters': filters }).then(
// async selectedDevice => {
// await device.open();
// }
// ).catch(error => {
// statusDisplay.textContent = error;
// }
// );
let filters = [];
// filters.push({ 'vendorId': 0x0403 });
// filters.push({ 'serialNumber': '123456' });
// filters.push({ 'productId': 0x5678 });
// Each filter object can have the following properties:
// vendorId
// productId
// classCode
// subclassCode
// protocolCode
// serialNumber
selectDevice.addEventListener("click", async () => {
// navigator.usb
// .requestDevice({ filters })
// .then((usbDevice) => {
// console.log(`Product name: ${usbDevice.productName}`);
// })
// .catch((e) => {
// console.error(`There is no device. ${e}`);
// });
await navigator.usb.requestDevice({
filters: filters,
});
// const devices = await navigator.usb.getDevices();
// for (const device of devices) {
// console.log("Opening device: " + device);
// await device.open();
// }
});
// Create a new worker from a JavaScript file
const worker = new Worker('worker.js');
// Handle messages sent from the worker
worker.onmessage = function(event) {
console.log('Message from worker:', event.data);
};
// Send a message to the worker
worker.postMessage('Hello from the main thread!');
worker.js:
async function loadModule() {
try {
// Dynamically import the module
// const module = await import('https://cdn.jsdelivr.net/npm/@yowasp/yosys/gen/bundle.js');
const module = await import('https://cdn.jsdelivr.net/npm/@yowasp/[email protected]/gen/bundle.js');
console.log("Listing USB devices");
const devices = await navigator.usb.getDevices();
for (const device of devices) {
console.log("Device: %o", device);
// try {
// await device.open();
// } catch (error) {
// console.log("ERROR:", error);
// }
}
// console.log("runOpenFPGALoader: %o", module.runOpenFPGALoader);
// module.runOpenFPGALoader(["--help"]);
// Once the module is imported, you can use its exports
// console.log("OpenFPGALoader Scanning USB devices");
// module.runOpenFPGALoader(["--scan-usb"]);
const fileUrl = 'next_kms.fs';
var fileContent;
await fetch(fileUrl)
.then(response => {
// Check if the request was successful
if (!response.ok) {
throw new Error('Network response was not ok');
}
// Read the response body as ArrayBuffer (binary data)
return response.arrayBuffer();
})
.then(arrayBuffer => {
// Create a Uint8Array from the ArrayBuffer
const uint8Array = new Uint8Array(arrayBuffer);
fileContent = uint8Array;
// Do something with the Uint8Array, for example, log its length
console.log('Length of Uint8Array:', uint8Array.length);
// You can perform any processing with the Uint8Array here
})
.catch(error => {
console.error('There was a problem fetching the file:', error);
});
var filesData = { "data.fs": fileContent };
// console.log("filesData: %o",filesData);
const moduleArgs = ["-b", "tangnano9k", "-v", "-f", "data.fs"];
console.log("OpenFPGALoader Flashing");
module.runOpenFPGALoader(moduleArgs, filesData);
// module.runYosys(["--version"]);
// module.runYosys(["-m openFPGALoader"]);
} catch (error) {
console.error('Error loading module:', error);
}
}
// Call the function to load the module
loadModule();
You can check working example at https://ramalhais.github.io/openfpgaloader-webflash/
Hm, I feel like there should be a way to do it without SAB.
For the time being (until bytecodealliance/jco#375 is fixed) you must use a Web Worker to use
@yowasp/yosys.
Good news: I've tested the changes there so you should be able to use @yowasp/yosys without a Worker soon.
@yowasp/yosys version 0.43.36-dev.746 can now be used on the main thread in Chrome.