Computer Laboratory

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