From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/latex/contrib/register/README | 52 ++ macros/latex/contrib/register/Reg_macro.pm | 498 ++++++++++ macros/latex/contrib/register/reg_list.pl | 329 +++++++ macros/latex/contrib/register/register.dtx | 1376 ++++++++++++++++++++++++++++ macros/latex/contrib/register/register.ins | 62 ++ macros/latex/contrib/register/register.pdf | Bin 0 -> 178459 bytes 6 files changed, 2317 insertions(+) create mode 100644 macros/latex/contrib/register/README create mode 100644 macros/latex/contrib/register/Reg_macro.pm create mode 100644 macros/latex/contrib/register/reg_list.pl create mode 100644 macros/latex/contrib/register/register.dtx create mode 100644 macros/latex/contrib/register/register.ins create mode 100644 macros/latex/contrib/register/register.pdf (limited to 'macros/latex/contrib/register') diff --git a/macros/latex/contrib/register/README b/macros/latex/contrib/register/README new file mode 100644 index 0000000000..f250c7dbc2 --- /dev/null +++ b/macros/latex/contrib/register/README @@ -0,0 +1,52 @@ + +REGISTER +Hardware register diagrams with field descriptions. + + +Description +----------- + +This package is designed for typesetting the programmable elements in +digital hardware, i.e., registers. Such registers typically have many +fields and can be quite wide; they are thus a challenge to typeset in +a consistent manner. Register is similar in some aspects to the +bytefield package. Anyone doing hardware documentation using LaTeX +should examine both packages. Register requires version 2001/07/25 or +newer of the float package. + +An example Perl module and script are provided, to convert the +register specifications into structures suitable for, say, a +pre-silicon test environment. + + +Building package +---------------- + +tex register.ins <== Produces register.sty (the package proper) +latex register.dtx <== Produces register.dvi (the documentation) +latex register.dtx <== Incorporates list of registers into + register.dvi + +One can substitute pdflatex in the commands above to produce PDF +directly. + +Note that register comes with pre-built documentation. The +documentation includes some representative examples of package usage. + + + +Copyright and license +--------------------- + +Copyright (C) 2001-2018 Matthew Lovell, lovells@gmail.com + +This package may be distributed and/or modified under the conditions +of the LaTeX Project Public License, either version 1.3 of this +license or (at your option) any later version. The latest version of +this license is in: + + http://www.latex-project.org/lppl.txt + +and version 1.3c or later is part of all distributions of LaTeX +version 2006/05/20 or later. + diff --git a/macros/latex/contrib/register/Reg_macro.pm b/macros/latex/contrib/register/Reg_macro.pm new file mode 100644 index 0000000000..5c00bc805e --- /dev/null +++ b/macros/latex/contrib/register/Reg_macro.pm @@ -0,0 +1,498 @@ +############################################################################### +# +# File: Reg_macro.pm +# Description: Module for parsing register macros from LaTeX documentation +# Author: Matthew Lovell +# Created: Mon Mar 31 16:50:05 2003 +# Modified: Sat May 19 09:33:20 2018 +# Language: CPerl +# +# (C) Copyright 2003, Matthew Lovell, all rights reserved. +# +############################################################################### + +=pod + +=head1 NAME + +Reg_macro.pm + +=head1 SYNOPSIS + +Parses register/CSR information from LaTeX files. + +=head1 DESCRIPTION + +After searching through a files input/include tree, this module will search +for all \begin{register} macros. All available information will be parsed +out of each encountered macro. Parsed information includes: + + register name + function + offset + field names, positions, and widths + register reset value + register reset mask + register write mask + +The parsed information can either be used either to produce in-order +tables for inclusion in documentation or to provide CSR information to +Phase 1 tools (metacheckers, CSR checkers, etc). + +=head1 PUBLIC ROUTINES + + get_tex_files() Recursively follow a file's input/include/import tree + + get_regs() Parse CSR information from a single specified file + + build_reg_hash() Build a multi-level hash, keyed by function and + offset, from the specified register information + +=head1 SEE ALSO + +Any project-specific LaTeX introductory material. + + +=head1 AUTHOR + +Matthew Lovell (lovells@gmail.com) + +=cut + +############################################################################### + +package Reg_macro; +use Exporter; +@ISA = qw(Exporter); +@EXPORT = qw(get_tex_files + get_regs + build_reg_hash + $REG_DEBUG + $REG_STRIDE + $REG_ERRORS + ); + +use FileHandle; +use Data::Dumper; + +# Debug flag +$REG_DEBUG = 0; + +# How large are registers? Default is 64-bits. +$REG_STRIDE = hex(0x08); + +# Error count +$REG_ERRORS = 0; + +############################################################################### +# P U B L I C R O U T I N E S # +############################################################################### + + + + +# Read a .tex file line by line, finding all \include or \input +# commands. Recurse upon encountering one of those, thus making +# a list of the entire TeX file tree. +# +# This subroutine can also be called with an option indicating that +# all \includegraphics targets should be parsed. With that option, +# this routine can extract all dependencies for a LaTeX file, which +# is useful for GNU make. +# +# Arguments: filename +# flag indicating all dependencies should be tracked +# +sub get_tex_files { + my ($filename, $all_files) = @_; + + # return immediately for some file types + if ($filename =~ /\.(eps|pdf|ps|func|error)$/) { + print "#INFO Reg_macro Not attempting to read '$filename'\n" if ($REG_DEBUG); + return $filename; + } + + my $path = dirname($filename); + + # Add .tex if not present + if ($filename !~ /\.\w+$/) { + $filename .= '.tex'; + } + + # initialize file list + my @file_list = ($filename); + + my $file = new FileHandle "$filename"; + unless (defined $file) { + print STDERR "#ERROR Reg_macro Unable to open '$filename'\n"; + $REG_ERRORS++; + return @file_list; + } + + # Allow files to turn off dependency extraction in particular sections, + # when desired. This may be useful if a preamble needs to input a file + # from the texmf tree, for example. + my $dependency_skip = 0; + + while (<$file>) { + + $dependency_skip = 1 if (m/^%% DEPEND OFF/); + $dependency_skip = 0 if (m/^%% DEPEND ON/); + next if $dependency_skip; + + # Skip over comments. + s/^%.*$//; # Remove whole comment lines + s/([^\\])%.*$/$1/; # Remove everything after unescaped %'s + + + # Get all include and input commands + my @list = m/\\(?:include|input)\{([\w\/.-]+)\}/g; + if ($path ne '' and $path ne '.') { + @list = map { $path . "/" . $_ } @list; + } + + # Find any import commands + if (m|\\import\{([\w\/.-]+)}\{([\w\/.-]+)\}|) { + push(@list,$1.$2); + } + + # Find ALL files for make dependencies + if ($all_files) { + + # Graphics files + if (m|\\includegraphics(?:\[.*?\])?\{([\w\/.-]+)\}|) { + + # Add .eps if not present + my $gfx_file = $1; + if ($gfx_file !~ /\.\w+$/) { + $gfx_file .= '.eps'; + } + + if ($path ne '' and $path ne '.') { + $gfx_file = $path . "/" . $gfx_file; + } + + push(@list,$gfx_file); + } + + + # project-specific: + # + # CSR files (just look for the \CSRtable invocation) + if (m|\\CSRtable|) { + my $func_file; + ($func_file = $filename) =~ s/\.tex$/.func/; + push(@list, $func_file); + } + + + } # end all_files + + my $subfile; + for $subfile (@list) { + push(@file_list, get_tex_files($subfile, $all_files)); + } + } + + return @file_list; +} # get_tex_files + + + + +# Read a .tex file line by line, looking for register declarations +# using the register.sty macro. This subroutine only examines +# a single file. +# +# Arguments: filename +# reference to array of register information +# +sub get_regs { + my ($filename, $reg_data) = @_; + + my $file = new FileHandle "$filename"; + + # Record the function in which a register resides. Allow this to + # be defined for just the first register in a file, then carried + # over to all the others. + my $function = 0; + + while (<$file>) { + # find register definition + if ( m/\\begin\{register\}\{[\w\!]+\}\{(.*)\}\{(.*)\}%(.*)$/ ) { + my $long_name = $1; + my $offset = $2; + my $testable = 1; + my $short_name = undef; + + my $remainder = $3; + + if ($remainder ne "") { + if ($remainder =~ /don\'?t(_| )test/i) { $testable = 0 } + if ($remainder =~ /NAME=([\w\\<>\d]+)/i) { $short_name = $1 } + if ($remainder =~ /func=(\d)/i) { $function = $1 } + if ($remainder =~ /off(?:set)?=([\w-,g]+)/) { $offset = $1 } + } + + # get rid of escaped underscores + $long_name =~ s/\\_/_/g; + $short_name =~ s/\\_/_/g; + + my $width = 0; + my $reg = { + long_name => $long_name, + short_name => $short_name, + function => $function, + offset => $offset, + testable => $testable, + fields => [] + }; + + + # now we need to extract fields. first, + # read in rest of the reg macro + @wholereg = (); + while (<$file>) { + push(@wholereg, $_); + last if (/\\end\{register\}/); + } + + + # combine lines if nested {}'s do not match + for (my $i = 0; $i <= $#wholereg; $i++) { + my $open = grep(/\{/, split(//, $wholereg[$i])); + my $close = grep(/\}/, split(//, $wholereg[$i])); + + if ($open != $close) { + my ($next) = splice(@wholereg, $i+1, 1); + $wholereg[$i] .= $next; + redo; + } + } + + foreach (@wholereg) { + + if (m/\\label\{(.*)\}/) { + $reg->{label} = $1; + } + + # normal register field (reset value specified) + if ( m/\\regfield\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*%(.*)$/s ) { + my $remain = $5; + my $field_name = $1; + my $field_len = $2; + my $field_start = $3; + my $reset = $4; $reset =~ s/^\{//; $reset =~ s/\}$//; $reset =~ s/_//g; + my $reset_mask = $testable; # indicates field is deterministic after reset + my $write_mask = $testable; # indicates field is modified by regbus writes + + + if ($field_name =~ m/\{([\w ])\}$/) { + $field_name = $1; + } + $field_name =~ s/\\_/_/g; + + + if ($remain =~ /read(?:_| )only/i) { $write_mask = 0; } + if ($remain =~ /status/i) { $reset_mask = 0; $write_mask = 0; } + if ($field_name =~ /reserved/i) { $write_mask = 0; } + + + if ($field_len > 32) { + die "#ERROR Reg_macro Field of greater than 32 bits in $short_name!\n"; + } + + push(@{$reg->{fields}}, + { + name => $field_name, + len => $field_len, + start => $field_start, + reset => $reset, + reset_mask => $reset_mask, + write_mask => $write_mask + }); + } + + + # register field without reset + if ( m/\\regfieldb\{(.*)\}\s*\{(.*)\}\s*\{(.*)\}\s*%(.*)$/s ) { + my $remain = $4; + my $field_name = $1; + my $field_len = $2; + my $field_start = $3; + my $reset_mask = $testable; # indicates field is deterministic after reset + my $write_mask = $testable; # indicates field is modified by regbus writes + + + if ($field_name =~ m/\{([\w ])\}$/) { + $field_name = $1; + } + $field_name =~ s/\\_/_/g; + + if ($remain =~ /read(?:_| )only/i) { $write_mask = 0; } + if ($remain =~ /status/i) { $reset_mask = 0; $write_mask = 0; } + if ($field_name =~ /reserved/i) { $write_mask = 0; } + + if ($field_len > 32) { + die "#ERROR Reg_macro Field of greater than 32 bits in $short_name!\n"; + } + + push(@{$reg->{fields}}, + { + name => $field_name, + len => $field_len, + start => $field_start, + reset_mask => $reset_mask, + write_mask => $write_mask + }); + } + + + } # end of register macro found + + print Dumper $reg if ($REG_DEBUG); + push(@$reg_data, $reg); + + } + } + +} # get_regs + + + +# Build a hash of registers, keyed on function and offset. That is, +# given parsed register information, construct a hash with the +# following structure +# +# $reg_hash { function } { offset } +# +# This will enable loops that iterate through registers in offset order +# +# Arguments: reference to array of reg information from get_regs +# Returns: reference to constructed hash +# +sub build_reg_hash { + my ($reg_array) = @_; + my $reg_hash = {}; + + my $unknown_count = 0; + + # iterate through all defined registers + foreach my $reg (@$reg_array) { + + if ($reg->{offset} =~ m/^(0x[0-9A-F]+)$/i) { + # simple offset specified + my $offset = $1; + + if (exists $reg_hash->{$reg->{function}}{$offset}) { + print STDERR "##ERROR Reg_macro A Collision at offset $offset of function $reg->{function} \n"; + print STDERR " Existing register: " . $reg_hash->{$reg->{function}}{$offset}{long_name} . "\n"; + print STDERR " New register: " . $reg->{long_name} . "\n"; + print STDERR "#END\n"; + $REG_ERRORS++; + } + + $reg_hash->{$reg->{function}}{$offset} = $reg; + + } elsif ($reg->{offset} =~ m/^(0x[0-9A-F]+)\s*-+\s*(0x[0-9A-F]+)/i) { + + # range specified. + my $start = hex($1); + my $end = hex($2); + + # determine stride + my $stride = $REG_STRIDE; + if ($reg->{offset} =~ m/,((?:0x)?[0-9A-F]+)/) { + $stride = hex($1); + } + + my $count = 0; + for (my $index = $start; $index <= $end; $index += $stride) { + + my $offset = sprintf("0x%03x",$index); + + if (exists $reg_hash->{$reg->{function}}{$offset}) { + print STDERR "##ERROR Reg_macro Collision at offset $offset of function $reg->{function} \n"; + print STDERR " Existing register: " . $reg_hash->{$reg->{function}}{$offset}{long_name} . "\n"; + print STDERR " New register: " . $reg->{long_name} . "\n"; + print STDERR "#END\n"; + $REG_ERRORS++; + } + + # perform any substitutions in long_name + my $reg_copy = { %{$reg} }; + if ($reg_copy->{long_name} =~ m//) { + $reg_copy->{long_name} =~ s//$count/; + } else { + $reg_copy->{long_name} .= " $count"; + } + + # perform any substitutions in short_name + if ($reg_copy->{short_name} =~ m//) { + $reg_copy->{short_name} =~ s//$count/; + } else { + $reg_copy->{short_name} .= "$count"; + } + + $reg_hash->{$reg->{function}}{$offset} = $reg_copy; + $count++; + } + + } else { + # unknown offset + $reg_hash->{$reg->{function}}{"unk".$unknown_count++} = $reg; + print STDERR "#WARNING Reg_macro Register '$reg->{long_name}' has an unknown offset \n"; + } + + } # end foreach + + return $reg_hash; +} # build_reg_hash + + + +# Convert an ASCII string representing a binary number to a true decimal number +sub bin2dec { + return unpack("N", pack("B32", substr("0" x 32 . shift, -32))); +} + +# Convert a true number to a binary ASCII string +sub dec2bin { + my $str = unpack("B32", pack("N", shift)); + return $str; +} + +# Covert an ASCII string representing a hex number to a binary ASCII string; +sub hex2bin { + return unpack("B32", pack("N", hex(shift))); +} + +# Convert an ASCII string representing a binary number to a hex ASCII string; +sub bin2hex { + + my $Bin = shift(@_); + my $Hex; + + # Clean up string and look for errors + chomp $Bin; + + if ($Bin =~ m/[^10]/) { + print STDERR "#ERROR Reg_macro $Bin is not binary\n"; + return (""); + } + return scalar reverse unpack "h*",(pack "b*", scalar reverse $Bin); +} + + + +# required by Perl +1; + +## Local Variables: +## mode: perl +## End: + + + + + diff --git a/macros/latex/contrib/register/reg_list.pl b/macros/latex/contrib/register/reg_list.pl new file mode 100644 index 0000000000..16c40cb554 --- /dev/null +++ b/macros/latex/contrib/register/reg_list.pl @@ -0,0 +1,329 @@ +#!/usr/bin/env perl +############################################################################### +# +# File: reg_list.pl +# RCS: $Header: /doc_tools/register/reg_list.pl 1.2 2004/08/16 23:37:07 lovell Exp $ +# Description: Output a table (per function) of CSR's in offset order +# Author: Matthew Lovell +# Created: Mon Mar 31 16:50:05 2003 +# Modified: Mon Aug 16 17:36:19 2004 +# Language: CPerl +# +# (C) Copyright 2003, Matthew Lovell, all rights reserved. +# +############################################################################### + +use lib("$ENV{WJ_HOME}/docs/common", + "$ENV{WJ_HOME}/docs/common"); + +use Getopt::Long; +use FileHandle; +use Reg_macro; + + +# Parameters controlling execution +my $params = + { + file => "", # LaTeX file to parse + list => 0, # just list files + table => 0, # produce table files + Make => 0, # dependency extraction + }; + + +$DEBUG = 0; + +############################################################################### +# M A I N # +############################################################################### + +# read options and get files from command-line +get_input_opts($params); +$REG_DEBUG = 1 if ($DEBUG); + +my @files = get_tex_files($params->{file}, $params->{Make}); + +if ($DEBUG or $params->{list}) { + print "\nFile tree\n"; + print "----------------------------\n"; + print join("\n",@files) . "\n\n"; + exit if ($params->{list}); +} + + +# +# Just output Makefile dependencies and exit +# +if ($params->{Make}) { + print_depends_list($params->{file}, + @files); + exit(0); +} + + +# +# ...otherwise, go on to extract some register information +# + +my @reg_data = (); + +for (@files) { + get_regs($_,\@reg_data) +} + +my $reg_hash = build_reg_hash(\@reg_data); + +if (!$params->{table}) { + print_reg_list($reg_hash); +} else { + make_reg_files($params->{file}, $reg_hash); +} + + +exit($REG_ERRORS); + +############################################################################### +# S U B R O U T I N E S # +############################################################################### + + +# Print out file dependencies in a format suitable for use by +# GNU make. Makefile rules should be setup to update this +# information as necessary. +# +# Arguments: .tex filename +# array of dependencies +# +sub print_depends_list { + my ($file, @depends) = @_; + + my @setup_files = qw[preamble.sty]; + + # separate all .error files + my @error_files = grep { $_ =~ /\.error$/ } @depends; + + # separate all .func files + my @func_files = grep { $_ =~ /\.func$/ } @depends; + + # ensure output is on STDOUT + select STDOUT; + + my $aux_file, $dvi_file, $d_file, $ps_file; + ($aux_file = $file) =~ s/\.tex$/.aux/; + ($dvi_file = $file) =~ s/\.tex$/.dvi/; + ($ps_file = $file) =~ s/\.tex$/.ps/; + ($d_file = $file) =~ s/\.tex$/.d/; + + + print "#\n"; + print "# Generated dependency file. Do NOT check into HMS !!\n"; + print "#\n\n"; + + # Print out dependency list for the .aux file itself + print "$aux_file $dvi_file : \\\n"; + map { print "\t$_ \\\n" } @setup_files; + map { print "\t$_ \\\n" } @error_files; + map { print "\t$_ \\\n" } @func_files; + + foreach my $file (@depends) { + next if ($file =~ m/\.(?:error|func)$/); + next if ($file =~ m/logo\.eps/); + print "\t$file \\\n"; + } + print "\n"; + + + # Repeat for the .d file, leaving out unneeded files + print "$d_file : \\\n"; + + foreach my $file (@depends) { + next if ($file =~ m/\.(?:error|func)$/); + next if ($file =~ m/\.eps$/); + print "\t$file \\\n"; + } + print "\n\n"; + + +} # print_depends_list + + + +# Print out register names in offset order to STDOUT. Used to +# ensure script is acting correctly. +# +# Arguments: reference to hash constructed by build_reg_hash +# +sub print_reg_list { + my ($reg_hash) = @_; + + my @functions = keys %$reg_hash; + + print "\n"; + for my $func (sort @functions) { + + print "Function $func Registers\n"; + print "-" x 80 . "\n"; + + for my $offset (sort { hex($a) <=> hex($b) } keys %{$reg_hash->{$func}}) { + my $output = ""; + if ($offset =~ /^unk/) { + $output = sprintf(" ? %-50s %-20s", + $reg_hash->{$func}{$offset}{long_name}, + $reg_hash->{$func}{$offset}{short_name} + ); + } else { + $output = sprintf("%03x %-50s %-20s", + hex($offset), + $reg_hash->{$func}{$offset}{long_name}, + $reg_hash->{$func}{$offset}{short_name} + ); + } + + print "$output\n"; + } + + print "\n\n"; + } + +} # print_reg_list + + + +# Output a LaTeX longtable listing registers in each function. +# +# Arguments: name of latex file parsed, used as the root for +# the table files names +# +# reference to hash created by build_reg_hash +# +sub make_reg_files { + my ($orig_file, $reg_hash) = @_; + + my @functions = keys %$reg_hash; + for my $func (sort @functions) { + + my $filename = $orig_file =~ s/\.tex$//; + $filename = $orig_file . ".func$func"; + + my $file = new FileHandle ">$filename"; + if (!defined $file) { + print STDERR "#ERROR reg_list.pl Unable to open $filename for writing!"; + die; + } + + for my $offset (sort { hex($a) <=> hex($b) } keys %{$reg_hash->{$func}}) { + + my $name = $reg_hash->{$func}{$offset}{long_name}; + if (defined $reg_hash->{$func}{$offset}{short_name}) { + $name .= " ($reg_hash->{$func}{$offset}{short_name})"; + } + + my $pageref = ""; + if (exists $reg_hash->{$func}{$offset}{label}) { + $pageref = '\pageref{' . $reg_hash->{$func}{$offset}{label} . '}'; + } + + if ($offset =~ /^unk/) { + printf $file "\\texttt{?} & %s & %s \\\\\n", + $name, $pageref; + } else { + printf $file "\\texttt{0x%03x} & %s & %s \\\\\n", + hex($offset), $name, $pageref; + } + + } + + close $file; + + } + + +} # make_reg_files + + +# Retrieve the input parms passed to this script and set the proper +# options. Some global variables may be set by this subroutine. +# +# Arguments: reference to parameters hash +# +sub get_input_opts { + my ($params) = @_; + my $help = 0; + + # Setup for GetOptions + $Getopt::Long::autoabbrev = 1; + $Getopt::Long::ignorecase = 0; + $Getopt::Long::order = $PERMUTE; + + my @optl = (); + push(@optl, + "help", \$help, # show usage information + "debug", \$DEBUG, # show debug information + "file=s", \$params->{file}, # LaTeX file to parse + + "list", \$params->{list}, + "table", \$params->{table}, + "Make", \$params->{Make}, + ); + + GetOptions(@optl); + + if ($help) { + print_usage_and_die(); + } + + if ($params->{file} eq "") { + print "Must specify a LaTeX file. Use --help for usage info.\n"; + exit(1); + } + + + return; +} # get_input_opts + + +sub print_usage_and_die { + $usage = <<"@@USAGE_INFO"; +Register (CSR) Lister + +This script parses all register/CSR diagrams found in a LaTeX document. +The document can include or import sub-documents; the script will follow +the tree. + +By default, a human-readable list of registers, ordered by offset +within each function, is printed to STDOUT. If the -table option is +given, files are written with a similar table formatted for inclusion +in a LaTeX document. The filenames will have the same root as the +file specified on the command-line, but with an extension of + + .func + +for each non-empty function encountered during parsing. + +Usage: + + reg_list.pl -file <.tex file> + ( [-table] | [-list] | [-Make] ) + [-debug] [-help] + + + <.tex file> LaTeX file to parse + + Mutually exclusive + ------------------ + -table Produce LaTeX table output, no STDOUT output + -list Show the file tree of <.tex file>, then quit + -Make Produce makefile dependencies for specified LaTeX file + + + Other options + ------------- + -debug Show parsing debug information + -help Print this stuff + + +@@USAGE_INFO + + print $usage; + exit(1); +} # print_usage_and_die diff --git a/macros/latex/contrib/register/register.dtx b/macros/latex/contrib/register/register.dtx new file mode 100644 index 0000000000..2c2b41cf6d --- /dev/null +++ b/macros/latex/contrib/register/register.dtx @@ -0,0 +1,1376 @@ +% \iffalse +% +% register.dtx +% Register diagrams with field descriptions +% +% Author: Matthew Lovell (lovells@gmail.com) +% Copyright 2001-2019 by Matthew B. Lovell +% +% Run LaTeX on the file `register.ins' to get a .sty-file and +% then on `register.dtx' to obtain instructions. +% +% This program is provided under the terms of the +% LaTeX Project Public License distributed from CTAN +% archives in directory macros/latex/base/lppl.txt. +% +% This program consists of register.dtx, register.ins, +% reg_reset.pl, and reg_table.pl. +% +%<*dtx> +\ProvidesFile{register.dtx} +% +% \fi +% \CheckSum{785} +% +% \def\fileversion{v1.9} +% \def\filedate{2019/01/01} +% \title{Register diagrams with field descriptions} +% \author{Matthew Lovell\\ +% \texttt{lovells@gmail.com} +% } +% \date{\filedate} +% \maketitle +% +% \providecommand{\LyX}{L\kern-.1667em\lower.25em\hbox{Y}\kern-.125emX\@} +% +% \begin{abstract} +% The |register| package is designed for typesetting +% the programmable elements in digital hardware, i.e., registers. +% Such registers typically have many fields and can be quite wide; +% they are thus a challenge to typeset in a consistent manner. +% This package attempts to address such issues. It is similar +% in some aspects to the |bitfield| package by Reuben Thomas and the +% |bytefield| package by Scott Pakin. +% \end{abstract} +% +% \StopEventually +% +% \iffalse +%<*driver> +\documentclass{ltxdoc} +\RequirePackage{textcomp} +\RequirePackage[TRflags,TRboxed,color]{register} +\RequirePackage{amsmath} +\RequirePackage{amssymb} +\setlength{\regWidth}{0.98\textwidth} +\setlength{\TRwidth}{40pt} +\RecordChanges +\begin{document} + \DocInput{register.dtx} +% \PrintChanges +\end{document} +% +% \fi +% +% \listofregisters +% +% +% \section{Introduction} \label{sec:background} +% +% My group at work designed the memory and I/O controllers for servers +% and workstations. Historically, our chip documentation was done +% with FrameMaker or Microsoft Word. While these approaches have +% various disadvantages, one of the most egregious was register +% documentation. +% +% The recent chips have 64-bit wide control-status registers (CSR) +% or, more simply, registers. Add the fact that many of these +% registers have a large number of single-bit fields, and you get a +% typesetting challenge. The typical solution was to describe such +% registers using a table, typing field names vertically if space +% became a problem. For a complicated register, these tables became +% quite complex and filled a large portion of a page. +% +% When we decided to evaluate \LaTeX{} for documentation, we had three +% goals in mind with respect to registers: +% \begin{enumerate} +% \item Create a method of documenting registers which was consistent +% and easy to read, regardless of the number of fields within a +% register. +% \item Automate the creation of lists of registers, both in order +% of appearance within the text and in memory address order. +% \item Enable the automatic extraction of documented register reset +% values in order to verify register functionality in the chip +% itself. +% \end{enumerate} +% The |register| package is my attempt at meeting all three goals. It +% was first put into use in April 1999; it may be not be +% pretty to all eyes, but it certainly has proven itself stable. +% +% In order to promote \LaTeX{} within our group at the time, we also +% adopted \LyX{}. The |register| package thus attempts to work well +% within that environment. All \LyX{}-specific code, however, is +% controlled via package options. +% +% \subsection{Feedback} +% +% As |register| is my first \LaTeX{} package, I would welcome +% feedback regarding problems, new features, or more proper means of +% implementing existing features. For example, is there an +% ``official'' method for determining the current font's maximum +% height and depth (see Section~\ref{sec:reg_fields} for details)? I +% would also appreciate knowing whether anyone ever actually uses it. +% +% It might also be worthwhile to investigate combining |register| with +% |bitfield| or |bytefield|. +% +% \section{Examples} + +% Register~\ref{Diagnostic Control} depicts a register with many +% single-bit fields. Registers such as this stress any scheme of +% typesetting, since the field names are so much longer than the space +% available for them within the diagram. By typesetting the field +% names at an angle, |register| manages to be consistent regardless of +% the number or width of fields. This rotation, however, means that +% documents which use |register| must be produced using PostScript. +% +% \begin{register}{H}{Diagnostic Control}{0x1F28}^^A NAME=DIAG_CTRL1 +% \label{Diagnostic Control}^^A +% \regfield{reserved}{1}{63}{0}^^A +% \regfield{cmp\_ack64}{1}{62}{0}^^A +% \regfield{cmp\_req64}{1}{61}{0}^^A +% \regfield{cmp\_devsel}{1}{60}{0}^^A +% \regfield{cmp\_stop}{1}{59}{0}^^A +% \regfield{cmp\_trdy}{1}{58}{0}^^A +% \regfield{cmp\_irdy}{1}{57}{0}^^A +% \regfield{cmp\_frame}{1}{56}{0}^^A +% \regfield{reserved}{1}{55}{0}^^A +% \regfield{mask\_ack64}{1}{54}{0}^^A +% \regfield{mask\_req64}{1}{53}{0}^^A +% \regfield{mask\_devsel}{1}{52}{0}^^A +% \regfield{mask\_stop}{1}{51}{0}^^A +% \regfield{mask\_trdy}{1}{50}{0}^^A +% \regfield{mask\_irdy}{1}{49}{0}^^A +% \regfield{mask\_frame}{1}{48}{0}^^A +% \regfield{cmp\_cbe}{8}{40}{0}^^A +% \regfield{mask\_cbe}{8}{32}{0}^^A +% \reglabel{Reset}^^A +% \regnewline^^A +% \regfield{reserved}{1}{31}{0}^^A +% \regfield{cmp\_arb}{7}{24}{0}^^A +% \regfield{reserved}{1}{23}{0}^^A +% \regfield{mask\_arb}{7}{16}{0}^^A +% \regfield{reserved}{5}{11}{0}^^A +% \regfield{grp\_en\_cntl}{1}{10}{0}^^A +% \regfield{grp\_en\_cbe}{1}{9}{0}^^A +% \regfield{grp\_en\_arb}{1}{8}{0}^^A +% \regfield{grp\_en\_fifo}{1}{7}{0}^^A +% \regfield{dly\_frame}{1}{6}{0}^^A +% \regfield{level\_frame}{1}{5}{0}^^A +% \regfield{level\_cntl}{1}{4}{0}^^A +% \regfield{level\_cbe}{1}{3}{0}^^A +% \regfield{level\_arb}{1}{2}{0}^^A +% \regfield{hlt\_trg\_on\_1}{1}{1}{0}^^A +% \regfield{alwys\_cnt\_1}{1}{0}{0}^^A +% \reglabel{Reset}^^A +% \regnewline^^A +% \end{register} +% +% Register~\ref{Function Class} is an example of a register one could +% derive from the PCI specification. It is a miscellaneous register +% in a PCI card which controls device independent functions. Note the +% field descriptions which, in this case, are actually part of the +% float. +% +% \begin{register}{htbp}{Function Class}{0x0008}^^A NAME=FC +% \label{Function Class}^^A +% \regfield{BIST}{8}{56}{0}^^A READ_ONLY +% \regfield{Header Type}{8}{48}{0}^^A READ_ONLY +% \regfield{Latency Timer}{8}{40}{0}^^A +% \regfield{Line Size}{8}{32}{0}^^A +% \reglabel{Reset}^^A +% \regnewline^^A +% \regfield{Class Code}{24}{8}{{0x060000}}^^A READ_ONLY +% \regfield{Revision}{8}{0}{{0x10}}^^A READ_ONLY +% \reglabel{Reset}^^A +% \regnewline^^A +% \begin{regdesc}^^A +% +% \begin{reglist}[Latency Timer] +% \item [BIST](Read only) Always returns 0. +% \item [Header~Type](Read only) Always returns 0. +% \item [Latency~Timer]PCI Latency Timer value (PCI 2.2 spec, Section 6.2.4). +% \item [Line~Size]PCI Cache Line Size (PCI 2.2 spec, Section 6.2.4). Valid +% values are listed below; any other value will be treated as indicating +% 64 byte cache lines. +% \begin{description} +% \item [0010\_0000]128 bytes +% \item [0001\_0000]64 bytes +% \end{description} +% \item [Class~Code](Read only) PCI Class Code (PCI 2.2 spec, Section 6.2.1). +% Chip identifies itself as a Host bridge. +% \item [Revision](Read only) Chip revision number. Bits 4--7 provide the major +% revision number, and bits 0--3 provide the minor +% revision number. +% \end{reglist} +% \end{regdesc} +% \end{register} +% +% A final example is shown in Figure~\ref{fig:regbus_cycle}. This +% example shows that the register drawing macros don't have to be used +% solely within a |register| float or environment. With Version~1.8, +% an unnumbered register environment is also available, using +% |register*|. Diagrams produced using the starred environment +% typeset just the register name, omitting the ``Register'' and number +% prefix. +% +% \begin{figure}[H] +% \begin{center}^^A +% \regfieldb{write\_en}{1}{15}^^A +% \regfieldb{reserved}{2}{13}^^A +% \regfieldb{function}{1}{12}^^A +% \regfieldb{block}{4}{8}^^A +% \regfieldb{register}{5}{3}^^A +% \regfieldb{reserved}{3}{0}^^A +% \reglabelb{Address phase} \\ +% \regfieldb{reserved}{8}{8}^^A +% \regfieldb{BE}{8}{0}^^A +% \reglabelb{BE phase}^^A +% \end{center}^^A +% \caption{Address and BE phases for register access}\label{fig:regbus_cycle} +% \end{figure} +% +% +% \section{User Interface} \label{sec:user} +% +% The user interface for register diagrams could be regarded as +% overly verbose. The main idea behind the parameters was to allow +% \LaTeX{} \emph{and} accompanying Perl scripts to decipher register +% fields and reset values. The simplest way to show the interface +% is via another example. Below is a 64-bit register. +% \begin{register}{H}{Example}{0x250}^^A name=example +% \label{example}^^A +% \regfield{FIFO depth}{6}{58}{{random}}^^A +% \regfield{Something}{4}{54}{1100}^^A +% \regfield{Status}{21}{33}{{uninitialized}}^^A +% \regfield{Enable}{1}{32}{1}^^A +% \reglabel{Reset}\regnewline^^A +% \regfield{Counter}{10}{22}{{0x244}}^^A READ_ONLY +% \regfield{Howdy}{5}{17}{1_1010}^^A +% \regfield{Control}{1}{16}{-}^^A +% \regfield{Hardfail}{1}{15}{1}^^A +% \regfield{Data}{15}{0}{{uninitialized}}^^A +% \reglabel{Reset}\regnewline^^A +% \end{register} +% +% It was created with the following commands: +% +% \begin{verbatim} +% \begin{register}{H}{Example}{0x250}% name=example +% \label{example}% +% \regfield{FIFO depth}{6}{58}{{random}}% +% \regfield{Something}{4}{54}{1100}% +% \regfield{Status}{21}{33}{{uninitialized}}% +% \regfield{Enable}{1}{32}{1}% +% \reglabel{Reset}\regnewline% +% \regfield{Counter}{10}{22}{{0x244}}% READ_ONLY +% \regfield{Howdy}{5}{17}{1_1010}% +% \regfield{Control}{1}{16}{-}% +% \regfield{Hardfail}{1}{15}{1}% +% \regfield{Data}{15}{0}{{uninitialized}}% +% \reglabel{Reset}%\regnewline% +% \end{register} +% \end{verbatim} +% +% \begin{macro}{register} +% \begin{macro}{\listofregisters} +% The register environment begins with |\begin{register}|. The three +% parameters to the environment are the float specification (|h|, |H|, +% |t|, |b|, or |p|); the register name; and the register's offset in +% memory space. These parameters become the register caption as well +% as the entry in the list of registers, which is typeset using +% |\listofregisters|. +% \end{macro} +% \end{macro} +% \hspace*{\MacroIndent}|\begin{register}{|\meta{placement}|}{|^^A +% \meta{register name}|}{|\meta{register offset}|}| +% +% \begin{macro}{\regfield} +% Each register field is then typeset using |\regfield|. The fields +% must be specified\footnote{Provided you're a little-endian person!} +% starting with the most-significant bit. The |\regfield| macro takes +% four parameters: field name, field length (in bits), starting bit +% number, and reset value. The reset value, unless you pass it as a +% single token (see example), will be spread apart to fill up the +% width of the field. The reset value, since it could be just a +% very long binary number, can be interrupted with underscores to +% improve readability. +% \end{macro} +% \hspace*{\MacroIndent}|\regfield{|\meta{name}|}{|\meta{length}|}{|^^A +% \meta{start bit}|}{|\meta{reset value}|}|\\[2pt] +% +% Note that the comments that are shown in the code are for the +% benefit of the helper scripts that accompany the |register| +% package. Those scripts are quite old and have \emph{not} been +% updated to be tolerant of the optional color argument that is now +% supported. However, the general notion of using embedded comments +% to augment register or field information is still applicable, if +% one is using this package with the intent of generating HDL code +% from documentation. +% +% \begin{macro}{\regBitWidth} +% \begin{macro}{\regnewline} +% \begin{macro}{\reglabel} +% The macro |\regBitWidth| specifies the maximum number of bits to be +% typeset on a single line. Once a line has been completed, a new line +% can be inserted via |\regnewline|. Before starting a new line, +% however, an appropriate label for the reset value should be typed. +% This label is generated via |\reglabel|, which takes the string to +% typeset as a single parameter. The package, via the macro +% |\regResetName|, assumes that |Reset| will be used in order to set +% some lengths appropriately; it really only matters for very full +% lines. In a future version, it may be possible to make +% |\regResetName| be the default parameter to |\reglabel|. +% \end{macro} +% \end{macro} +% \end{macro} +% \hspace*{\MacroIndent}|\reglabel{|\meta{reset label}|}|\\[2pt] +% +% +% As another example, consider Register~\ref{Configuration} below, which has +% field descriptions as part of the float. This diagram was created +% with the following code: +% \begin{verbatim} +% \begin{register}{htbp}{Configuration}{0x2848}% name=CONFIG +% \label{Configuration}% +% \regfield{soft reset perf}{1}{63}{0}% STATUS +% \regfield{reserved}{30}{33}{0}% +% \regfield{Test mode}{1}{32}{0}% +% \reglabel{Reset}\regnewline% +% \regfield{reserved}{13}{19}{0}% +% \regfield{\parbox[b]{0pt}{Request Depth}}{7}{12}{1}% +% \regfield{reserved}{3}{9}{0}% +% \regfield{line\_2x\_L}{1}{8}{?}% STATUS +% \regfield{reserved}{1}{7}{0}% +% \regfield{ill\_cmd\_enable}{1}{6}{0}% +% \regfield{LPCE}{1}{5}{0}% +% \regfield{DVI disable}{1}{4}{0}% +% \regfield{SBA enable}{1}{3}{0}% +% \regfield{reserved}{2}{1}{0}% +% \regfield{line\_2x\_enable}{1}{0}{0}% READ_ONLY +% \reglabel{Reset}\regnewline% +% \begin{regdesc}\begin{reglist}[Request~Depth] +% \item [line\_2x\_enable]Setting this bit enables the chip +% to utilize a second connected data line. +% \item [SBA~enable]Setting this bit activates the sideband-address port. +% The SBA port is only useable in a double-line configuration. +% \item [DVI~disable]Setting this bit \emph{turns off} DVI extraction for +% DMA requests. +% \item [LPCE]Line Parity Check Enable. +% \item [ill\_cmd\_enable]\TR{3}Illegal Command enable. +% This bit is new for TR3. +% \item [line\_2x\_L](Read only) Indicates whether this chip is connected +% to a second data line. When this bit is 0, a second line +% is available. +% \item [Request~Depth]Controls number of outstanding DMA requests. +% \item [Test~mode]Activates data line test mode. +% \item [soft~reset~perf]\TR{4}Indicates that a soft reset has been +% performed. This bit is new for TR4. +% \end{reglist}\end{regdesc}\end{register} +% \end{verbatim} +% +% +% \begin{register}{htbp}{Configuration}{0x2848}^^A NAME=CONFIG +% \label{Configuration}^^A +% \regfield{soft reset perf}{1}{63}{0}^^A STATUS +% \regfield{reserved}{30}{33}{0}^^A +% \regfield{Test mode}{1}{32}{0}^^A +% \reglabel{Reset}\regnewline^^A +% \regfield{reserved}{13}{19}{0}^^A +% \regfield{\parbox[b]{0pt}{Request Depth}}{7}{12}{1}^^A +% \regfield{reserved}{3}{9}{0}^^A +% \regfield{line\_2x\_L}{1}{8}{?}^^A STATUS +% \regfield{reserved}{1}{7}{0}^^A +% \regfield{ill\_cmd\_enable}{1}{6}{0}^^A +% \regfield{PCE}{1}{5}{0}^^A +% \regfield{DVI disable}{1}{4}{0}^^A +% \regfield{SBA enable}{1}{3}{0}^^A +% \regfield{reserved}{2}{1}{0}^^A +% \regfield{line\_2x\_enable}{1}{0}{0}^^A READ_ONLY +% \reglabel{Reset}\regnewline^^A +% +% \begin{regdesc}\begin{reglist}[Request~Depth] +% \item [line\_2x\_enable]Setting this bit enables this chip to utilize a second +% connected data line. +% \item [SBA~enable]Setting this bit activates the sideband-address port. +% The SBA port is only useable in a double-line configuration. +% \item [DVI~disable]Setting this bit \emph{turns off} DVI extraction for +% DMA requests. +% \item [LPCE]Line Parity Check Enable. +% \item [ill\_cmd\_enable]\TR{3}Illegal OCMD enable. +% This bit is new for TR3. +% \item [line\_2x\_L](Read only) Indicates whether this chip is connected +% to a second data line. When this bit is 0, a second line is available. +% \item [Request~Depth]Controls number of outstanding DMA requests. +% \item [Test~mode]Activates data line test mode. +% \item [soft~reset~perf]\TR{4}Indicates that a soft reset has been +% performed. This bit is new for TR4. +% \end{reglist}\end{regdesc}\end{register} +% +% \begin{macro}{regdesc} +% \begin{macro}{reglist} +% \begin{macro}{lyxlist} + +% This example uses the |regdesc| environment, which can either be +% part of a register float or used standalone. The purpose of +% |regdesc| is really just to turn on centering and, when the |LyX| +% package option is specified, redefine the |lyxlist| environment. If +% one is using \LyX{}, then register field descriptions can be entered +% using its List type. If one is typing \LaTeX{} directly, just use +% the |reglist| list definition. +% \end{macro} +% \end{macro} +% \end{macro} +% +% The |regdesc| and |reglist| environments both take optional +% arguments. For |regdesc|, the optional argument specifies how wide +% the register description body should be. The default value is 90\% +% of |\textwidth|. For |reglist|, the optional argument is the +% longest field name, which allows the list to be spaced appropriately +% (like examples given in \emph{The \LaTeX{} Companion}). +% +% \begin{macro}{\regfieldb} +% Finally, if a register with no reset values is desired, one can use +% the |\regfieldb| macro. It takes the same first three arguments as +% |\regfield|. Figure~\ref{fig:regbus_cycle} was produced using |\regfieldb|. +% \end{macro} +% +% +% +% \subsection{TR Flags} +% +% \begin{macro}{\TR} +% The previous example also shows the TR flags. These marginal notes can +% be used to denote features that are specific to a particular release +% of a chip. These macros were created since \LaTeX{}'s |\marginpar| +% is itself a float; as such it cannot be nested inside other floats. +% The |\TR| macros thus implement something very similar to the +% solution for Problem~14.28 in \emph{The \TeX{}book}. + +% TR flags are turned on via the |TRflags| package option. If the +% option is not specified, then the |\TR| macro still exists but is +% empty. The TR flags are placed inside an |\fbox| if the |TRboxed| +% package option is specified. +% +% For two-sided documents, the TR flags are placed in the outer +% margins. The placement decision is made by placing labels for each +% TR flag and then determining even/odd page numbering in a subsequent +% \LaTeX{} run. +% \end{macro} +% +% \subsection{Background Colors} \label{sec:colors} +% +% With Version 1.7, this package also supports an optional |color| package option. If that option +% is present, then |xcolor| is loaded and the |\regfield| and |\regfieldb| macros support an +% optional first argument that is used as fill color for the boxes drawn by |\framebox|. Internally, +% |\colorbox| is used to provide this functionality. +% +% Repeating our example from earlier, but with some fill colors specified: +% \begin{verbatim} +% \begin{register}{H}{Color Example}{0x250}% name=example +% \label{colexample}% +% \regfield{FIFO depth}{6}{58}{{random}}% +% \regfield[green!30]{Something}{4}{54}{1100}% +% \regfield[gray!20]{Status}{21}{33}{{uninitialized}}% +% \regfield{Enable}{1}{32}{1}% +% \reglabel{Reset}\regnewline% +% \regfield{Counter}{10}{22}{{0x244}}% READ_ONLY +% \regfield[red!20]{Howdy}{5}{17}{1_1010}% +% \regfield{Control}{1}{16}{-}% +% \regfield[yellow!50]{Hardfail}{1}{15}{1}% +% \regfield[gray!20]{Data}{15}{0}{{uninitialized}}% +% \reglabel{Reset}%\regnewline% +% \end{register} +% \end{verbatim} +% now yields the following: +% \begin{register}{H}{Color Example}{0x250}^^A name=example +% \label{colexample}^^A +% \regfield{FIFO depth}{6}{58}{{random}}^^A +% \regfield[green!30]{Something}{4}{54}{1100}^^A +% \regfield[gray!20]{Status}{21}{33}{{uninitialized}}^^A +% \regfield{Enable}{1}{32}{1}^^A +% \reglabel{Reset}\regnewline^^A +% \regfield{Counter}{10}{22}{{0x244}}^^A READ_ONLY +% \regfield[red!20]{Howdy}{5}{17}{1_1010}^^A +% \regfield{Control}{1}{16}{-}^^A +% \regfield[yellow!50]{Hardfail}{1}{15}{1}^^A +% \regfield[gray!20]{Data}{15}{0}{{uninitialized}}^^A +% \reglabel{Reset}%\regnewline^^A +% \end{register} +% +% \section{Helper Scripts} \label{sec:scripts} +% +% A (now old) Perl module and a Perl script are included as part of the +% |register| package. The module augments the package by +% providing the ability to parse the register macro information into +% Perl. This information consists of the parameters used within +% the macros themselves, as well as the comments which follow. If +% you examine the last register example, you will notice that some +% fields specify |READ\_ONLY| or |STATUS| in a comment. The +% ``directives'' can be used to indicate that particular fields are +% unaffected by writes or unaffected by reset, respectively. +% +% The script, |reg_list.pl|, utilizes the Perl module to produce lists +% of registers in offset-order or to generate reset value and mask +% information for each register. The later data can be used in +% simulation to ensure that registers behave as documented. +% +% Users are cautioned that the Perl script, since it is no longer in +% active use by the author, has not been modified to support the +% optional color argument for the |regfield| macro. +% +% \section{Version History} \label{sec:history} +% +% \begin{itemize} +% \item [\textbf{v0.1}] (1999/03/29) First release +% \item [\textbf{v0.2}] (2000/01/29) Added regdesc environment, for use under LyX +% \item [\textbf{v0.21}] (2000/03/12) Fixed minute problem shown in regs with lots of 1-bit fields +% \item [\textbf{v0.3}] (2000/06/19) Added reglabelb macro, for setting label without a drop +% \item [\textbf{v0.31}] (2000/07/11) Modified names of lengths used within macros +% \item [\textbf{v0.32}] (2000/08/02) Modified regdesc env to use regdescsep for vertical separation +% \item [\textbf{v0.4}] (2001/08/11) Added macros for marginal Tape Release flags +% \item [\textbf{v0.5}] (2001/08/12) Added package options for handling LyX, hyperref, and TR flags +% \item [\textbf{v0.6}] (2001/08/19) Moved chapter redefinition into package; improved TR flags +% \item [\textbf{v1.0}] (2001/09/06) Created .dtx documentation; first public release +% \item [\textbf{v1.01}] (2003/01/17) Removed automatic label in register diagrams +% \item [\textbf{v1.1}] (2003/02/15) Changed length manipulation to work with parskip package +% \item [\textbf{v1.2}] (2003/03/31) Removed requirement to specify register offset +% \item [\textbf{v1.3}] (2003/11/24) Changed how center is handled within register environment +% \item [\textbf{v1.4}] (2004/08/16) Now provide a boolean set only in register context +% \item [\textbf{v1.5}] (2007/03/08) Corrected use of conditionals used in spreading register reset value +% \item [\textbf{v1.6}] (2011/01/11) Mainmatter correction suggested by Kjetil Oftedal +% \item [\textbf{v1.6.1}] (2018/05/19) Published with updated email address; no functional changes +% \item [\textbf{v1.7}] (2018/08/18) Added color option to package, suggested by Marco Stolba +% \item [\textbf{v1.8}] (2018/11/10) Added unnumbered |register*| environment, suggested and written by Stephan Bauroth +% \item [\textbf{v1.9}] (2019/01/01) Switched to a re-definable macro to provide default float name and LoR name, suggested by Benyuan Liu. +% \end{itemize} +% +% +% ^^A ------------------------------------------------------------------------- +% \newpage +% +% \section{Implementation} \label{sec:docstrip} +% +% \subsection{Identification \& Options} \label{sec:id} +% +% The |register| document class can only be used with \LaTeXe, so we make +% sure that an appropriate message is displayed when another \TeX{} +% format is used. +% \begin{macrocode} +%<*package>\NeedsTeXFormat{LaTeX2e} +% \end{macrocode} +% +% Announce the name and unconditionally load most of the required packages: +% \begin{macrocode} +\ProvidesPackage{register} [2019/01/01 v1.9 Register macros with +hyperref/LyX support] + +\RequirePackage{ifthen}[1997/11/02] +\RequirePackage{graphicx}[1997/06/09] +\RequirePackage{float}[2001/07/25] +\RequirePackage{calc}[1998/06/07] +% \end{macrocode} +% +% Declare the package options and some booleans. There are options indicating +% whether |register| is being used with \LyX{} or |hyperref|. The marginal +% TR flags can also be turned on or off with an option. +% \begin{macrocode} +\DeclareOption{LyX}{\setboolean{RegisterLyX}{true}} +\DeclareOption{hyperref}{\setboolean{RegisterHyperref}{true}} +\DeclareOption{TRflags}{\setboolean{RegisterTRFlags}{true}} +\DeclareOption{TRboxed}{\setboolean{RegisterTRBoxed}{true}} +\DeclareOption{color}{\setboolean{RegisterColors}{true}} + +\DeclareOption*{% Emit a warning for other options + \PackageWarning{register}{Unknown option '\CurrentOption'}% +} + +\newboolean{RegisterLyX} +\newboolean{RegisterHyperref} +\newboolean{RegisterTRFlags} +\newboolean{RegisterTRBoxed} +\newboolean{RegisterColors} + +\setboolean{RegisterLyX}{false} +\setboolean{RegisterHyperref}{false} +\setboolean{RegisterTRFlags}{false} +\setboolean{RegisterTRBoxed}{false} +\setboolean{RegisterColors}{false} + +\ProcessOptions\relax % Process package options +% \end{macrocode} +% +% +% If the |color| package option has been specified, go ahead and +% load the |xcolor| package as well. +% \begin{macrocode} +\ifthenelse{\boolean{RegisterColors}}{\RequirePackage{xcolor}[2007/01/21]}{} +% \end{macrocode} +% +% Next, provide a flag indicating when one is inside a register +% context. Some users may wish to define macros, for example, +% which make use of |\marginpar|. Those cannot be used inside +% of a floating register. So, this flag is provided to +% provide something to test against. +% \begin{macrocode} +\newboolean{RegisterContext} +\setboolean{RegisterContext}{false} +% \end{macrocode} +% +% \begin{macro}{\regFloatName} +% \begin{macro}{\regListName} +% \begin{macro}{\regResetName} +% Below are some macros that support a little internationalization, expanded +% upon a suggestion from Benyuan Liu. +% The |\regFloatName| provides the default string used to label each register diagram. +% The string with which to label reset values is |\regResetName|. +% The font size for field names and for the |\regResetName| is controlled by |\regLabelSize|, defined further below. +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +\newcommand{\regFloatName}{Register} +\newcommand{\regListName}{List of Registers} +\newcommand{\regResetName}{Reset} +% \end{macrocode} + + +% \subsection{Float Declaration \& Lengths} \label{sec:float} +% +% Declare the new register float type and the lengths which the +% macros will use. The register diagrams tend to look best with +% the caption at the top of the float. If |\chapter| is defined in +% the current document class, then the register diagrams will count +% by chapter, otherwise they will count by section. +% +% \begin{macrocode} +\floatstyle{plaintop} \@ifundefined{chapter} +{\newfloat{Regfloat}{tbp}{rdf}[section]} +{\newfloat{Regfloat}{tbp}{rdf}[chapter]} +\floatname{Regfloat}{\regFloatName} +% \end{macrocode} +% +% \subsection{Style Parameters} \label{sec:style} +% +% \begin{macro}{\regWidth} +% \begin{macro}{\regBitWidth} +% The |\regWidth| length controls how physically wide the register +% diagrams are, while |\regBitWidth| specifies how the maximum +% number of bits per line in the diagram. The default value +% for |\regWidth| is 95\% of the width of the main text body. +% \end{macro} +% \end{macro} +% +% \begin{macro}{\regBitSize} +% \begin{macro}{\regBitFamily} +% \begin{macro}{\regResetSize} +% \begin{macro}{\regLabelSize} +% \begin{macro}{\regLabelFamily} +% \begin{macro}{\regDescFamily} +% The |\regBitSize| command controls the font size +% used for bit values, |\regResetSize| controls the font size used +% for reset values, and |\regBitFamily| controls which font family +% is used to denote bit positions. +% Finally, |\regDescFamily| controls the appearance of field names +% within register descriptions. +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +\newlength{\regWidth} +\newlength{\regFieldLen} +\newlength{\regLabelAdjust} +\newlength{\regResetHeight} +\newlength{\regResetDepth} +\newlength{\regResetDrop} +\newlength{\regDescSkip} +\newlength{\regRsvdHeight} +\newlength{\regRsvdDrop} +\newlength{\regFboxSep} +\setlength{\regWidth}{0.95\textwidth} +\newcommand{\regBitWidth}{32} +\newcommand{\regBitSize}{\tiny} +\newcommand{\regBitFamily}{\sffamily} +\newcommand{\regResetSize}{\scriptsize} +\newcommand{\regLabelSize}{\footnotesize} +\newcommand{\regLabelFamily}{\rmfamily} +\newcommand{\regDescFamily}{\bf} +% \end{macrocode} +% The lengths below control the vertical spacing between a +% register diagrams and the register field descriptions. This +% distance must change when the |\regdesc| is part of the |\Regfloat| +% or standalone. +% \begin{macrocode} +\newlength{\regdescsep} +\newlength{\oldregdescsep} +\setlength{\regdescsep}{-\medskipamount} + +\newsavebox{\Label} +\newsavebox{\RotatedLabel} +\newcounter{upperbit} +\newcounter{lowerbit} +% \end{macrocode} +% +% \subsection{Register macros} \label{sec:regdesc} +% +% \begin{macro}{\reglist} +% Define a new environment for register field descriptions, +% beneath a register diagram. These descriptions can indicate what +% a particular field is used for, whether it is read-only, etc. The +% field descriptions themselves are in a |\reglist| list environment, +% unless \LyX{} is being used. +% \end{macro} +% \begin{macrocode} +\newenvironment{reglist}[1][M] + {\begin{list}{} + {\settowidth{\labelwidth}{\regDescFamily #1} + \addtolength{\labelwidth}{\labelsep} + \setlength{\leftmargin}{\labelwidth} + \addtolength{\leftmargin}{\labelsep} + \addtolength{\leftmargin}{0.5\regDescSkip} + \addtolength{\rightmargin}{0.5\regDescSkip} + \setlength{\topsep}{0pt} + \setlength{\itemsep}{0pt} + \setlength{\parsep}{0.5\baselineskip} + \renewcommand{\makelabel}[1]{\regDescFamily ##1 \hfill}}} + {\end{list}} +% \end{macrocode} +% +% +% \begin{macro}{\regdesc} +% Next is the |\regdesc| environment. If \LyX{} is being used, +% the environment temporarily redefines the |lyxlist| environment, which +% is what \LyX{} provides as the default list structure. Otherwise, +% the user is left to use |\reglist|. The redefinition should look very +% similar to that for |\reglist|. +% +% In all cases, |\regdesc| starts by attempting to place a small +% amount of vertical space between it and the presumed register +% diagram immediately above it. +% \end{macro} +% \begin{macrocode} +\newenvironment{regdesc}[1][0.90\textwidth]% +% --------------------------------------------- +{% + \setlength{\regDescSkip}{\textwidth - #1}% + \vspace{\regdescsep}% +\ifthenelse{\boolean{RegisterLyX}}{% + \renewenvironment{lyxlist}[1] + {\begin{list}{} + {\settowidth{\labelwidth}{\regDescFamily ##1} + \addtolength{\labelwidth}{\labelsep} + \setlength{\leftmargin}{\labelwidth} + \addtolength{\leftmargin}{\labelsep} + \addtolength{\leftmargin}{0.5\regDescSkip} + \addtolength{\rightmargin}{0.5\regDescSkip} + \setlength{\topsep}{0pt} + %\setlength{\partopsep}{0pt} + \renewcommand{\makelabel}[1]{\regDescFamily ####1 \hfill}}} + {\end{list}}}{}% + % endif + % set spacing appropriately + \leftskip 0.5\regDescSkip% + \rightskip 0.5\regDescSkip% + \parfillskip=\z@ plus 1fil% + \parskip=0.5\baselineskip \advance\parskip by 0pt plus 2pt% +}% end begin{regdesc} +% -------------------------------------------- +{\vskip\baselineskip} +% \end{macrocode} +% +% \begin{macro}{\regnewline} +% This command allows a register diagram to be broken into multiple lines +% \end{macro} +% \begin{macrocode} +\newcommand{\regnewline}{\\*} +% \end{macrocode} +% +% +% \begin{macro}{\register} +% This environment declares the floating environment in which a +% register diagram and, optionally, its field descriptions can be +% typeset. It takes as arguments the float type (h, t, p, H); the +% register name; and the register offset/address. +% \end{macro} +% \begin{macrocode} +\newenvironment{register}[3] +{\begin{Regfloat}[#1]% + \setlength{\leftskip}{0pt}% + \setlength{\oldregdescsep}{\regdescsep}% + \setlength{\regdescsep}{0.5\baselineskip}% + \setlength{\partopsep}{0pt}% + \setlength{\topsep}{0pt}% + \setboolean{RegisterContext}{true}% + \ifthenelse{\equal{#3}{}}% + {\caption[#2]{\textsc{#2}}}% else + {\caption[#2]{\textsc{#2} ({#3})}}% + \centering} +{% restore lengths + \leftskip\z@% + \rightskip\z@% + \parfillskip=\z@ plus 1fil% + \setlength{\regdescsep}{\oldregdescsep}% + \setboolean{RegisterContext}{false}% + \end{Regfloat}} +% \end{macrocode} +% +% \begin{macro}{\register*} +% This register* environment provides for an unnumbered or ``captionless'' register; +% registers in such an environment are not added to the list of registers. +% \end{macro} +% \begin{macrocode} +\newenvironment{register*}[3] +{\begin{Regfloat}[#1]% + \setlength{\leftskip}{0pt}% + \setlength{\oldregdescsep}{\regdescsep}% + \setlength{\regdescsep}{0.5\baselineskip}% + \setlength{\partopsep}{0pt}% + \setlength{\topsep}{0pt}% + \setboolean{RegisterContext}{true}% + \ifthenelse{\equal{#3}{}}% + {\centering\textsc{#2}\\}% else + {\centering\textsc{#2} ({#3})\\}% + \centering} +{% restore lengths + \leftskip\z@% + \rightskip\z@% + \parfillskip=\z@ plus 1fil% + \setlength{\regdescsep}{\oldregdescsep}% + \setboolean{RegisterContext}{false}% + \end{Regfloat}} +% \end{macrocode} +% +% +% \begin{macro}{\regUnderScore} +% \begin{macro}{\regFiller} +% \begin{macro}{\regSpread} +% The next definitions provide a method of spreading out +% an argument, i.e., placing |\hfill|'s between each character. +% They can be used to space the reset value of a register field +% appropriately. Previous versions of these macros used \TeX{}'s +% conditionals incorrectly. +% +% If you are using the |underscore| package, you should +% \emph{repeat} the definition of |\regUnderScore|, after loading +% |underscore| in order to observe the changes made by that package. +% The spreading macros below strive to strip out underscores. +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macrocode} +\def\regUnderScore{_}% +\def\regFiller#1{\def\regInner{#1}% +\ifx\regInner\regUnderScore% +\else% +\ifnum\count0>0% +\hfill#1% +\else#1\fi% +\fi% +\advance\count0 by 1% +} +\def\regSpread#1{\count0=0{}\regSpreadaux#1\empty} +\def\regSpreadaux#1#2\empty{\def\aux{#1}%\show#1% +\ifx\aux\empty% +\else% +\def\aux{#2}% +\regFiller{#1}% +\ifx\aux\empty% +\else% +\regSpreadaux#2\empty% +\fi\fi} +% \end{macrocode} +% +% +% \subsubsection{Register fields} \label{sec:reg_fields} +% +% Define some internal utility macros which get called repeatedly. +% These macros figure out some of the dimensions of the current font +% (is there a better way to do this?), construct and rotate label +% boxes, and typeset bit positions. +% \begin{macrocode} +\newcommand{\setRegLengths}{% + % Compute basic width of a single bit + \settowidth{\regFieldLen}{\regLabelSize \regResetName}% + \setlength{\regFieldLen}{\regWidth - \regFieldLen}% + \setlength{\regFieldLen}{\regFieldLen / \regBitWidth}% + % Figure out height and depth of reset field in current font + % Is there a more ``official'' method to do this? + \settodepth{\regResetDepth}{\regResetSize ()jgpq}% + \settoheight{\regResetHeight}{\regResetSize ()ABCjkl}% + \addtolength{\regResetHeight}{\regResetDepth}% + % Compute how far to drop the reset fields down. The value at + % the end is effectively the separation between the bit position + % box and the reset value box. + \setlength{\regResetDrop}{\regResetHeight + 2\fboxsep - 2\fboxrule + 3pt}% + % New lengths to support colorbox use, when fboxsep gets set to 0 + \setlength{\regRsvdDrop}{\regResetDrop + \fboxsep}% + \setlength{\regRsvdHeight}{\regResetHeight + 2\fboxsep}% + \setlength{\regFboxSep}{\fboxsep}% +} +% \end{macrocode} +% These macros assembly, rotate, and typset the register field name. +% It is the use of |\rotatebox| below which makes |register| require +% PostScript processing. +% \begin{macrocode} +\newcommand{\regMakeFieldName}[1]{% + % Create box to hold label + \savebox{\Label}{\regLabelSize\regLabelFamily #1}% +} +\newcommand{\regRotateFieldName}{% + \savebox{\RotatedLabel}{\rotatebox[origin=lB]{45}{\usebox{\Label}}}% + \makebox[0pt][l]{\raisebox{\regResetHeight + \fboxsep + \depth + 1pt}% + {\hspace{\regLabelAdjust}\usebox{\RotatedLabel}}}% +} +% \end{macrocode} +% The |\typesetRegBits| macro constructs the frame for a particular +% register field and sets the starting and ending bit positions +% within that frame. +% \begin{macrocode} +\newcommand{\typesetRegBits}[1]{% + \ifthenelse{#1 > 1}% + {\framebox[\regFieldLen][c]% + {\regBitSize \rule[-1\regResetDepth]{0pt}{\regResetHeight}% + \regBitFamily\arabic{upperbit} \hfill \arabic{lowerbit}}}% + {\framebox[\regFieldLen][c]% + {\regBitSize \rule[-1\regResetDepth]{0pt}{\regResetHeight}% + \regBitFamily\arabic{lowerbit}}}% +} +% \end{macrocode} +% This macro constructs a frame, below the bit position frame, +% displaying the reset (or some other) value for a register field. +% \begin{macrocode} +\newcommand{\typesetRegReset}[1]{% + % Typeset reset value in a framebox + \makebox[0pt][l]{\raisebox{-1\regResetDrop}{\framebox[\regFieldLen][c]% + % Place an invisible rule to control the box + % surrounding the reset field + {\regResetSize \rule[-1\regResetDepth]{0pt}{\regResetHeight}\regSpread{#1}}}}% +} +% \end{macrocode} +% +% +% +% \begin{macro}{\regfieldNoColor} +% The macros below are the user interface to the register drawing +% routines. The first of these, |\regfieldNoColor| takes four arguments: +% the field name, field length (in bits), the starting bit number, +% and the field's reset value. This is the version of the macro that +% does not make any use of |\colorbox|. +% \end{macro} +% \begin{macrocode} +\newcommand{\regfieldNoColor}[4]{% + % Compute overall field length + \setRegLengths% + \setlength{\regFieldLen}{#2\regFieldLen + \fboxrule}% + % Figure out bit positions + \setcounter{lowerbit}{#3}% + \setcounter{upperbit}{#3 + #2 - 1}% + \regMakeFieldName{#1}% + % Figure out how far over to place label, accounting for height + \setlength{\regLabelAdjust}{0.5\regFieldLen - 0.707107\ht\Label}% + % Now, rotate and type the label + \regRotateFieldName% + \typesetRegReset{#4}% + % Typeset bit positions in a framebox + \typesetRegBits{#2}% + \hspace{-1\fboxrule}% +} +% \end{macrocode} +% +% +% +% \begin{macro}{\regfieldbNoColor} +% The |\regfieldbNoColor| macro can be used to construct a register diagram +% without reset values. It's parameters are thus the same +% as for |\regfieldNoColor| with the omission of reset value. +% \end{macro} +% \begin{macrocode} +\newcommand{\regfieldbNoColor}[3]{% + % Compute overall field length + \setRegLengths% + \setlength{\regFieldLen}{#2\regFieldLen + \fboxrule}% + % Figure out bit positions + \setcounter{lowerbit}{#3}% + \setcounter{upperbit}{#3 + #2 - 1}% + % Create box to hold label + \regMakeFieldName{#1}% + % Figure out how far over to place label, accounting for height + \setlength{\regLabelAdjust}{0.5\regFieldLen - 0.707107\ht\Label}% + % Now, rotate and typeset the label + \regRotateFieldName% + % Typeset bit positions + \typesetRegBits{#2}% + \hspace{-1\fboxrule}% +} +% \end{macrocode} +% +% \begin{macro}{\typesetRegColorBits} +% \begin{macro}{\typesetRegColorReset} +% \begin{macro}{\regfieldColor} +% \begin{macro}{\regfieldbColor} +% Now, we define versions of the same macros that make use of |\colorbox|, taking +% an additional argument that specifies the fill color to use. +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macrocode} +\ifthenelse{\boolean{RegisterColors}}{% +\newcommand{\typesetRegColorBits}[2]{% + \ifthenelse{#2 > 1}% + {\setlength\fboxsep{0pt}% + \colorbox{#1}{% + \framebox[\regFieldLen][c]% + {\regBitSize \rule[-1\regResetDepth - \regFboxSep]{0pt}% + {\regResetHeight + 2\regFboxSep}% + \regBitFamily\hspace{\regFboxSep}% +\arabic{upperbit} \hfill \arabic{lowerbit}% +\hspace{\regFboxSep}}}}% + {\setlength\fboxsep{0pt}% + \colorbox{#1}{% + \framebox[\regFieldLen][c]% + {\regBitSize \rule[-1\regResetDepth - \regFboxSep]{0pt}% + {\regResetHeight + 2\regFboxSep}% + \regBitFamily\arabic{lowerbit}}}}% + \setlength\fboxsep{\regFboxSep}% +} +\newcommand{\typesetRegColorReset}[2]{% + % Typeset reset value in a framebox + \makebox[0pt][l]{\raisebox{-1\regRsvdDrop}{% + \setlength\fboxsep{0pt}% + \colorbox{#1}{\framebox[\regFieldLen][c]% + % Place an invisible rule to control the box surrounding the reset field + {\regResetSize \rule[-1\regResetDepth]{0pt}{\regRsvdHeight}% + \raisebox{\regFboxSep}{\makebox[\regFieldLen]% + {\hspace{\regFboxSep}\regSpread{#2}\hspace{\regFboxSep}}}}}% +}}} +\newcommand{\regfieldColor}[5]{% + % Compute overall field length + \setRegLengths% + \setlength{\regFieldLen}{#3\regFieldLen + \fboxrule}% + % Figure out bit positions + \setcounter{lowerbit}{#4}% + \setcounter{upperbit}{#4 + #3 - 1}% + \regMakeFieldName{#2}% + % Figure out how far over to place label, accounting for height + \setlength{\regLabelAdjust}{0.5\regFieldLen - 0.707107\ht\Label}% + % Now, rotate and type the label + \regRotateFieldName% + \typesetRegColorReset{#1}{#5}% + % Typeset bit positions in a framebox + \typesetRegColorBits{#1}{#3}% + \hspace{-1\fboxrule}% +} +\newcommand{\regfieldbColor}[4]{% + % Compute overall field length + \setRegLengths% + \setlength{\regFieldLen}{#3\regFieldLen + \fboxrule}% + % Figure out bit positions + \setcounter{lowerbit}{#4}% + \setcounter{upperbit}{#4 + #3 - 1}% + % Create box to hold label + \regMakeFieldName{#2}% + % Figure out how far over to place label, accounting for height + \setlength{\regLabelAdjust}{0.5\regFieldLen - 0.707107\ht\Label}% + % Now, rotate and typeset the label + \regRotateFieldName% + % Typeset bit positions + \typesetRegColorBits{#1}{#3}% + \hspace{-1\fboxrule}% +} +}{} +% \end{macrocode} +% +% +% \begin{macro}{\regfield} +% \begin{macro}{\regfieldb} +% Next, provide definitions for the |\regfield| and |\regfieldb| macros that are +% intended for direct use within the register diagrams. These commands just check +% for the presence of a non-empty optional argument and, based upon that, decide +% whether to invoke the Color or NoColor variants of the typesetting macros. +% \end{macro} +% \end{macro} +% \begin{macrocode} +\ifthenelse{\boolean{RegisterColors}}{ + \newcommand{\regfield}[5][]{% + \ifthenelse{\equal{#1}{}}{% + \regfieldNoColor{#2}{#3}{#4}{#5}}% + {\regfieldColor{#1}{#2}{#3}{#4}{#5}}} + \newcommand{\regfieldb}[4][]{% + \ifthenelse{\equal{#1}{}}{% + \regfieldbNoColor{#2}{#3}{#4}}% + {\regfieldbColor{#1}{#2}{#3}{#4}}} +}{ + \newcommand{\regfield}[5][]{% + \regfieldNoColor{#2}{#3}{#4}{#5}}% + \newcommand{\regfieldb}[4][]{% + \regfieldbNoColor{#2}{#3}{#4}}% +} +% \end{macrocode} +% +% \begin{macro}{\regbits} +% The |\regbits| macro typesets a register field without +% showing bit positions. As such, it only takes three +% parameters: field name, field bit length, and field value. +% \end{macro} +% \begin{macrocode} +\newcommand{\regbits}[3]{% + % Compute overall field length + \setRegLengths% + \setlength{\regFieldLen}{#2\regFieldLen + \fboxrule}% + % Figure out bit positions + \setcounter{lowerbit}{#3}% + \setcounter{upperbit}{#3 + #2 - 1}% + % Create box to hold label + \regMakeFieldName{#1}% + % Figure out how far over to place label, accounting for height + \setlength{\regLabelAdjust}{0.5\regFieldLen - 0.707107\ht\Label}% + % Now, rotate and typeset the label + \regRotateFieldName% + % Typeset field value + \framebox[\regFieldLen][c]% + {\tiny\regSpread{#3}}% + \hspace{-1\fboxrule}% +} +% \end{macrocode} +% +% +% +% \begin{macro}{\regspace} +% \begin{macro}{\reglabel} +% \begin{macro}{\reglabelb} +% Finally, define some additional utility macros. An invisible box +% with the same width as a specified number of bits is typeset by +% |\regspace|. It takes as its sole parameter the desired +% bitwidth. The |\reglabel| macro typesets the label for the reset +% field in register diagrams. Finally, |\reglabelb| performs the +% same function, but without any drop. +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macrocode} +\newcommand{\regspace}[1]{% + % Compute overall field length + \setRegLengths% + \setlength{\regFieldLen}{#1\regFieldLen + \fboxrule}% + \makebox[\regFieldLen]{}% +} + +\newcommand{\reglabel}[1]{% + \settowidth{\regFieldLen}{\regLabelSize \regResetName}% + \setlength{\regResetDrop}{\regResetDrop + 0.5\fboxsep}% + $\,$\raisebox{-1\regResetDrop}{\makebox[\regFieldLen][l]% + {\regLabelSize\regBitFamily #1}}% +} + +\newcommand{\reglabelb}[1]{% + \settowidth{\regFieldLen}{\regLabelSize \regResetName}% + $\,$\raisebox{-0.5\fboxsep}{\makebox[\regFieldLen][l]% + {\regLabelSize\regBitFamily #1}}% +} +% \end{macrocode} +% +% +% +% \subsubsection{Hyperref Interface} \label{sec:hyperref} +% +% This code helps with the hyperlinks to register floats +% when producing linked PDF. +% \begin{macrocode} +\ifthenelse{\boolean{RegisterHyperref}}{% + % Define a counter for the hyperref package. Otherwise, + % the hyperlinks to registers don't work correctly + \@namedef{theHRegfloat}{\theRegfloat} + + % Define a bookmark level for Regfloats (for hyperref package) + \def\toclevel@Regfloat{0} +}{} +% \end{macrocode} +% +% +% +% +% \subsubsection{List of Registers} \label{sec:list} +% +% The code below redefines what the |float| package specifies +% in order to provide a hook for changing the format of the +% ToC line for registers. +% \begin{macrocode} +\newcommand{\listofregisters}{% + \@ifundefined{ext@Regfloat}{\float@error{Regfloat}}{% + \@ifundefined{chapter}{\def\@tempa{\section*}}% + {\def\@tempa{\chapter*}}% + \@tempa{\regListName\@mkboth{\uppercase{\regListName}}% + {\uppercase{\regListName}}}% + \addcontentsline{toc}{chapter}{\regListName}% + \@starttoc{\@nameuse{ext@Regfloat}}}} +\newcommand\l@Regfloat{\@dottedtocline{1}{1.5em}{2.3em}} +% \end{macrocode} +% +% +% +% The |\chapter| command, if present, is also redefined in order +% to get identical chapter-related spacing in the list of registers +% as appears in the LoF and LoT. Kjetil Oftedal provided a fix +% wherein we test that @mainmatter is defined prior to using it. +% \begin{macrocode} +\@ifundefined{@mainmatter}{\newif\if@mainmatter \@mainmattertrue}{} +\@ifundefined{chapter}{} +{% Adjust chapter definition slightly for Regfloats +\def\@chapter[#1]#2{\ifnum \c@secnumdepth >\m@ne + \if@mainmatter + \refstepcounter{chapter}% + \typeout{\@chapapp\space\thechapter.}% + \addcontentsline{toc}{chapter}% + {\protect\numberline{\thechapter}#1}% + \else + \addcontentsline{toc}{chapter}{#1}% + \fi + \else + \addcontentsline{toc}{chapter}{#1}% + \fi + \chaptermark{#1}% + \addtocontents{lof}{\protect\addvspace{10\p@}}% + \addtocontents{lot}{\protect\addvspace{10\p@}}% + \addtocontents{rdf}{\protect\addvspace{10\p@}}% --- Add space --- + \if@twocolumn + \@topnewpage[\@makechapterhead{#2}]% + \else + \@makechapterhead{#2}% + \@afterheading + \fi} +} +% \end{macrocode} +% +% +% +% \subsection{TR flag macros} \label{sec:TRflags}% +% +% Define a mechanism for including TR flags in register descriptions, +% as well as possibly in the main body of the text. One cannot just +% use |\marginpar|'s within a register description, since they are +% typically part of a register float. \LaTeX{}'s |\marginpar| command is +% \emph{also} considered a float, so they cannot be nested. +% +% So, we resort to using some lower level \LaTeX{}. This certainly +% isn't the most elegant way to get the flags, but I think it will +% work for the majority of cases. +% +% The |\TR{x}| command is intended to be placed at the start of +% a register field description, so that the alignment is +% obvious on the page. To also get decent alignment in +% main body text, it is necessary to have a second definition. +% So, we'll see these commands get redefined inside regdesc, +% below. +% +% The TR flags also decide which page they are on by placing +% labels and testing the resulting pagenumber. This enables +% the flags to be placed in the outer margin in two-sided +% documents. +% +% \begin{macro}{\TRfamily} +% \begin{macro}{\TRwidth} +% The font family used for the TR flags can be controlled via +% |\TRfamily|. The width available for TR flags is controlled +% by |\TRwidth|, which by default is set to |\marginparwidth|. +% Setting the width may be important if you are using the +% |TRboxed| package option. +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +% Define a pageref which will work with \isodd +\newcommand\@GetTRSecondParam{} +\long\def\@GetTRSecondParam#1#2#3\@nil{#2} +\newcommand*{\GetTRPageRef}[1]{% + \expandafter\expandafter\expandafter\@GetTRSecondParam + \csname r@#1\endcsname + 0% dummy, if the reference is undefined + \@nil +} + +\newcommand{\TRfamily}{\sffamily} +\newcounter{T@peReleaseTag} +\newlength{\TRwidth} +\setlength{\TRwidth}{\marginparwidth} +\newlength{\T@peReleaseDepth} + +% Internal command to form the actual TR margin note. +\newcommand{\TRwriteout}[1]{% + \makebox[\TRwidth][c]{% + \raisebox{\T@peReleaseDepth}{% + \ifthenelse{\boolean{RegisterTRBoxed}}% + {\fbox{\TRfamily #1}}% + {\TRfamily #1}}}% +} + +% Internal command to typeset a TR flag in the right margin +\newcommand{\TRrightlabel}[1]{% + % Place a strut in order to set line depth + \mbox{}\strut\settodepth{\T@peReleaseDepth}{\strut}% + \vadjust{\hspace{\textwidth}\hspace{\marginparsep}% + \smash{\rlap{\TRwriteout{#1}}}}} + +% Internal command to typeset a TR flag in the left margin +\ifthenelse{\boolean{@twoside}}{ + % Two-sided document + \newcommand{\TRleftlabel}[1]{% + % Place a strut in order to set line depth + \mbox{}\strut\settodepth{\T@peReleaseDepth}{\strut}% + \vadjust{\smash{\llap{\TRwriteout{#1}}\kern\marginparsep}}} +}{ + % Otherwise, the command is the same as rightlabel + \newcommand{\TRleftlabel}[1]{% + \TRrightlabel{#1}} +} +% \end{macrocode} +% +% +% \begin{macro}{\TR} +% Finally, the user-level command is simply |\TR|. +% \end{macro} +% \begin{macrocode} +\ifthenelse{\boolean{RegisterTRFlags}}{ +\newcommand{\TR}[1]{% + \stepcounter{T@peReleaseTag}% + \label{TapeReleaseTag-\theT@peReleaseTag}% + \ifthenelse{\isodd{\GetTRPageRef{TapeReleaseTag-\theT@peReleaseTag}}}% + {\TRrightlabel{TR\hspace{1pt}#1}}% + {\TRleftlabel{TR\hspace{1pt}#1}}% +}} +{\newcommand{\TR}[1]{}} +% \end{macrocode} +% +% \par +% Enjoy! Happy documenting. +% +% +% \Finale +% +\endinput + +%% \CharacterTable +%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +%% Digits \0\1\2\3\4\5\6\7\8\9 +%% Exclamation \! Double quote \" Hash (number) \# +%% Dollar \$ Percent \% Ampersand \& +%% Acute accent \' Left paren \( Right paren \) +%% Asterisk \* Plus \+ Comma \, +%% Minus \- Point \. Solidus \/ +%% Colon \: Semicolon \; Less than \< +%% Equals \= Greater than \> Question mark \? +%% Commercial at \@ Left bracket \[ Backslash \\ +%% Right bracket \] Circumflex \^ Underscore \_ +%% Grave accent \` Left brace \{ Vertical bar \| +%% Right brace \} Tilde \~} + +%%% Local Variables: +%%% mode: LaTeX +%%% End: + diff --git a/macros/latex/contrib/register/register.ins b/macros/latex/contrib/register/register.ins new file mode 100644 index 0000000000..529742dbdb --- /dev/null +++ b/macros/latex/contrib/register/register.ins @@ -0,0 +1,62 @@ +%% +%% register.ins +%% +%% This program is provided under the terms of the +%% LaTeX Project Public License distributed from CTAN +%% archives in directory macros/latex/base/lppl.txt. +%% +%% This package consists of register.dtx, register.ins, reg_list.pl, +%% and Reg_macro.pm, as well as the accompanying register.pdf and +%% README documentation. +%% +%% This file will generate fast loadable files and documentation +%% driver files from the doc files in this package when run through +%% LaTeX or TeX. +%% +%% Author: Matthew Lovell (lovells@gmail.com) +%% +%% --------------- start of docstrip commands ------------------ +%% +\def\batchfile{register.ins} +\input docstrip +\def\SimplePackage#1{\generateFile{#1.sty}{t}{\from{#1.dtx}{package}}} +\preamble +Hardware register diagrams with field descriptions. + +This package may be distributed and/or modified under the conditions +of the LaTeX Project Public License, either version 1.3 of this +license or (at your option) any later version. The latest version of +this license is in: + + http://www.latex-project.org/lppl.txt + +and version 1.3c or later is part of all distributions of LaTeX version +2006/05/20 or later. + +Author: Matthew Lovell (lovells@gmail.com) + +\endpreamble + +\Msg{*** Generating the LaTeX2e package file ***} +\SimplePackage{register} + +\Msg{***********************************************************} +\Msg{*} +\Msg{* To finish the installation you have to move the following} +\Msg{* file into a directory searched by LaTeX. See the FAQ on} +\Msg{* CTAN at /help/uk-tex-faq for more on this.} +\Msg{*} +\Msg{* \space\space register.sty} +\Msg{*} +\Msg{* To produce the documented source run the file ending with} +\Msg{* `.dtx' through LaTeX.} +\Msg{*} +\Msg{* Happy TeXing} +\Msg{***********************************************************} + +\endinput + + +%%% Local Variables: +%%% mode: LaTeX +%%% End: diff --git a/macros/latex/contrib/register/register.pdf b/macros/latex/contrib/register/register.pdf new file mode 100644 index 0000000000..1a0ad7f95c Binary files /dev/null and b/macros/latex/contrib/register/register.pdf differ -- cgit v1.2.3