1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-06-20 08:29:30 +00:00

can load verilog module from .asm file

This commit is contained in:
Steven Hugg 2018-03-01 23:15:33 -06:00
parent 725770ea3b
commit c14e470778
5 changed files with 90 additions and 32 deletions

View File

@ -116,7 +116,7 @@ module cpu_platform(clk, reset, hsync, vsync, rgb);
wire [15:0] cpu_bus; wire [15:0] cpu_bus;
assign cpu_bus = cpu_ram_addr[15] assign cpu_bus = cpu_ram_addr[15]
? rom[cpu_ram_addr[9:0]] ? program_rom[cpu_ram_addr[9:0]]
: ram_read; : ram_read;
CPU16 cpu( CPU16 cpu(
@ -129,11 +129,11 @@ module cpu_platform(clk, reset, hsync, vsync, rgb);
.data_out(ram_write), .data_out(ram_write),
.write(ram_writeenable)); .write(ram_writeenable));
reg [15:0] rom[0:1023]; reg [15:0] program_rom[0:1023];
`ifdef EXT_INLINE_ASM `ifdef EXT_INLINE_ASM
initial begin initial begin
rom = '{ program_rom = '{
__asm __asm
.arch femto16 .arch femto16
.org 0x8000 .org 0x8000
@ -160,7 +160,7 @@ InitPTLoop:
rts rts
ClearTiles: ClearTiles:
mov bx,@$6000 mov bx,@$6000
mov cx,@$390 mov cx,@$3c0
ClearLoop: ClearLoop:
mov [bx],ax mov [bx],ax
inc bx inc bx

View File

@ -581,23 +581,40 @@ var VerilogPlatform = function(mainElement, options) {
this.loadROM = function(title, output) { this.loadROM = function(title, output) {
var mod; var mod;
try { if (output.code) {
mod = new Function('base', output.code); try {
} catch (e) { mod = new Function('base', output.code);
this.printErrorCodeContext(e, output.code); } catch (e) {
throw e; this.printErrorCodeContext(e, output.code);
throw e;
}
// compile Verilog code
var base = new VerilatorBase();
gen = new mod(base);
gen.__proto__ = base;
current_output = output;
module_name = output.name ? output.name.substr(1) : "top";
trace_ports = current_output.ports;
trace_signals = current_output.ports.concat(current_output.signals);
trace_index = 0;
// power on module
this.poweron();
} else {
// TODO: :^P
output = {program_rom_variable: title, program_rom: output};
} }
// compile Verilog code // replace program ROM, if using the assembler
var base = new VerilatorBase(); if (output.program_rom && output.program_rom_variable) {
gen = new mod(base); if (gen[output.program_rom_variable]) {
gen.__proto__ = base; if (gen[output.program_rom_variable].length != output.program_rom.length)
current_output = output; alert("ROM size mismatch -- expected " + gen[output.program_rom_variable].length + " got " + output.program_rom.length);
module_name = output.name ? output.name.substr(1) : "top"; else
trace_ports = current_output.ports; gen[output.program_rom_variable] = output.program_rom;
trace_signals = current_output.ports.concat(current_output.signals); } else {
trace_index = 0; alert("No program_rom variable found (" + output.program_rom_variable + ")");
// power on module }
this.poweron(); }
// restart audio
restartAudio(); restartAudio();
} }
@ -661,7 +678,7 @@ var VerilogPlatform = function(mainElement, options) {
} }
this.getToolForFilename = function(fn) { this.getToolForFilename = function(fn) {
if (fn.endsWith("asm")) if (fn.endsWith("asm"))
return "caspr"; return "jsasm";
else else
return "verilator"; return "verilator";
} }

View File

@ -143,6 +143,7 @@ var TOOL_TO_SOURCE_STYLE = {
'sdasz80': 'z80', 'sdasz80': 'z80',
'sdcc': 'text/x-csrc', 'sdcc': 'text/x-csrc',
'verilator': 'verilog', 'verilator': 'verilog',
'jsasm': 'z80'
} }
var worker = new Worker("./src/worker/workermain.js"); var worker = new Worker("./src/worker/workermain.js");
@ -180,7 +181,7 @@ function scrollProfileView(_ed) {
} }
function newEditor(mode) { function newEditor(mode) {
var isAsm = mode=='6502' || mode =='z80' || mode=='verilog'; // TODO var isAsm = mode=='6502' || mode =='z80' || mode=='verilog' || mode=='gas'; // TODO
editor = CodeMirror(document.getElementById('editor'), { editor = CodeMirror(document.getElementById('editor'), {
theme: 'mbo', theme: 'mbo',
lineNumbers: true, lineNumbers: true,
@ -419,13 +420,13 @@ function updateSelector() {
function loadFileDependencies(text) { function loadFileDependencies(text) {
var arr = []; var arr = [];
if (platform_id == 'verilog') { if (platform_id == 'verilog') {
var re = /`include\s+"(.+?)"/g; var re = /^(`include|[.]include)\s+"(.+?)"/gm;
var m; var m;
while (m = re.exec(text)) { while (m = re.exec(text)) {
arr.push({ arr.push({
filename:m[1], filename:m[2],
prefix:platform_id, prefix:platform_id,
text:store.loadFile(m[1]) || store.loadFile('local/'+m[1]) // TODO?? text:store.loadFile(m[2]) || store.loadFile('local/'+m[2]) // TODO??
}); });
} }
} }
@ -524,6 +525,9 @@ function setCompileOutput(data) {
addErrorMarker(0, e+""); addErrorMarker(0, e+"");
current_output = null; current_output = null;
} }
} else if (rom.program_rom_variable) { //TODO: a little wonky...
platform.loadROM(rom.program_rom_variable, rom.program_rom);
rom_changed = true;
} }
if (rom_changed || trace_pending_at_pc) { if (rom_changed || trace_pending_at_pc) {
// update editor annotations // update editor annotations

View File

@ -84,6 +84,9 @@ var Assembler = function(spec) {
warning(msg, line); warning(msg, line);
aborted = true; aborted = true;
} }
function fatalIf(msg, line) {
if (msg) fatal(msg, line);
}
function hex(v, nd) { function hex(v, nd) {
try { try {
if (!nd) nd = 2; if (!nd) nd = 2;
@ -160,7 +163,7 @@ var Assembler = function(spec) {
return {opcode:opcode, nbits:oplen}; return {opcode:opcode, nbits:oplen};
} }
function loadArch(arch) { self.loadArch = function(arch) {
if (self.loadFile) { if (self.loadFile) {
var json = self.loadFile(arch + ".json"); var json = self.loadFile(arch + ".json");
if (json && json.vars && json.rules) { if (json && json.vars && json.rules) {
@ -182,7 +185,11 @@ var Assembler = function(spec) {
else if (tokens[0] == '.width') else if (tokens[0] == '.width')
width = parseInt(tokens[1]); width = parseInt(tokens[1]);
else if (tokens[0] == '.arch') else if (tokens[0] == '.arch')
loadArch(tokens[1]); fatalIf(self.loadArch(tokens[1]));
else if (tokens[0] == '.include')
fatalIf(self.loadInclude(tokens[1]));
else if (tokens[0] == '.module')
fatalIf(self.loadModule(tokens[1]));
else else
warning("Unrecognized directive: " + tokens); warning("Unrecognized directive: " + tokens);
} }
@ -274,7 +281,8 @@ var Assembler = function(spec) {
self.state = function() { self.state = function() {
return {ip:ip, line:linenum, origin:origin, codelen:codelen, return {ip:ip, line:linenum, origin:origin, codelen:codelen,
output:outwords, asmlines:asmlines, errors:errors, fixups:fixups}; intermediate:{}, // TODO: listing, symbols?
output:outwords, lines:asmlines, errors:errors, fixups:fixups};
} }
} }

View File

@ -1065,7 +1065,7 @@ function writeDependencies(depends, FS, errors, callback) {
} }
if (callback) if (callback)
text = callback(d, text); text = callback(d, text);
if (text) if (text && FS)
FS.writeFile(d.filename, text, {encoding:'utf8'}); FS.writeFile(d.filename, text, {encoding:'utf8'});
} }
} }
@ -1118,9 +1118,10 @@ function compileCASPR(code, platform, options) {
} }
} }
function compileASM(asmcode, platform, options) { function compileJSASM(asmcode, platform, options, is_inline) {
load("assembler"); load("assembler");
var asm = new Assembler(); var asm = new Assembler();
var includes = [];
asm.loadFile = function(filename) { asm.loadFile = function(filename) {
// TODO: what if it comes from dependencies? // TODO: what if it comes from dependencies?
var path = '../../presets/' + platform + '/' + filename; var path = '../../presets/' + platform + '/' + filename;
@ -1130,14 +1131,41 @@ function compileASM(asmcode, platform, options) {
xhr.send(null); xhr.send(null);
return xhr.response; return xhr.response;
}; };
asm.loadInclude = function(filename) {
if (!filename.startsWith('"') || !filename.endsWith('"'))
return 'Expected filename in "double quotes"';
filename = filename.substr(1, filename.length-2);
includes.push(filename);
};
var module_top;
var module_output;
asm.loadModule = function(top_module) {
// TODO: cache module
// compile last file in list
module_top = top_module;
var main_filename = includes[includes.length-1];
var code = '`include "' + main_filename + '"\n';
code += "/* module " + top_module + " */\n";
var voutput = compileVerilator(code, platform, options);
if (voutput.errors.length)
return voutput.errors[0].msg;
module_output = voutput;
}
var result = asm.assembleFile(asmcode); var result = asm.assembleFile(asmcode);
if (module_output) {
var asmout = result.output;
result.output = module_output.output;
result.output.program_rom = asmout;
// cpu_platform__DOT__program_rom
result.output.program_rom_variable = module_top + "__DOT__program_rom";
}
return result; return result;
} }
function compileInlineASM(code, platform, options, errors, asmlines) { function compileInlineASM(code, platform, options, errors, asmlines) {
code = code.replace(/__asm\b([\s\S]+?)\b__endasm\b/g, function(s,asmcode,index) { code = code.replace(/__asm\b([\s\S]+?)\b__endasm\b/g, function(s,asmcode,index) {
var firstline = code.substr(0,index).match(/\n/g).length; var firstline = code.substr(0,index).match(/\n/g).length;
var asmout = compileASM(asmcode, platform, options); var asmout = compileJSASM(asmcode, platform, options, true);
if (asmout.errors && asmout.errors.length) { if (asmout.errors && asmout.errors.length) {
for (var i=0; i<asmout.errors.length; i++) { for (var i=0; i<asmout.errors.length; i++) {
asmout.errors[i].line += firstline; asmout.errors[i].line += firstline;
@ -1152,7 +1180,7 @@ function compileInlineASM(code, platform, options, errors, asmlines) {
s += 0|out[i]; s += 0|out[i];
} }
if (asmlines) { if (asmlines) {
var al = asmout.asmlines; var al = asmout.lines;
for (var i=0; i<al.length; i++) { for (var i=0; i<al.length; i++) {
al[i].line += firstline; al[i].line += firstline;
asmlines.push(al[i]); asmlines.push(al[i]);
@ -1263,6 +1291,7 @@ var TOOLS = {
'verilator': compileVerilator, 'verilator': compileVerilator,
'yosys': compileYosys, 'yosys': compileYosys,
'caspr': compileCASPR, 'caspr': compileCASPR,
'jsasm': compileJSASM,
} }
var TOOL_PRELOADFS = { var TOOL_PRELOADFS = {