Records and Channels

This example illustrates how ldb can be used to display channels with a structured type such as a record or vector in a helpful fashion.

The example program implements some simple instruction decoding, converting a stream of instructions (integers) into a stream of decoded instructions (records). Here is the code:

	use(channels).
	
	decoder_delay:expr(int)=10.
	execute_delay:expr(int)=10.
	prefetch_cycle:expr(int)=10.
	
	instr_type : type = int.
	
	opcode_type : type = scalar.
	op_add : val(opcode_type).
	op_sub : val(opcode_type).
	op_mul : val(opcode_type).
	op_div : val(opcode_type).
	
	regnum_type : type = int.
	
	dec_instr_type : type = record ( opcode :: opcode_type,
	                                 reg1 :: regnum_type,
	                                 reg2 :: regnum_type ).
	
	decode(i:val(instr_type)):expr(dec_instr_type)=(
	  di:var(dec_instr_type).
	
	  di->opcode := ( case ((i and 16#300)>>8)
	                    when 0 => op_mul
	                    when 1 => op_add
	                    when 2 => op_div
	                    when 3 => op_sub );
	  di->reg1 := cast(regnum_type,(i and 16#0F0)>>4);
	  di->reg2 := cast(regnum_type,i and 16#00F);
	  di
	).
	
	
	decoder_block(i:var(chan(instr_type)),
	              o:var(chan(dec_instr_type))):expr(void)=(
	  forever(
	    i?(
	      wait_for(decoder_delay);
	      o!decode(?i)
	    )
	  )
	).
	
	
	source_block(o:var(chan(instr_type))):expr(void)=(
	  forever(
	    o!(cast(instr_type,rand(16#400))) |
	    wait_for(prefetch_cycle)
	  )
	).
	
	
	sink_block(i:var(chan(dec_instr_type))):expr(void)=(
	  forever(
	    i?(
	      wait_for(execute_delay)
	    )
	  )
	).
	
	
	I:var(chan(instr_type)).
	DI:var(chan(dec_instr_type)).
	
	init_chan(I,"Instructions");
	init_chan(DI,"Decoded instructions");
	
	(
	  source_block(I) |
	  decoder_block(I,DI) |
	  sink_block(DI)
	)
With Show Data enabled for the channels by default the display is like this:

Here the values are shown in decimal. For the decoded instruction the three fields are shown separated by spaces.

By choosing Format from the pop-up menus we can display dialog boxes that allow us to change the representation of this information.

There is one box for each field of the channel's type. (If the type is a record with fields that are themselves records or vectors these are flattened to give one box per field in the combined entity). The strings in the entries are sprintf format strings - see the sprintf man page or a C textbook for details. So for example if we want to display the undecoded instruction as a 3 digit hex number zero extended we could enter %03X in its format entry. For correct alignment fields should include a leading space, including the first.

Note: it is a good idea to stop the simulation while changing the format strings. If you don't and a new value arrives while the string has a transitory illegal value everything will die horribly.

Alternatively you can use the width, base and extension menus near the top of the window to set a format, and then press the Set buttons to apply this format to appropriate fields.

For the decoded instruction we may only be interested in the opcode, in which case setting its format to %d and the two register numbers to empty strings would be appropriate. With these settings the output is as follows:

Note: at the moment there is no way to show a symbolic value for the opcode. This may come later.

To show the decoded instruction in more detail we can add field names and line breaks by setting its format dialog as follows:

Note that to get line breaks you should press Return at the end of the format entry. This will show as \n. Don't type \n, this will come out as \n. Multi-line formats are only really usefull when Show Blobs is used; with Show Data the data box makes the timing information invisible:

It is possible to save the channel format information by choosing Session->Save Configuration in the main window. This dialog box gives a list of aspects of the current configuration to save. By default the configuration is saved in a file with the name of the bcode file and extention .lirc, which means that it will be read automatically when li is next started.