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

View File

@ -581,23 +581,40 @@ var VerilogPlatform = function(mainElement, options) {
this.loadROM = function(title, output) {
var mod;
try {
mod = new Function('base', output.code);
} catch (e) {
this.printErrorCodeContext(e, output.code);
throw e;
if (output.code) {
try {
mod = new Function('base', output.code);
} catch (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
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();
// replace program ROM, if using the assembler
if (output.program_rom && output.program_rom_variable) {
if (gen[output.program_rom_variable]) {
if (gen[output.program_rom_variable].length != output.program_rom.length)
alert("ROM size mismatch -- expected " + gen[output.program_rom_variable].length + " got " + output.program_rom.length);
else
gen[output.program_rom_variable] = output.program_rom;
} else {
alert("No program_rom variable found (" + output.program_rom_variable + ")");
}
}
// restart audio
restartAudio();
}
@ -661,7 +678,7 @@ var VerilogPlatform = function(mainElement, options) {
}
this.getToolForFilename = function(fn) {
if (fn.endsWith("asm"))
return "caspr";
return "jsasm";
else
return "verilator";
}

View File

@ -143,6 +143,7 @@ var TOOL_TO_SOURCE_STYLE = {
'sdasz80': 'z80',
'sdcc': 'text/x-csrc',
'verilator': 'verilog',
'jsasm': 'z80'
}
var worker = new Worker("./src/worker/workermain.js");
@ -180,7 +181,7 @@ function scrollProfileView(_ed) {
}
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'), {
theme: 'mbo',
lineNumbers: true,
@ -419,13 +420,13 @@ function updateSelector() {
function loadFileDependencies(text) {
var arr = [];
if (platform_id == 'verilog') {
var re = /`include\s+"(.+?)"/g;
var re = /^(`include|[.]include)\s+"(.+?)"/gm;
var m;
while (m = re.exec(text)) {
arr.push({
filename:m[1],
filename:m[2],
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+"");
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) {
// update editor annotations

View File

@ -84,6 +84,9 @@ var Assembler = function(spec) {
warning(msg, line);
aborted = true;
}
function fatalIf(msg, line) {
if (msg) fatal(msg, line);
}
function hex(v, nd) {
try {
if (!nd) nd = 2;
@ -160,7 +163,7 @@ var Assembler = function(spec) {
return {opcode:opcode, nbits:oplen};
}
function loadArch(arch) {
self.loadArch = function(arch) {
if (self.loadFile) {
var json = self.loadFile(arch + ".json");
if (json && json.vars && json.rules) {
@ -182,7 +185,11 @@ var Assembler = function(spec) {
else if (tokens[0] == '.width')
width = parseInt(tokens[1]);
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
warning("Unrecognized directive: " + tokens);
}
@ -274,7 +281,8 @@ var Assembler = function(spec) {
self.state = function() {
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)
text = callback(d, text);
if (text)
if (text && FS)
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");
var asm = new Assembler();
var includes = [];
asm.loadFile = function(filename) {
// TODO: what if it comes from dependencies?
var path = '../../presets/' + platform + '/' + filename;
@ -1130,14 +1131,41 @@ function compileASM(asmcode, platform, options) {
xhr.send(null);
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);
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;
}
function compileInlineASM(code, platform, options, errors, asmlines) {
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 asmout = compileASM(asmcode, platform, options);
var asmout = compileJSASM(asmcode, platform, options, true);
if (asmout.errors && asmout.errors.length) {
for (var i=0; i<asmout.errors.length; i++) {
asmout.errors[i].line += firstline;
@ -1152,7 +1180,7 @@ function compileInlineASM(code, platform, options, errors, asmlines) {
s += 0|out[i];
}
if (asmlines) {
var al = asmout.asmlines;
var al = asmout.lines;
for (var i=0; i<al.length; i++) {
al[i].line += firstline;
asmlines.push(al[i]);
@ -1263,6 +1291,7 @@ var TOOLS = {
'verilator': compileVerilator,
'yosys': compileYosys,
'caspr': compileCASPR,
'jsasm': compileJSASM,
}
var TOOL_PRELOADFS = {