Bluepsec Examples
Thacker's Tiny 3 Computer - Embedded Assembler
Overview
This package contains an embedded assembler for Thacker's Tiny 3 Computer.
The code
/*****************************************************************************
TinyAsm
=======
Simon Moore
August 2011
Assembler for Chuck Thacker's Tiny3 processor embedded by Bluespec
*****************************************************************************/
package TinyAsm;
import List::*;
import FIFO::*;
import GetPut::*;
import ClientServer::*;
import TinyTypes::*;
typedef Tuple2#(String,InstructionT) AsmLineT; // type of a line of assembler
typedef List#(String) LabelTblT; // type of assembler label table
typedef List#(WordT) InstructionROM_T;
/********** functions to create (label,instruction) pairs **********/
function AsmLineT asm(String label, OpcodeT op, FuncT func, ShiftT shift, SkipT skip, RegT rw, RegT ra, RegT rb);
return tuple2(label,tagged Normal{rw:rw, ra:ra, rb:rb, func:func, shift:shift, skip:skip, op:op});
endfunction
function AsmLineT asmi(String label, RegT rw, ImmT imm);
return tuple2(label,tagged Immediate{rw:rw, imm:imm});
endfunction
// returns the position of string "tofind" in "list"
function Maybe#(Integer) find_pos_string (String tofind, List#(String) list);
Maybe#(Integer) rtn = tagged Invalid;
for(Integer j=0; (j<length(list)) && !isValid(rtn); j=j+1)
if(list[j]==tofind)
rtn=tagged Valid fromInteger(j);
return rtn;
endfunction
// returns True if "tofind" is in "list", otherwise False
function Bool find_str(String tofind, List#(String) list)
= isValid(find_pos_string(tofind,list));
function InstructionROM_T assembler(function List#(AsmLineT) program_source(function ImmT findaddr(String label)));
/********** phase 0 of the assembly process **********/
function ImmT no_label(String label) = -1;
List#(AsmLineT) prog_phase_0 = program_source(no_label);
let label_tbl = tpl_1(unzip(prog_phase_0));
/********** phase 1 of the assembly process **********/
function ImmT label_lookup(String label) =
fromInteger(fromMaybe(-1,find_pos_string(label,label_tbl)));
List#(AsmLineT) prog_phase_1 = program_source(label_lookup);
Integer prog_len = length(prog_phase_1);
List#(WordT) rom = map(instruction2word, tpl_2(unzip(prog_phase_1)));
return rom;
endfunction
function Tuple2#(Bool,Fmt) find_duplicate_labels(function List#(AsmLineT) program_source(function ImmT findaddr(String label)));
function Tuple2#(Bool,Fmt) report_duplicates(List#(String) labels);
Fmt msg = $format("");
Bool error = False;
if(labels!=Nil)
begin
if((head(labels)!="") && find_str(head(labels),tail(labels)))
begin
msg = $format("Assembler error: label \"%s\" defined more than once\n",head(labels));
error = True;
end
let rd = report_duplicates(tail(labels));
error = error || tpl_1(rd);
msg = msg + tpl_2(rd);
end
return tuple2(error,msg);
endfunction
function ImmT no_label(String label) = -1;
List#(AsmLineT) labelled_prog = program_source(no_label);
Tuple2#(List#(String), List#(InstructionT)) lab_prog = unzip(labelled_prog);
let labels = tpl_1(lab_prog);
return report_duplicates(labels);
endfunction
function Fmt disassembleROM(InstructionROM_T rom);
Fmt msg = $format("");
for(Integer a=0; a<length(rom); a=a+1)
begin
InstructionT inst = word2instruction(rom[a]);
msg = msg + $format("pm[%2d] : ",a) + fshow(inst) + $format("\n");
end
return msg;
endfunction
// assemble "the_program" (function with list of assembler) and create a ROM
module mkInstructionROM#(function List#(AsmLineT) the_program(function ImmT findaddr(String label)))
(Server#(PCT, InstructionT));
InstructionROM_T rom = assembler(the_program);
FIFO#(InstructionT) out_fifo <- mkLFIFO;
interface Put request;
method Action put(addr);
out_fifo.enq(word2instruction(rom[addr]));
endmethod
endinterface
interface response = toGet(out_fifo);
endmodule
endpackage: TinyAsm
Link to the TinyAsm.bsv source